Fri Aug 24 02:28:10 2007

Asterisk developer's documentation


rtp.c File Reference

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

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"

Include dependency graph for rtp.c:

Go to the source code of this file.

Data Structures

struct  __attribute__
struct  ast_rtcp
 Structure defining an RTCP session. More...
struct  ast_rtp
 RTP session description. More...
struct  rtpPayloadType
 Structure representing a RTP session.The value of each payload format mapping:. More...
struct  stun_addr
struct  stun_attr
struct  stun_header
struct  stun_state

Defines

#define DEFAULT_DTMF_TIMEOUT   3000
#define FLAG_3389_WARNING   (1 << 0)
#define FLAG_CALLBACK_MODE   (1 << 6)
#define FLAG_DTMF_COMPENSATE   (1 << 7)
#define FLAG_HAS_DTMF   (1 << 3)
#define FLAG_HAS_STUN   (1 << 8)
#define FLAG_NAT_ACTIVE   (3 << 1)
#define FLAG_NAT_INACTIVE   (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
#define FLAG_P2P_NEED_DTMF   (1 << 5)
#define FLAG_P2P_SENT_MARK   (1 << 4)
#define MAX_TIMESTAMP_SKEW   640
#define RTCP_DEFAULT_INTERVALMS   5000
#define RTCP_MAX_INTERVALMS   60000
#define RTCP_MIN_INTERVALMS   500
#define RTCP_PT_APP   204
#define RTCP_PT_BYE   203
#define RTCP_PT_FUR   192
#define RTCP_PT_RR   201
#define RTCP_PT_SDES   202
#define RTCP_PT_SR   200
#define RTP_MTU   1200
#define RTP_SEQ_MOD   (1<<16)
#define STUN_ACCEPT   (1)
#define STUN_BINDERR   0x0111
#define STUN_BINDREQ   0x0001
#define STUN_BINDRESP   0x0101
#define STUN_CHANGE_REQUEST   0x0003
#define STUN_CHANGED_ADDRESS   0x0005
#define STUN_ERROR_CODE   0x0009
#define STUN_IGNORE   (0)
#define STUN_MAPPED_ADDRESS   0x0001
#define STUN_MESSAGE_INTEGRITY   0x0008
#define STUN_PASSWORD   0x0007
#define STUN_REFLECTED_FROM   0x000b
#define STUN_RESPONSE_ADDRESS   0x0002
#define STUN_SECERR   0x0112
#define STUN_SECREQ   0x0002
#define STUN_SECRESP   0x0102
#define STUN_SOURCE_ADDRESS   0x0004
#define STUN_UNKNOWN_ATTRIBUTES   0x000a
#define STUN_USERNAME   0x0006

Functions

static void append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
static void append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
static AST_LIST_HEAD_STATIC (protos, ast_rtp_protocol)
 List of current sessions.
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
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.
static int ast_rtcp_write (void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (void *data)
 Send RTCP recipient's report.
static int ast_rtcp_write_sr (void *data)
 Send RTCP sender's report.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
enum ast_bridge_result ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
int ast_rtp_codec_getformat (int pt)
ast_codec_prefast_rtp_codec_getpref (struct ast_rtp *rtp)
int ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs)
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_early_bridge (struct ast_channel *dest, struct ast_channel *src)
 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, const int isAstFormat, const 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 (const int isAstFormat, const int code, enum ast_rtp_options options)
 Mapping an Asterisk code into a MIME subtype (string):.
rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
 Mapping between RTP payload format codes and Asterisk codes:.
int ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media)
ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
void ast_rtp_new_init (struct ast_rtp *rtp)
 Initialize a new RTP structure.
ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
 Initializate a RTP session using an in_addr structure.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register interface to channel driver.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister interface to channel driver.
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.
static int ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec)
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.
static int ast_rtp_senddigit_continuation (struct ast_rtp *rtp)
 Send continuation frame for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
void ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
static enum ast_bridge_result bridge_native_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for true native bridge (reinvite).
static enum ast_bridge_result bridge_p2p_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for partial native bridge (packet2packet).
static int bridge_p2p_rtp_write (struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen)
 Perform a Packet2Packet RTP write.
static void calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
static struct ast_rtp_protocolget_proto (struct ast_channel *chan)
 Get channel driver interface structure.
static int p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
 Helper function to switch a channel and RTP stream out of callback mode.
static int p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
 P2P RTP Callback.
static void p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1)
 Helper function that sets what an RTP structure is bridged to.
static struct ast_frameprocess_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len)
static struct ast_frameprocess_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp)
 Process RTP DTMF and events according to RFC 2833.
static struct ast_frameprocess_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len)
 Process Comfort Noise RTP.
static int rtcp_debug_test_addr (struct sockaddr_in *addr)
static int rtcp_do_debug (int fd, int argc, char *argv[])
static int rtcp_do_debug_deprecated (int fd, int argc, char *argv[])
static int rtcp_do_debug_ip (int fd, int argc, char *argv[])
static int rtcp_do_debug_ip_deprecated (int fd, int argc, char *argv[])
static int rtcp_do_stats (int fd, int argc, char *argv[])
static int rtcp_do_stats_deprecated (int fd, int argc, char *argv[])
static int rtcp_no_debug (int fd, int argc, char *argv[])
static int rtcp_no_debug_deprecated (int fd, int argc, char *argv[])
static int rtcp_no_stats (int fd, int argc, char *argv[])
static int rtcp_no_stats_deprecated (int fd, int argc, char *argv[])
static int rtp_debug_test_addr (struct sockaddr_in *addr)
static int rtp_do_debug (int fd, int argc, char *argv[])
static int rtp_do_debug_ip (int fd, int argc, char *argv[])
static int rtp_no_debug (int fd, int argc, char *argv[])
static int rtp_socket (void)
static int rtpread (int *id, int fd, short events, void *cbdata)
static struct ast_framesend_dtmf (struct ast_rtp *rtp, enum ast_frame_type type)
static const char * stun_attr2str (int msg)
static int stun_do_debug (int fd, int argc, char *argv[])
static int stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len)
static const char * stun_msg2str (int msg)
static int stun_no_debug (int fd, int argc, char *argv[])
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
static void stun_req_id (struct stun_header *req)
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)

Variables

static struct ast_cli_entry cli_rtp []
static struct ast_cli_entry cli_rtp_no_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated
static struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated
static struct ast_cli_entry cli_rtp_rtcp_stats_deprecated
static struct ast_cli_entry cli_stun_no_debug_deprecated
static char debug_usage []
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
struct {
   rtpPayloadType   payloadType
   char *   subtype
   char *   type
mimeTypes []
static char no_debug_usage []
stun_addr packed
stun_attr packed
stun_header packed
static char rtcp_debug_usage []
static char rtcp_no_debug_usage []
static char rtcp_no_stats_usage []
static char rtcp_stats_usage []
static int rtcpdebug
static struct sockaddr_in rtcpdebugaddr
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static int rtcpstats
static int rtpdebug
static struct sockaddr_in rtpdebugaddr
static int rtpend
static int rtpstart
static struct rtpPayloadType static_RTP_PT [MAX_RTP_PT]
static char stun_debug_usage []
static char stun_no_debug_usage []
static int stundebug


Detailed Description

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

Author:
Mark Spencer <markster@digium.com>
Note:
RTP is defined in RFC 3550.

Definition in file rtp.c.


Define Documentation

#define DEFAULT_DTMF_TIMEOUT   3000

samples

Definition at line 76 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 186 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 193 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 194 of file rtp.c.

Referenced by ast_rtp_bridge(), ast_rtp_setdtmfcompensate(), process_rfc2833(), and send_dtmf().

#define FLAG_HAS_DTMF   (1 << 3)

Definition at line 190 of file rtp.c.

Referenced by ast_rtp_bridge(), ast_rtp_new_init(), and ast_rtp_setdtmf().

#define FLAG_HAS_STUN   (1 << 8)

Definition at line 195 of file rtp.c.

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 187 of file rtp.c.

Referenced by ast_rtp_early_bridge(), ast_rtp_getnat(), ast_rtp_make_compatible(), ast_rtp_raw_write(), ast_rtp_read(), bridge_native_loop(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 188 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 189 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_P2P_NEED_DTMF   (1 << 5)

Definition at line 192 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 191 of file rtp.c.

Referenced by ast_rtp_stop(), bridge_p2p_loop(), and bridge_p2p_rtp_write().

#define MAX_TIMESTAMP_SKEW   640

Definition at line 60 of file rtp.c.

Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp().

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 63 of file rtp.c.

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 65 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 64 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 72 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 71 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

Definition at line 67 of file rtp.c.

Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr().

#define RTCP_PT_RR   201

Definition at line 69 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

Definition at line 70 of file rtp.c.

Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr().

#define RTCP_PT_SR   200

Definition at line 68 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 74 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 62 of file rtp.c.

Referenced by ast_rtp_read().

#define STUN_ACCEPT   (1)

Definition at line 259 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 263 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 261 of file rtp.c.

Referenced by ast_rtp_stun_request(), stun_handle_packet(), and stun_msg2str().

#define STUN_BINDRESP   0x0101

Definition at line 262 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 258 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 268 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 269 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 264 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 273 of file rtp.c.

Referenced by ast_rtp_stun_request(), stun_attr2str(), stun_handle_packet(), and stun_process_attr().


Function Documentation

static void append_attr_address ( struct stun_attr **  attr,
int  attrval,
struct sockaddr_in *  sin,
int *  len,
int *  left 
) [static]

Definition at line 366 of file rtp.c.

References stun_addr::addr.

Referenced by stun_handle_packet().

00367 {
00368    int size = sizeof(**attr) + 8;
00369    struct stun_addr *addr;
00370    if (*left > size) {
00371       (*attr)->attr = htons(attrval);
00372       (*attr)->len = htons(8);
00373       addr = (struct stun_addr *)((*attr)->value);
00374       addr->unused = 0;
00375       addr->family = 0x01;
00376       addr->port = sin->sin_port;
00377       addr->addr = sin->sin_addr.s_addr;
00378       (*attr) = (struct stun_attr *)((*attr)->value + 8);
00379       *len += size;
00380       *left -= size;
00381    }
00382 }

static void append_attr_string ( struct stun_attr **  attr,
int  attrval,
const char *  s,
int *  len,
int *  left 
) [static]

Definition at line 353 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

00354 {
00355    int size = sizeof(**attr) + strlen(s);
00356    if (*left > size) {
00357       (*attr)->attr = htons(attrval);
00358       (*attr)->len = htons(strlen(s));
00359       memcpy((*attr)->value, s, strlen(s));
00360       (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
00361       *len += size;
00362       *left -= size;
00363    }
00364 }

static AST_LIST_HEAD_STATIC ( protos  ,
ast_rtp_protocol   
) [static]

List of current sessions.

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 524 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00525 {
00526    unsigned int interval;
00527    /*! \todo XXX Do a more reasonable calculation on this one
00528    * Look in RFC 3550 Section A.7 for an example*/
00529    interval = rtcpinterval;
00530    return interval;
00531 }

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 517 of file rtp.c.

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

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1849 of file rtp.c.

References ast_calloc, ast_log(), free, LOG_WARNING, rtp_socket(), and ast_rtcp::s.

Referenced by ast_rtp_new_with_bindaddr().

01850 {
01851    struct ast_rtcp *rtcp;
01852 
01853    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01854       return NULL;
01855    rtcp->s = rtp_socket();
01856    rtcp->us.sin_family = AF_INET;
01857    rtcp->them.sin_family = AF_INET;
01858 
01859    if (rtcp->s < 0) {
01860       free(rtcp);
01861       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01862       return NULL;
01863    }
01864 
01865    return rtcp;
01866 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 822 of file rtp.c.

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

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

00823 {
00824    socklen_t len;
00825    int position, i, packetwords;
00826    int res;
00827    struct sockaddr_in sin;
00828    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
00829    unsigned int *rtcpheader;
00830    int pt;
00831    struct timeval now;
00832    unsigned int length;
00833    int rc;
00834    double rttsec;
00835    uint64_t rtt = 0;
00836    unsigned int dlsr;
00837    unsigned int lsr;
00838    unsigned int msw;
00839    unsigned int lsw;
00840    unsigned int comp;
00841    struct ast_frame *f = &ast_null_frame;
00842    
00843    if (!rtp || !rtp->rtcp)
00844       return &ast_null_frame;
00845 
00846    len = sizeof(sin);
00847    
00848    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
00849                0, (struct sockaddr *)&sin, &len);
00850    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
00851    
00852    if (res < 0) {
00853       if (errno == EBADF)
00854          CRASH;
00855       if (errno != EAGAIN) {
00856          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
00857          return NULL;
00858       }
00859       return &ast_null_frame;
00860    }
00861 
00862    packetwords = res / 4;
00863    
00864    if (rtp->nat) {
00865       /* Send to whoever sent to us */
00866       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00867           (rtp->rtcp->them.sin_port != sin.sin_port)) {
00868          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00869          if (option_debug || rtpdebug)
00870             ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00871       }
00872    }
00873 
00874    if (option_debug)
00875       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00876 
00877    /* Process a compound packet */
00878    position = 0;
00879    while (position < packetwords) {
00880       i = position;
00881       length = ntohl(rtcpheader[i]);
00882       pt = (length & 0xff0000) >> 16;
00883       rc = (length & 0x1f000000) >> 24;
00884       length &= 0xffff;
00885     
00886       if ((i + length) > packetwords) {
00887          ast_log(LOG_WARNING, "RTCP Read too short\n");
00888          return &ast_null_frame;
00889       }
00890       
00891       if (rtcp_debug_test_addr(&sin)) {
00892          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00893          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
00894          ast_verbose("Reception reports: %d\n", rc);
00895          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
00896       }
00897     
00898       i += 2; /* Advance past header and ssrc */
00899       
00900       switch (pt) {
00901       case RTCP_PT_SR:
00902          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
00903          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
00904          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
00905          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
00906     
00907          if (rtcp_debug_test_addr(&sin)) {
00908             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
00909             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
00910             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
00911          }
00912          i += 5;
00913          if (rc < 1)
00914             break;
00915          /* Intentional fall through */
00916       case RTCP_PT_RR:
00917          /* Don't handle multiple reception reports (rc > 1) yet */
00918          /* Calculate RTT per RFC */
00919          gettimeofday(&now, NULL);
00920          timeval2ntp(now, &msw, &lsw);
00921          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
00922             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
00923             lsr = ntohl(rtcpheader[i + 4]);
00924             dlsr = ntohl(rtcpheader[i + 5]);
00925             rtt = comp - lsr - dlsr;
00926 
00927             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
00928                sess->ee_delay = (eedelay * 1000) / 65536; */
00929             if (rtt < 4294) {
00930                 rtt = (rtt * 1000000) >> 16;
00931             } else {
00932                 rtt = (rtt * 1000) >> 16;
00933                 rtt *= 1000;
00934             }
00935             rtt = rtt / 1000.;
00936             rttsec = rtt / 1000.;
00937 
00938             if (comp - dlsr >= lsr) {
00939                rtp->rtcp->accumulated_transit += rttsec;
00940                rtp->rtcp->rtt = rttsec;
00941                if (rtp->rtcp->maxrtt<rttsec)
00942                   rtp->rtcp->maxrtt = rttsec;
00943                if (rtp->rtcp->minrtt>rttsec)
00944                   rtp->rtcp->minrtt = rttsec;
00945             } else if (rtcp_debug_test_addr(&sin)) {
00946                ast_verbose("Internal RTCP NTP clock skew detected: "
00947                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
00948                         "diff=%d\n",
00949                         lsr, comp, dlsr, dlsr / 65536,
00950                         (dlsr % 65536) * 1000 / 65536,
00951                         dlsr - (comp - lsr));
00952             }
00953          }
00954 
00955          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
00956          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
00957          if (rtcp_debug_test_addr(&sin)) {
00958             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
00959             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
00960             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
00961             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
00962             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
00963             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
00964             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
00965             if (rtt)
00966                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
00967          }
00968          break;
00969       case RTCP_PT_FUR:
00970          if (rtcp_debug_test_addr(&sin))
00971             ast_verbose("Received an RTCP Fast Update Request\n");
00972          rtp->f.frametype = AST_FRAME_CONTROL;
00973          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
00974          rtp->f.datalen = 0;
00975          rtp->f.samples = 0;
00976          rtp->f.mallocd = 0;
00977          rtp->f.src = "RTP";
00978          f = &rtp->f;
00979          break;
00980       case RTCP_PT_SDES:
00981          if (rtcp_debug_test_addr(&sin))
00982             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00983          break;
00984       case RTCP_PT_BYE:
00985          if (rtcp_debug_test_addr(&sin))
00986             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00987          break;
00988       default:
00989          if (option_debug)
00990             ast_log(LOG_DEBUG, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00991          break;
00992       }
00993       position += (length + 1);
00994    }
00995          
00996    return f;
00997 }

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

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

02315 {
02316    struct ast_rtp *rtp = data;
02317    int res;
02318 
02319    rtp->rtcp->sendfur = 1;
02320    res = ast_rtcp_write(data);
02321    
02322    return res;
02323 }

static int ast_rtcp_write ( void *  data  )  [static]

Write and RTCP packet to the far end.

Note:
Decide if we are going to send an SR (with Reception Block) or RR RR is sent if we have not sent any rtp packets in the previous interval

Definition at line 2539 of file rtp.c.

References ast_rtcp_write_rr(), ast_rtcp_write_sr(), ast_rtcp::lastsrtxcount, ast_rtp::rtcp, and ast_rtp::txcount.

Referenced by ast_rtcp_send_h261fur(), ast_rtp_raw_write(), and ast_rtp_read().

02540 {
02541    struct ast_rtp *rtp = data;
02542    int res;
02543    
02544    if (!rtp || !rtp->rtcp)
02545       return 0;
02546 
02547    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02548       res = ast_rtcp_write_sr(data);
02549    else
02550       res = ast_rtcp_write_rr(data);
02551    
02552    return res;
02553 }

static int ast_rtcp_write_rr ( void *  data  )  [static]

Send RTCP recipient's report.

Note:
Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos it can change mid call, and SDES can't)

Definition at line 2440 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, len, LOG_ERROR, ast_rtcp::received_prior, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, and ast_rtp::themssrc.

Referenced by ast_rtcp_write().

02441 {
02442    struct ast_rtp *rtp = data;
02443    int res;
02444    int len = 32;
02445    unsigned int lost;
02446    unsigned int extended;
02447    unsigned int expected;
02448    unsigned int expected_interval;
02449    unsigned int received_interval;
02450    int lost_interval;
02451    struct timeval now;
02452    unsigned int *rtcpheader;
02453    char bdata[1024];
02454    struct timeval dlsr;
02455    int fraction;
02456 
02457    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
02458       return 0;
02459      
02460    if (!rtp->rtcp->them.sin_addr.s_addr) {
02461       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
02462       if (rtp->rtcp->schedid > 0)
02463          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02464       rtp->rtcp->schedid = -1;
02465       return 0;
02466    }
02467 
02468    extended = rtp->cycles + rtp->lastrxseqno;
02469    expected = extended - rtp->seedrxseqno + 1;
02470    lost = expected - rtp->rxcount;
02471    expected_interval = expected - rtp->rtcp->expected_prior;
02472    rtp->rtcp->expected_prior = expected;
02473    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02474    rtp->rtcp->received_prior = rtp->rxcount;
02475    lost_interval = expected_interval - received_interval;
02476    if (expected_interval == 0 || lost_interval <= 0)
02477       fraction = 0;
02478    else
02479       fraction = (lost_interval << 8) / expected_interval;
02480    gettimeofday(&now, NULL);
02481    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02482    rtcpheader = (unsigned int *)bdata;
02483    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
02484    rtcpheader[1] = htonl(rtp->ssrc);
02485    rtcpheader[2] = htonl(rtp->themssrc);
02486    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02487    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02488    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02489    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
02490    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02491 
02492    if (rtp->rtcp->sendfur) {
02493       rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
02494       rtcpheader[9] = htonl(rtp->ssrc);               /* Our SSRC */
02495       len += 8;
02496       rtp->rtcp->sendfur = 0;
02497    }
02498 
02499    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
02500    it can change mid call, and SDES can't) */
02501    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02502    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02503    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
02504    len += 12;
02505    
02506    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02507 
02508    if (res < 0) {
02509       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
02510       /* Remove the scheduler */
02511       if (rtp->rtcp->schedid > 0)
02512          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02513       rtp->rtcp->schedid = -1;
02514       return 0;
02515    }
02516 
02517    rtp->rtcp->rr_count++;
02518 
02519    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02520       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
02521          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 
02522          "  IA jitter: %.4f\n" 
02523          "  Their last SR: %u\n" 
02524          "  DLSR: %4.4f (sec)\n\n",
02525          ast_inet_ntoa(rtp->rtcp->them.sin_addr),
02526          ntohs(rtp->rtcp->them.sin_port),
02527          rtp->ssrc, rtp->themssrc, fraction, lost,
02528          rtp->rxjitter,
02529          rtp->rtcp->themrxlsr,
02530          (double)(ntohl(rtcpheader[7])/65536.0));
02531    }
02532 
02533    return res;
02534 }

static int ast_rtcp_write_sr ( void *  data  )  [static]

Send RTCP sender's report.

Definition at line 2326 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len, LOG_ERROR, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.

Referenced by ast_rtcp_write().

02327 {
02328    struct ast_rtp *rtp = data;
02329    int res;
02330    int len = 0;
02331    struct timeval now;
02332    unsigned int now_lsw;
02333    unsigned int now_msw;
02334    unsigned int *rtcpheader;
02335    unsigned int lost;
02336    unsigned int extended;
02337    unsigned int expected;
02338    unsigned int expected_interval;
02339    unsigned int received_interval;
02340    int lost_interval;
02341    int fraction;
02342    struct timeval dlsr;
02343    char bdata[512];
02344 
02345    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
02346    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
02347       return 0;
02348    
02349    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
02350       ast_verbose("RTCP SR transmission error, rtcp halted\n");
02351       if (rtp->rtcp->schedid > 0)
02352          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02353       rtp->rtcp->schedid = -1;
02354       return 0;
02355    }
02356 
02357    gettimeofday(&now, NULL);
02358    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
02359    rtcpheader = (unsigned int *)bdata;
02360    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
02361    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
02362    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
02363    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
02364    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
02365    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
02366    len += 28;
02367    
02368    extended = rtp->cycles + rtp->lastrxseqno;
02369    expected = extended - rtp->seedrxseqno + 1;
02370    if (rtp->rxcount > expected) 
02371       expected += rtp->rxcount - expected;
02372    lost = expected - rtp->rxcount;
02373    expected_interval = expected - rtp->rtcp->expected_prior;
02374    rtp->rtcp->expected_prior = expected;
02375    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02376    rtp->rtcp->received_prior = rtp->rxcount;
02377    lost_interval = expected_interval - received_interval;
02378    if (expected_interval == 0 || lost_interval <= 0)
02379       fraction = 0;
02380    else
02381       fraction = (lost_interval << 8) / expected_interval;
02382    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02383    rtcpheader[7] = htonl(rtp->themssrc);
02384    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02385    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02386    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02387    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
02388    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02389    len += 24;
02390    
02391    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
02392 
02393    if (rtp->rtcp->sendfur) {
02394       rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
02395       rtcpheader[14] = htonl(rtp->ssrc);               /* Our SSRC */
02396       len += 8;
02397       rtp->rtcp->sendfur = 0;
02398    }
02399    
02400    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 
02401    /* it can change mid call, and SDES can't) */
02402    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02403    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02404    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
02405    len += 12;
02406    
02407    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02408    if (res < 0) {
02409       ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
02410       if (rtp->rtcp->schedid > 0)
02411          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02412       rtp->rtcp->schedid = -1;
02413       return 0;
02414    }
02415    
02416    /* FIXME Don't need to get a new one */
02417    gettimeofday(&rtp->rtcp->txlsr, NULL);
02418    rtp->rtcp->sr_count++;
02419 
02420    rtp->rtcp->lastsrtxcount = rtp->txcount;  
02421    
02422    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02423       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
02424       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
02425       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
02426       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
02427       ast_verbose("  Sent packets: %u\n", rtp->txcount);
02428       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
02429       ast_verbose("  Report block:\n");
02430       ast_verbose("  Fraction lost: %u\n", fraction);
02431       ast_verbose("  Cumulative loss: %u\n", lost);
02432       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
02433       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
02434       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
02435    }
02436    return res;
02437 }

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

Referenced by process_sdp().

00398 {
00399    return sizeof(struct ast_rtp);
00400 }

enum ast_bridge_result ast_rtp_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
)

Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.

Definition at line 3222 of file rtp.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_codec_pref_getsize(), ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_DTMF_COMPENSATE, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, option_debug, option_verbose, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

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

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2697 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

02698 {
02699    if (pt < 0 || pt > MAX_RTP_PT)
02700       return 0; /* bogus payload type */
02701 
02702    if (static_RTP_PT[pt].isAstFormat)
02703       return static_RTP_PT[pt].code;
02704    else
02705       return 0;
02706 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2692 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02693 {
02694    return &rtp->pref;
02695 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2679 of file rtp.c.

References ast_smoother_free(), ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, prefs, and ast_rtp::smoother.

Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp(), register_verify(), set_peer_capabilities(), start_rtp(), and transmit_response_with_sdp().

02680 {
02681    int x;
02682    for (x = 0; x < 32; x++) {  /* Ugly way */
02683       rtp->pref.order[x] = prefs->order[x];
02684       rtp->pref.framing[x] = prefs->framing[x];
02685    }
02686    if (rtp->smoother)
02687       ast_smoother_free(rtp->smoother);
02688    rtp->smoother = NULL;
02689    return 0;
02690 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 2096 of file rtp.c.

References ast_io_remove(), ast_mutex_destroy(), ast_sched_del(), ast_smoother_free(), ast_verbose(), ast_rtp::bridge_lock, ast_rtcp::expected_prior, free, ast_rtp::io, ast_rtp::ioid, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtp::s, ast_rtcp::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_user_full(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().

02097 {
02098    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02099       /*Print some info on the call here */
02100       ast_verbose("  RTP-stats\n");
02101       ast_verbose("* Our Receiver:\n");
02102       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02103       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02104       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02105       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02106       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02107       ast_verbose("  RR-count:    %u\n", rtp->rtcp->rr_count);
02108       ast_verbose("* Our Sender:\n");
02109       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02110       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02111       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->reported_lost);
02112       ast_verbose("  Jitter:      %u\n", rtp->rtcp->reported_jitter);
02113       ast_verbose("  SR-count:    %u\n", rtp->rtcp->sr_count);
02114       ast_verbose("  RTT:      %f\n", rtp->rtcp->rtt);
02115    }
02116 
02117    if (rtp->smoother)
02118       ast_smoother_free(rtp->smoother);
02119    if (rtp->ioid)
02120       ast_io_remove(rtp->io, rtp->ioid);
02121    if (rtp->s > -1)
02122       close(rtp->s);
02123    if (rtp->rtcp) {
02124       if (rtp->rtcp->schedid > 0)
02125          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02126       close(rtp->rtcp->s);
02127       free(rtp->rtcp);
02128       rtp->rtcp=NULL;
02129    }
02130 
02131    ast_mutex_destroy(&rtp->bridge_lock);
02132 
02133    free(rtp);
02134 }

int ast_rtp_early_bridge ( struct ast_channel dest,
struct ast_channel src 
)

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

Definition at line 1482 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.

Referenced by wait_for_answer().

01483 {
01484    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01485    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01486    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01487    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01488    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
01489    int srccodec, destcodec, nat_active = 0;
01490 
01491    /* Lock channels */
01492    ast_channel_lock(dest);
01493    if (src) {
01494       while(ast_channel_trylock(src)) {
01495          ast_channel_unlock(dest);
01496          usleep(1);
01497          ast_channel_lock(dest);
01498       }
01499    }
01500 
01501    /* Find channel driver interfaces */
01502    destpr = get_proto(dest);
01503    if (src)
01504       srcpr = get_proto(src);
01505    if (!destpr) {
01506       if (option_debug)
01507          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01508       ast_channel_unlock(dest);
01509       if (src)
01510          ast_channel_unlock(src);
01511       return 0;
01512    }
01513    if (!srcpr) {
01514       if (option_debug)
01515          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>");
01516       ast_channel_unlock(dest);
01517       if (src)
01518          ast_channel_unlock(src);
01519       return 0;
01520    }
01521 
01522    /* Get audio and video interface (if native bridge is possible) */
01523    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01524    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01525    if (srcpr) {
01526       audio_src_res = srcpr->get_rtp_info(src, &srcp);
01527       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01528    }
01529 
01530    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01531    if (audio_dest_res != AST_RTP_TRY_NATIVE) {
01532       /* Somebody doesn't want to play... */
01533       ast_channel_unlock(dest);
01534       if (src)
01535          ast_channel_unlock(src);
01536       return 0;
01537    }
01538    if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec)
01539       srccodec = srcpr->get_codec(src);
01540    else
01541       srccodec = 0;
01542    if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec)
01543       destcodec = destpr->get_codec(dest);
01544    else
01545       destcodec = 0;
01546    /* Ensure we have at least one matching codec */
01547    if (!(srccodec & destcodec)) {
01548       ast_channel_unlock(dest);
01549       if (src)
01550          ast_channel_unlock(src);
01551       return 0;
01552    }
01553    /* Consider empty media as non-existant */
01554    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
01555       srcp = NULL;
01556    /* If the client has NAT stuff turned on then just safe NAT is active */
01557    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01558       nat_active = 1;
01559    /* Bridge media early */
01560    if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active))
01561       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>");
01562    ast_channel_unlock(dest);
01563    if (src)
01564       ast_channel_unlock(src);
01565    if (option_debug)
01566       ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>");
01567    return 1;
01568 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 512 of file rtp.c.

References ast_rtp::s.

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

00513 {
00514    return rtp->s;
00515 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

Definition at line 2018 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.

Referenced by ast_rtp_read(), and do_monitor().

02019 {
02020    struct ast_rtp *bridged = NULL;
02021 
02022    ast_mutex_lock(&rtp->bridge_lock);
02023    bridged = rtp->bridged;
02024    ast_mutex_unlock(&rtp->bridge_lock);
02025 
02026    return bridged;
02027 }

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

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

Referenced by process_sdp().

01690 {
01691    int pt;
01692    
01693    ast_mutex_lock(&rtp->bridge_lock);
01694    
01695    *astFormats = *nonAstFormats = 0;
01696    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01697       if (rtp->current_RTP_PT[pt].isAstFormat) {
01698          *astFormats |= rtp->current_RTP_PT[pt].code;
01699       } else {
01700          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01701       }
01702    }
01703    
01704    ast_mutex_unlock(&rtp->bridge_lock);
01705    
01706    return;
01707 }

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

Definition at line 2000 of file rtp.c.

References ast_rtp::them.

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

02001 {
02002    if ((them->sin_family != AF_INET) ||
02003       (them->sin_port != rtp->them.sin_port) ||
02004       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02005       them->sin_family = AF_INET;
02006       them->sin_port = rtp->them.sin_port;
02007       them->sin_addr = rtp->them.sin_addr;
02008       return 1;
02009    }
02010    return 0;
02011 }

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

Return RTCP quality string.

Definition at line 2066 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_rtp_quality::rtt, ast_rtcp::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().

02067 {
02068    /*
02069    *ssrc          our ssrc
02070    *themssrc      their ssrc
02071    *lp            lost packets
02072    *rxjitter      our calculated jitter(rx)
02073    *rxcount       no. received packets
02074    *txjitter      reported jitter of the other end
02075    *txcount       transmitted packets
02076    *rlp           remote lost packets
02077    *rtt           round trip time
02078    */
02079 
02080    if (qual) {
02081       qual->local_ssrc = rtp->ssrc;
02082       qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02083       qual->local_jitter = rtp->rxjitter;
02084       qual->local_count = rtp->rxcount;
02085       qual->remote_ssrc = rtp->themssrc;
02086       qual->remote_lostpackets = rtp->rtcp->reported_lost;
02087       qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02088       qual->remote_count = rtp->txcount;
02089       qual->rtt = rtp->rtcp->rtt;
02090    }
02091    snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt);
02092    
02093    return rtp->rtcp->quality;
02094 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 567 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 575 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00576 {
00577    return rtp->rtpkeepalive;
00578 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 559 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

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

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

Definition at line 2013 of file rtp.c.

References ast_rtp::us.

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

02014 {
02015    *us = rtp->us;
02016 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 595 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00596 {
00597    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00598 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3752 of file rtp.c.

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

Referenced by main().

03753 {
03754    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03755    ast_rtp_reload();
03756 }

int ast_rtp_lookup_code ( struct ast_rtp rtp,
const int  isAstFormat,
const int  code 
)

Looks up an RTP code out of our *static* outbound list.

Definition at line 1731 of file rtp.c.

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

01732 {
01733    int pt = 0;
01734 
01735    ast_mutex_lock(&rtp->bridge_lock);
01736 
01737    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
01738       code == rtp->rtp_lookup_code_cache_code) {
01739       /* Use our cached mapping, to avoid the overhead of the loop below */
01740       pt = rtp->rtp_lookup_code_cache_result;
01741       ast_mutex_unlock(&rtp->bridge_lock);
01742       return pt;
01743    }
01744 
01745    /* Check the dynamic list first */
01746    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01747       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
01748          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01749          rtp->rtp_lookup_code_cache_code = code;
01750          rtp->rtp_lookup_code_cache_result = pt;
01751          ast_mutex_unlock(&rtp->bridge_lock);
01752          return pt;
01753       }
01754    }
01755 
01756    /* Then the static list */
01757    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01758       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
01759          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01760          rtp->rtp_lookup_code_cache_code = code;
01761          rtp->rtp_lookup_code_cache_result = pt;
01762          ast_mutex_unlock(&rtp->bridge_lock);
01763          return pt;
01764       }
01765    }
01766 
01767    ast_mutex_unlock(&rtp->bridge_lock);
01768 
01769    return -1;
01770 }

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

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

Referenced by process_sdp().

01793 {
01794    int format;
01795    unsigned len;
01796    char *end = buf;
01797    char *start = buf;
01798 
01799    if (!buf || !size)
01800       return NULL;
01801 
01802    snprintf(end, size, "0x%x (", capability);
01803 
01804    len = strlen(end);
01805    end += len;
01806    size -= len;
01807    start = end;
01808 
01809    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01810       if (capability & format) {
01811          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01812 
01813          snprintf(end, size, "%s|", name);
01814          len = strlen(end);
01815          end += len;
01816          size -= len;
01817       }
01818    }
01819 
01820    if (start == end)
01821       snprintf(start, size, "nothing)"); 
01822    else if (size > 1)
01823       *(end -1) = ')';
01824    
01825    return buf;
01826 }

const char* ast_rtp_lookup_mime_subtype ( const int  isAstFormat,
const int  code,
enum ast_rtp_options  options 
)

Mapping an Asterisk code into a MIME subtype (string):.

Definition at line 1772 of file rtp.c.

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

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

01774 {
01775    unsigned int i;
01776 
01777    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01778       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01779          if (isAstFormat &&
01780              (code == AST_FORMAT_G726_AAL2) &&
01781              (options & AST_RTP_OPT_G726_NONSTANDARD))
01782             return "G726-32";
01783          else
01784             return mimeTypes[i].subtype;
01785       }
01786    }
01787 
01788    return "";
01789 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1709 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), MAX_RTP_PT, result, and static_RTP_PT.

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

01710 {
01711    struct rtpPayloadType result;
01712 
01713    result.isAstFormat = result.code = 0;
01714 
01715    if (pt < 0 || pt > MAX_RTP_PT) 
01716       return result; /* bogus payload type */
01717 
01718    /* Start with negotiated codecs */
01719    ast_mutex_lock(&rtp->bridge_lock);
01720    result = rtp->current_RTP_PT[pt];
01721    ast_mutex_unlock(&rtp->bridge_lock);
01722 
01723    /* If it doesn't exist, check our static RTP type list, just in case */
01724    if (!result.code) 
01725       result = static_RTP_PT[pt];
01726 
01727    return result;
01728 }

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

Definition at line 1570 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, ast_rtp_pt_copy(), AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.

Referenced by wait_for_answer().

01571 {
01572    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01573    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01574    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01575    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01576    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 
01577    int srccodec, destcodec;
01578 
01579    /* Lock channels */
01580    ast_channel_lock(dest);
01581    while(ast_channel_trylock(src)) {
01582       ast_channel_unlock(dest);
01583       usleep(1);
01584       ast_channel_lock(dest);
01585    }
01586 
01587    /* Find channel driver interfaces */
01588    if (!(destpr = get_proto(dest))) {
01589       if (option_debug)
01590          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01591       ast_channel_unlock(dest);
01592       ast_channel_unlock(src);
01593       return 0;
01594    }
01595    if (!(srcpr = get_proto(src))) {
01596       if (option_debug)
01597          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
01598       ast_channel_unlock(dest);
01599       ast_channel_unlock(src);
01600       return 0;
01601    }
01602 
01603    /* Get audio and video interface (if native bridge is possible) */
01604    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01605    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01606    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01607    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01608 
01609    /* Ensure we have at least one matching codec */
01610    if (srcpr->get_codec)
01611       srccodec = srcpr->get_codec(src);
01612    else
01613       srccodec = 0;
01614    if (destpr->get_codec)
01615       destcodec = destpr->get_codec(dest);
01616    else
01617       destcodec = 0;
01618 
01619    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01620    if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) {
01621       /* Somebody doesn't want to play... */
01622       ast_channel_unlock(dest);
01623       ast_channel_unlock(src);
01624       return 0;
01625    }
01626    ast_rtp_pt_copy(destp, srcp);
01627    if (vdestp && vsrcp)
01628       ast_rtp_pt_copy(vdestp, vsrcp);
01629    if (media) {
01630       /* Bridge early */
01631       if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01632          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
01633    }
01634    ast_channel_unlock(dest);
01635    ast_channel_unlock(src);
01636    if (option_debug)
01637       ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
01638    return 1;
01639 }

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

References ast_rtp_new_with_bindaddr(), io, and sched.

01973 {
01974    struct in_addr ia;
01975 
01976    memset(&ia, 0, sizeof(ia));
01977    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01978 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

Definition at line 1872 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().

01873 {
01874    ast_mutex_init(&rtp->bridge_lock);
01875 
01876    rtp->them.sin_family = AF_INET;
01877    rtp->us.sin_family = AF_INET;
01878    rtp->ssrc = ast_random();
01879    rtp->seqno = ast_random() & 0xffff;
01880    ast_set_flag(rtp, FLAG_HAS_DTMF);
01881 
01882    return;
01883 }

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

References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, FLAG_CALLBACK_MODE, free, io, LOG_ERROR, rtp_socket(), rtpread(), and sched.

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

01886 {
01887    struct ast_rtp *rtp;
01888    int x;
01889    int first;
01890    int startplace;
01891    
01892    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
01893       return NULL;
01894 
01895    ast_rtp_new_init(rtp);
01896 
01897    rtp->s = rtp_socket();
01898    if (rtp->s < 0) {
01899       free(rtp);
01900       ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
01901       return NULL;
01902    }
01903    if (sched && rtcpenable) {
01904       rtp->sched = sched;
01905       rtp->rtcp = ast_rtcp_new();
01906    }
01907    
01908    /* Select a random port number in the range of possible RTP */
01909    x = (ast_random() % (rtpend-rtpstart)) + rtpstart;
01910    x = x & ~1;
01911    /* Save it for future references. */
01912    startplace = x;
01913    /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
01914    for (;;) {
01915       /* Must be an even port number by RTP spec */
01916       rtp->us.sin_port = htons(x);
01917       rtp->us.sin_addr = addr;
01918       /* If there's rtcp, initialize it as well. */
01919       if (rtp->rtcp) {
01920          rtp->rtcp->us.sin_port = htons(x + 1);
01921          rtp->rtcp->us.sin_addr = addr;
01922       }
01923       /* Try to bind it/them. */
01924       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
01925          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
01926          break;
01927       if (!first) {
01928          /* Primary bind succeeded! Gotta recreate it */
01929          close(rtp->s);
01930          rtp->s = rtp_socket();
01931       }
01932       if (errno != EADDRINUSE) {
01933          /* We got an error that wasn't expected, abort! */
01934          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
01935          close(rtp->s);
01936          if (rtp->rtcp) {
01937             close(rtp->rtcp->s);
01938             free(rtp->rtcp);
01939          }
01940          free(rtp);
01941          return NULL;
01942       }
01943       /* The port was used, increment it (by two). */
01944       x += 2;
01945       /* Did we go over the limit ? */
01946       if (x > rtpend)
01947          /* then, start from the begingig. */
01948          x = (rtpstart + 1) & ~1;
01949       /* Check if we reached the place were we started. */
01950       if (x == startplace) {
01951          /* If so, there's no ports available. */
01952          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
01953          close(rtp->s);
01954          if (rtp->rtcp) {
01955             close(rtp->rtcp->s);
01956             free(rtp->rtcp);
01957          }
01958          free(rtp);
01959          return NULL;
01960       }
01961    }
01962    rtp->sched = sched;
01963    rtp->io = io;
01964    if (callbackmode) {
01965       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
01966       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
01967    }
01968    ast_rtp_pt_default(rtp);
01969    return rtp;
01970 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Definition at line 2797 of file rtp.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, protos, and ast_rtp_protocol::type.

Referenced by load_module().

02798 {
02799    struct ast_rtp_protocol *cur;
02800 
02801    AST_LIST_LOCK(&protos);
02802    AST_LIST_TRAVERSE(&protos, cur, list) {   
02803       if (!strcmp(cur->type, proto->type)) {
02804          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02805          AST_LIST_UNLOCK(&protos);
02806          return -1;
02807       }
02808    }
02809    AST_LIST_INSERT_HEAD(&protos, proto, list);
02810    AST_LIST_UNLOCK(&protos);
02811    
02812    return 0;
02813 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2789 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.

Referenced by load_module(), and unload_module().

02790 {
02791    AST_LIST_LOCK(&protos);
02792    AST_LIST_REMOVE(&protos, proto, list);
02793    AST_LIST_UNLOCK(&protos);
02794 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1406 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by process_sdp().

01407 {
01408    int i;
01409 
01410    if (!rtp)
01411       return;
01412 
01413    ast_mutex_lock(&rtp->bridge_lock);
01414 
01415    for (i = 0; i < MAX_RTP_PT; ++i) {
01416       rtp->current_RTP_PT[i].isAstFormat = 0;
01417       rtp->current_RTP_PT[i].code = 0;
01418    }
01419 
01420    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01421    rtp->rtp_lookup_code_cache_code = 0;
01422    rtp->rtp_lookup_code_cache_result = 0;
01423 
01424    ast_mutex_unlock(&rtp->bridge_lock);
01425 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

Definition at line 1446 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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().

01447 {
01448    unsigned int i;
01449 
01450    ast_mutex_lock(&dest->bridge_lock);
01451    ast_mutex_lock(&src->bridge_lock);
01452 
01453    for (i=0; i < MAX_RTP_PT; ++i) {
01454       dest->current_RTP_PT[i].isAstFormat = 
01455          src->current_RTP_PT[i].isAstFormat;
01456       dest->current_RTP_PT[i].code = 
01457          src->current_RTP_PT[i].code; 
01458    }
01459    dest->rtp_lookup_code_cache_isAstFormat = 0;
01460    dest->rtp_lookup_code_cache_code = 0;
01461    dest->rtp_lookup_code_cache_result = 0;
01462 
01463    ast_mutex_unlock(&src->bridge_lock);
01464    ast_mutex_unlock(&dest->bridge_lock);
01465 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 1427 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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.

Referenced by ast_rtp_new_with_bindaddr().

01428 {
01429    int i;
01430 
01431    ast_mutex_lock(&rtp->bridge_lock);
01432 
01433    /* Initialize to default payload types */
01434    for (i = 0; i < MAX_RTP_PT; ++i) {
01435       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01436       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01437    }
01438 
01439    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01440    rtp->rtp_lookup_code_cache_code = 0;
01441    rtp->rtp_lookup_code_cache_result = 0;
01442 
01443    ast_mutex_unlock(&rtp->bridge_lock);
01444 }

static int ast_rtp_raw_write ( struct ast_rtp rtp,
struct ast_frame f,
int  codec 
) [static]

Definition at line 2590 of file rtp.c.

References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), f, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_rtp::lastdigitts, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_DEBUG, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

02591 {
02592    unsigned char *rtpheader;
02593    int hdrlen = 12;
02594    int res;
02595    unsigned int ms;
02596    int pred;
02597    int mark = 0;
02598 
02599    ms = calc_txstamp(rtp, &f->delivery);
02600    /* Default prediction */
02601    if (f->subclass < AST_FORMAT_MAX_AUDIO) {
02602       pred = rtp->lastts + f->samples;
02603 
02604       /* Re-calculate last TS */
02605       rtp->lastts = rtp->lastts + ms * 8;
02606       if (ast_tvzero(f->delivery)) {
02607          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
02608             and if so, go with our prediction */
02609          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
02610             rtp->lastts = pred;
02611          else {
02612             if (option_debug > 2)
02613                ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
02614             mark = 1;
02615          }
02616       }
02617    } else {
02618       mark = f->subclass & 0x1;
02619       pred = rtp->lastovidtimestamp + f->samples;
02620       /* Re-calculate last TS */
02621       rtp->lastts = rtp->lastts + ms * 90;
02622       /* If it's close to our prediction, go for it */
02623       if (ast_tvzero(f->delivery)) {
02624          if (abs(rtp->lastts - pred) < 7200) {
02625             rtp->lastts = pred;
02626             rtp->lastovidtimestamp += f->samples;
02627          } else {
02628             if (option_debug > 2)
02629                ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
02630             rtp->lastovidtimestamp = rtp->lastts;
02631          }
02632       }
02633    }
02634    /* If the timestamp for non-digit packets has moved beyond the timestamp
02635       for digits, update the digit timestamp.
02636    */
02637    if (rtp->lastts > rtp->lastdigitts)
02638       rtp->lastdigitts = rtp->lastts;
02639 
02640    if (f->has_timing_info)
02641       rtp->lastts = f->ts * 8;
02642 
02643    /* Get a pointer to the header */
02644    rtpheader = (unsigned char *)(f->data - hdrlen);
02645 
02646    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
02647    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
02648    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
02649 
02650    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02651       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02652       if (res <0) {
02653          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
02654             ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
02655          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
02656             /* Only give this error message once if we are not RTP debugging */
02657             if (option_debug || rtpdebug)
02658                ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
02659             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
02660          }
02661       } else {
02662          rtp->txcount++;
02663          rtp->txoctetcount +=(res - hdrlen);
02664          
02665          if (rtp->rtcp && rtp->rtcp->schedid < 1) 
02666              rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
02667       }
02668             
02669       if (rtp_debug_test_addr(&rtp->them))
02670          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02671                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
02672    }
02673 
02674    rtp->seqno++;
02675 
02676    return 0;
02677 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1097 of file rtp.c.

References ast_backtrace(), ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, CRASH, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, event, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_frame::has_timing_info, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len, ast_frame::len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::rtcp, rtp_debug_test_addr(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtp::them, ast_rtcp::them, ast_rtp::themssrc, and ast_frame::ts.

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

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

int ast_rtp_reload ( void   ) 

Definition at line 3687 of file rtp.c.

References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and VERBOSE_PREFIX_2.

Referenced by ast_rtp_init().

03688 {
03689    struct ast_config *cfg;
03690    const char *s;
03691 
03692    rtpstart = 5000;
03693    rtpend = 31000;
03694    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03695    cfg = ast_config_load("rtp.conf");
03696    if (cfg) {
03697       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03698          rtpstart = atoi(s);
03699          if (rtpstart < 1024)
03700             rtpstart = 1024;
03701          if (rtpstart > 65535)
03702             rtpstart = 65535;
03703       }
03704       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03705          rtpend = atoi(s);
03706          if (rtpend < 1024)
03707             rtpend = 1024;
03708          if (rtpend > 65535)
03709             rtpend = 65535;
03710       }
03711       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03712          rtcpinterval = atoi(s);
03713          if (rtcpinterval == 0)
03714             rtcpinterval = 0; /* Just so we're clear... it's zero */
03715          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03716             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03717          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03718             rtcpinterval = RTCP_MAX_INTERVALMS;
03719       }
03720       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03721 #ifdef SO_NO_CHECK
03722          if (ast_false(s))
03723             nochecksums = 1;
03724          else
03725             nochecksums = 0;
03726 #else
03727          if (ast_false(s))
03728             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03729 #endif
03730       }
03731       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03732          dtmftimeout = atoi(s);
03733          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03734             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03735                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03736             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03737          };
03738       }
03739       ast_config_destroy(cfg);
03740    }
03741    if (rtpstart >= rtpend) {
03742       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03743       rtpstart = 5000;
03744       rtpend = 31000;
03745    }
03746    if (option_verbose > 1)
03747       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03748    return 0;
03749 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2046 of file rtp.c.

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

02047 {
02048    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02049    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02050    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02051    rtp->lastts = 0;
02052    rtp->lastdigitts = 0;
02053    rtp->lastrxts = 0;
02054    rtp->lastividtimestamp = 0;
02055    rtp->lastovidtimestamp = 0;
02056    rtp->lasteventseqn = 0;
02057    rtp->lastevent = 0;
02058    rtp->lasttxformat = 0;
02059    rtp->lastrxformat = 0;
02060    rtp->dtmfcount = 0;
02061    rtp->dtmfsamples = 0;
02062    rtp->seqno = 0;
02063    rtp->rxseqno = 0;
02064 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2556 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::data, ast_rtp::dtmfmute, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by do_monitor().

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2156 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_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 oh323_digit_begin(), and sip_senddigit_begin().

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

Definition at line 2220 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_verbose(), ast_rtp::lastdigitts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by ast_rtp_read().

02221 {
02222    unsigned int *rtpheader;
02223    int hdrlen = 12, res = 0;
02224    char data[256];
02225 
02226    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02227       return 0;
02228 
02229    /* Setup packet to send */
02230    rtpheader = (unsigned int *)data;
02231         rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02232         rtpheader[1] = htonl(rtp->lastdigitts);
02233         rtpheader[2] = htonl(rtp->ssrc);
02234         rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
02235    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02236    
02237    /* Transmit */
02238    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02239    if (res < 0)
02240       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02241          ast_inet_ntoa(rtp->them.sin_addr),
02242          ntohs(rtp->them.sin_port), strerror(errno));
02243    if (rtp_debug_test_addr(&rtp->them))
02244       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02245              ast_inet_ntoa(rtp->them.sin_addr),
02246              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02247 
02248    /* Increment sequence number */
02249    rtp->seqno++;
02250    /* Increment duration */
02251    rtp->send_duration += 160;
02252 
02253    return 0;
02254 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2257 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, 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 oh323_digit_end(), and sip_senddigit_end().

02258 {
02259    unsigned int *rtpheader;
02260    int hdrlen = 12, res = 0, i = 0;
02261    char data[256];
02262    
02263    /* If no address, then bail out */
02264    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02265       return 0;
02266    
02267    if ((digit <= '9') && (digit >= '0'))
02268       digit -= '0';
02269    else if (digit == '*')
02270       digit = 10;
02271    else if (digit == '#')
02272       digit = 11;
02273    else if ((digit >= 'A') && (digit <= 'D'))
02274       digit = digit - 'A' + 12;
02275    else if ((digit >= 'a') && (digit <= 'd'))
02276       digit = digit - 'a' + 12;
02277    else {
02278       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02279       return 0;
02280    }
02281 
02282    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02283 
02284    rtpheader = (unsigned int *)data;
02285    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02286    rtpheader[1] = htonl(rtp->lastdigitts);
02287    rtpheader[2] = htonl(rtp->ssrc);
02288    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02289    /* Set end bit */
02290    rtpheader[3] |= htonl((1 << 23));
02291    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02292    /* Send 3 termination packets */
02293    for (i = 0; i < 3; i++) {
02294       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02295       if (res < 0)
02296          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02297             ast_inet_ntoa(rtp->them.sin_addr),
02298             ntohs(rtp->them.sin_port), strerror(errno));
02299       if (rtp_debug_test_addr(&rtp->them))
02300          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02301                 ast_inet_ntoa(rtp->them.sin_addr),
02302                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02303    }
02304    rtp->sending_digit = 0;
02305    rtp->send_digit = 0;
02306    /* Increment lastdigitts */
02307    rtp->lastdigitts += 960;
02308    rtp->seqno++;
02309 
02310    return res;
02311 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 585 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00586 {
00587    rtp->callback = callback;
00588 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 580 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00581 {
00582    rtp->data = data;
00583 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

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

Definition at line 1645 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, ast_rtp::current_RTP_PT, MAX_RTP_PT, and static_RTP_PT.

Referenced by gtalk_newcall(), and process_sdp().

01646 {
01647    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01648       return; /* bogus payload type */
01649 
01650    ast_mutex_lock(&rtp->bridge_lock);
01651    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01652    ast_mutex_unlock(&rtp->bridge_lock);
01653 } 

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

Definition at line 1989 of file rtp.c.

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

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

01990 {
01991    rtp->them.sin_port = them->sin_port;
01992    rtp->them.sin_addr = them->sin_addr;
01993    if (rtp->rtcp) {
01994       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
01995       rtp->rtcp->them.sin_addr = them->sin_addr;
01996    }
01997    rtp->rxseqno = 0;
01998 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 547 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00548 {
00549    rtp->rtpholdtimeout = timeout;
00550 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 553 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00554 {
00555    rtp->rtpkeepalive = period;
00556 }

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

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

Definition at line 1658 of file rtp.c.

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

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

01661 {
01662    unsigned int i;
01663 
01664    if (pt < 0 || pt > MAX_RTP_PT) 
01665       return; /* bogus payload type */
01666    
01667    ast_mutex_lock(&rtp->bridge_lock);
01668 
01669    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01670       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01671           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01672          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01673          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01674              mimeTypes[i].payloadType.isAstFormat &&
01675              (options & AST_RTP_OPT_G726_NONSTANDARD))
01676             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01677          break;
01678       }
01679    }
01680 
01681    ast_mutex_unlock(&rtp->bridge_lock);
01682 
01683    return;
01684 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 541 of file rtp.c.

References ast_rtp::rtptimeout.

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

00542 {
00543    rtp->rtptimeout = timeout;
00544 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 534 of file rtp.c.

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

Referenced by handle_response_invite().

00535 {
00536    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00537    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00538 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00601 {
00602    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00603 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00606 {
00607    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00608 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 590 of file rtp.c.

References ast_rtp::nat.

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

00591 {
00592    rtp->nat = nat;
00593 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 610 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00611 {
00612    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00613 }

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 1980 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

01981 {
01982    int res;
01983 
01984    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
01985       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01986    return res;
01987 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Definition at line 2029 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_rtp::them, and ast_rtcp::them.

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

02030 {
02031    if (rtp->rtcp && rtp->rtcp->schedid > 0) {
02032       ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02033       rtp->rtcp->schedid = -1;
02034    }
02035 
02036    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02037    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02038    if (rtp->rtcp) {
02039       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02040       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02041    }
02042    
02043    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02044 }

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

Definition at line 402 of file rtp.c.

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

Referenced by gtalk_update_stun().

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

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2708 of file rtp.c.

References ast_codec_pref_getsize(), AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_frame::datalen, f, fmt, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

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

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

static enum ast_bridge_result bridge_native_loop ( struct ast_channel c0,
struct ast_channel c1,
struct ast_rtp p0,
struct ast_rtp p1,
struct ast_rtp vp0,
struct ast_rtp vp1,
struct ast_rtp_protocol pr0,
struct ast_rtp_protocol pr1,
int  codec0,
int  codec1,
int  timeoutms,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
void *  pvt0,
void *  pvt1 
) [static]

Bridge loop for true native bridge (reinvite).

Definition at line 2816 of file rtp.c.

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate_data(), ast_inet_ntoa(), ast_log(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), ast_frame::data, ast_frame::datalen, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, inaddrcmp(), LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

02817 {
02818    struct ast_frame *fr = NULL;
02819    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
02820    int oldcodec0 = codec0, oldcodec1 = codec1;
02821    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
02822    struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
02823    
02824    /* Set it up so audio goes directly between the two endpoints */
02825 
02826    /* Test the first channel */
02827    if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
02828       ast_rtp_get_peer(p1, &ac1);
02829       if (vp1)
02830          ast_rtp_get_peer(vp1, &vac1);
02831    } else
02832       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
02833    
02834    /* Test the second channel */
02835    if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
02836       ast_rtp_get_peer(p0, &ac0);
02837       if (vp0)
02838          ast_rtp_get_peer(vp0, &vac0);
02839    } else
02840       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
02841 
02842    /* Now we can unlock and move into our loop */
02843    ast_channel_unlock(c0);
02844    ast_channel_unlock(c1);
02845 
02846    /* Throw our channels into the structure and enter the loop */
02847    cs[0] = c0;
02848    cs[1] = c1;
02849    cs[2] = NULL;
02850    for (;;) {
02851       /* Check if anything changed */
02852       if ((c0->tech_pvt != pvt0) ||
02853           (c1->tech_pvt != pvt1) ||
02854           (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
02855          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
02856          if (c0->tech_pvt == pvt0)
02857             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02858                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02859          if (c1->tech_pvt == pvt1)
02860             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02861                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02862          return AST_BRIDGE_RETRY;
02863       }
02864 
02865       /* Check if they have changed their address */
02866       ast_rtp_get_peer(p1, &t1);
02867       if (vp1)
02868          ast_rtp_get_peer(vp1, &vt1);
02869       if (pr1->get_codec)
02870          codec1 = pr1->get_codec(c1);
02871       ast_rtp_get_peer(p0, &t0);
02872       if (vp0)
02873          ast_rtp_get_peer(vp0, &vt0);
02874       if (pr0->get_codec)
02875          codec0 = pr0->get_codec(c0);
02876       if ((inaddrcmp(&t1, &ac1)) ||
02877           (vp1 && inaddrcmp(&vt1, &vac1)) ||
02878           (codec1 != oldcodec1)) {
02879          if (option_debug > 1) {
02880             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02881                c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
02882             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
02883                c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
02884             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02885                c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
02886             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02887                c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
02888          }
02889          if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
02890             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
02891          memcpy(&ac1, &t1, sizeof(ac1));
02892          memcpy(&vac1, &vt1, sizeof(vac1));
02893          oldcodec1 = codec1;
02894       }
02895       if ((inaddrcmp(&t0, &ac0)) ||
02896           (vp0 && inaddrcmp(&vt0, &vac0))) {
02897          if (option_debug > 1) {
02898             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02899                c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
02900             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02901                c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
02902          }
02903          if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
02904             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
02905          memcpy(&ac0, &t0, sizeof(ac0));
02906          memcpy(&vac0, &vt0, sizeof(vac0));
02907          oldcodec0 = codec0;
02908       }
02909 
02910       /* Wait for frame to come in on the channels */
02911       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
02912          if (!timeoutms) {
02913             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02914                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02915             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02916                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02917             return AST_BRIDGE_RETRY;
02918          }
02919          if (option_debug)
02920             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
02921          if (ast_check_hangup(c0) || ast_check_hangup(c1))
02922             break;
02923          continue;
02924       }
02925       fr = ast_read(who);
02926       other = (who == c0) ? c1 : c0;
02927       if (!fr || ((fr->frametype == AST_FRAME_DTMF) &&
02928              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
02929               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
02930          /* Break out of bridge */
02931          *fo = fr;
02932          *rc = who;
02933          if (option_debug)
02934             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
02935          if (c0->tech_pvt == pvt0)
02936             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02937                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02938          if (c1->tech_pvt == pvt1)
02939             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02940                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02941          return AST_BRIDGE_COMPLETE;
02942       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02943          if ((fr->subclass == AST_CONTROL_HOLD) ||
02944              (fr->subclass == AST_CONTROL_UNHOLD) ||
02945              (fr->subclass == AST_CONTROL_VIDUPDATE)) {
02946             if (fr->subclass == AST_CONTROL_HOLD) {
02947                /* If we someone went on hold we want the other side to reinvite back to us */
02948                if (who == c0)
02949                   pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
02950                else
02951                   pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
02952             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
02953                /* If they went off hold they should go back to being direct */
02954                if (who == c0)
02955                   pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
02956                else
02957                   pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
02958             }
02959             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
02960             ast_frfree(fr);
02961          } else {
02962             *fo = fr;
02963             *rc = who;
02964             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
02965             return AST_BRIDGE_COMPLETE;
02966          }
02967       } else {
02968          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
02969              (fr->frametype == AST_FRAME_DTMF) ||
02970              (fr->frametype == AST_FRAME_VOICE) ||
02971              (fr->frametype == AST_FRAME_VIDEO) ||
02972              (fr->frametype == AST_FRAME_IMAGE) ||
02973              (fr->frametype == AST_FRAME_HTML) ||
02974              (fr->frametype == AST_FRAME_MODEM) ||
02975              (fr->frametype == AST_FRAME_TEXT)) {
02976             ast_write(other, fr);
02977          }
02978          ast_frfree(fr);
02979       }
02980       /* Swap priority */
02981       cs[2] = cs[0];
02982       cs[0] = cs[1];
02983       cs[1] = cs[2];
02984    }
02985 
02986    if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02987       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02988    if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02989       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02990 
02991    return AST_BRIDGE_FAILED;
02992 }

static enum ast_bridge_result bridge_p2p_loop ( struct ast_channel c0,
struct ast_channel c1,
struct ast_rtp p0,
struct ast_rtp p1,
int  timeoutms,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
void *  pvt0,
void *  pvt1 
) [static]

Bridge loop for partial native bridge (packet2packet).

Definition at line 3090 of file rtp.c.

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate_data(), ast_log(), ast_read(), ast_waitfor_n(), ast_write(), ast_frame::data, ast_frame::datalen, FLAG_P2P_SENT_MARK, ast_frame::frametype, LOG_NOTICE, ast_channel::masq, ast_channel::masqr, option_debug, p2p_callback_disable(), p2p_callback_enable(), p2p_set_bridge(), ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

03091 {
03092    struct ast_frame *fr = NULL;
03093    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03094    int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
03095    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03096    int p0_callback = 0, p1_callback = 0;
03097    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03098 
03099    /* Okay, setup each RTP structure to do P2P forwarding */
03100    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03101    p2p_set_bridge(p0, p1);
03102    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03103    p2p_set_bridge(p1, p0);
03104 
03105    /* Activate callback modes if possible */
03106    p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03107    p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03108 
03109    /* Now let go of the channel locks and be on our way */
03110    ast_channel_unlock(c0);
03111    ast_channel_unlock(c1);
03112 
03113    /* Go into a loop forwarding frames until we don't need to anymore */
03114    cs[0] = c0;
03115    cs[1] = c1;
03116    cs[2] = NULL;
03117    for (;;) {
03118       /* Check if anything changed */
03119       if ((c0->tech_pvt != pvt0) ||
03120           (c1->tech_pvt != pvt1) ||
03121           (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
03122          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03123          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03124             ast_frfree(fr);
03125          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03126             ast_frfree(fr);
03127          res = AST_BRIDGE_RETRY;
03128          break;
03129       }
03130       /* Wait on a channel to feed us a frame */
03131       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03132          if (!timeoutms) {
03133             res = AST_BRIDGE_RETRY;
03134             break;
03135          }
03136          if (option_debug)
03137             ast_log(LOG_NOTICE, "Ooh, empty read...\n");
03138          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03139             break;
03140          continue;
03141       }
03142       /* Read in frame from channel */
03143       fr = ast_read(who);
03144       other = (who == c0) ? c1 : c0;
03145       /* Dependong on the frame we may need to break out of our bridge */
03146       if (!fr || ((fr->frametype == AST_FRAME_DTMF) &&
03147              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03148              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03149          /* Record received frame and who */
03150          *fo = fr;
03151          *rc = who;
03152          if (option_debug)
03153             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03154          res = AST_BRIDGE_COMPLETE;
03155          break;
03156       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03157          if ((fr->subclass == AST_CONTROL_HOLD) ||
03158              (fr->subclass == AST_CONTROL_UNHOLD) ||
03159              (fr->subclass == AST_CONTROL_VIDUPDATE)) {
03160             /* If we are going on hold, then break callback mode and P2P bridging */
03161             if (fr->subclass == AST_CONTROL_HOLD) {
03162                if (p0_callback)
03163                   p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03164                if (p1_callback)
03165                   p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03166                p2p_set_bridge(p0, NULL);
03167                p2p_set_bridge(p1, NULL);
03168             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03169                /* If we are off hold, then go back to callback mode and P2P bridging */
03170                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03171                p2p_set_bridge(p0, p1);
03172                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03173                p2p_set_bridge(p1, p0);
03174                p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03175                p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03176             }
03177             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03178             ast_frfree(fr);
03179          } else {
03180             *fo = fr;
03181             *rc = who;
03182             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03183             res = AST_BRIDGE_COMPLETE;
03184             break;
03185          }
03186       } else {
03187          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03188              (fr->frametype == AST_FRAME_DTMF) ||
03189              (fr->frametype == AST_FRAME_VOICE) ||
03190              (fr->frametype == AST_FRAME_VIDEO) ||
03191              (fr->frametype == AST_FRAME_IMAGE) ||
03192              (fr->frametype == AST_FRAME_HTML) ||
03193              (fr->frametype == AST_FRAME_MODEM) ||
03194              (fr->frametype == AST_FRAME_TEXT)) {
03195             ast_write(other, fr);
03196          }
03197 
03198          ast_frfree(fr);
03199       }
03200       /* Swap priority */
03201       cs[2] = cs[0];
03202       cs[0] = cs[1];
03203       cs[1] = cs[2];
03204    }
03205 
03206    /* If we are totally avoiding the core, then restore our link to it */
03207    if (p0_callback)
03208       p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03209    if (p1_callback)
03210       p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03211 
03212    /* Break out of the direct bridge */
03213    p2p_set_bridge(p0, NULL);
03214    p2p_set_bridge(p1, NULL);
03215 
03216    return res;
03217 }

static int bridge_p2p_rtp_write ( struct ast_rtp rtp,
struct ast_rtp bridged,
unsigned int *  rtpheader,
int  len,
int  hdrlen 
) [static]

Perform a Packet2Packet RTP write.

Definition at line 1048 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_set_flag, ast_test_flag, ast_verbose(), rtpPayloadType::code, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_P2P_NEED_DTMF, FLAG_P2P_SENT_MARK, rtpPayloadType::isAstFormat, LOG_DEBUG, ast_rtp::nat, option_debug, reconstruct(), rtp_debug_test_addr(), ast_rtp::s, and ast_rtp::them.

Referenced by ast_rtp_read().

01049 {
01050    int res = 0, payload = 0, bridged_payload = 0, mark;
01051    struct rtpPayloadType rtpPT;
01052    int reconstruct = ntohl(rtpheader[0]);
01053 
01054    /* Get fields from packet */
01055    payload = (reconstruct & 0x7f0000) >> 16;
01056    mark = (((reconstruct & 0x800000) >> 23) != 0);
01057 
01058    /* Check what the payload value should be */
01059    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01060 
01061    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01062    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01063       return -1;
01064 
01065    /* Otherwise adjust bridged payload to match */
01066    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01067 
01068    /* If the mark bit has not been sent yet... do it now */
01069    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01070       mark = 1;
01071       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01072    }
01073 
01074    /* Reconstruct part of the packet */
01075    reconstruct &= 0xFF80FFFF;
01076    reconstruct |= (bridged_payload << 16);
01077    reconstruct |= (mark << 23);
01078    rtpheader[0] = htonl(reconstruct);
01079 
01080    /* Send the packet back out */
01081    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01082    if (res < 0) {
01083       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01084          ast_log(LOG_DEBUG, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno));
01085       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01086          if (option_debug || rtpdebug)
01087             ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port));
01088          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01089       }
01090       return 0;
01091    } else if (rtp_debug_test_addr(&bridged->them))
01092          ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), bridged_payload, len - hdrlen);
01093 
01094    return 0;
01095 }

static void calc_rxstamp ( struct timeval *  tv,
struct ast_rtp rtp,
unsigned int  timestamp,
int  mark 
) [static]

Definition at line 999 of file rtp.c.

References ast_rtp::drxcore, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtp::rtcp, ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtp::rxtransit, and ast_rtp::seedrxts.

Referenced by ast_rtp_read(), and schedule_delivery().

01000 {
01001    struct timeval now;
01002    double transit;
01003    double current_time;
01004    double d;
01005    double dtv;
01006    double prog;
01007    
01008    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01009       gettimeofday(&rtp->rxcore, NULL);
01010       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01011       /* map timestamp to a real time */
01012       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01013       rtp->rxcore.tv_sec -= timestamp / 8000;
01014       rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
01015       /* Round to 0.1ms for nice, pretty timestamps */
01016       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01017       if (rtp->rxcore.tv_usec < 0) {
01018          /* Adjust appropriately if necessary */
01019          rtp->rxcore.tv_usec += 1000000;
01020          rtp->rxcore.tv_sec -= 1;
01021       }
01022    }
01023 
01024    gettimeofday(&now,NULL);
01025    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01026    tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
01027    tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
01028    if (tv->tv_usec >= 1000000) {
01029       tv->tv_usec -= 1000000;
01030       tv->tv_sec += 1;
01031    }
01032    prog = (double)((timestamp-rtp->seedrxts)/8000.);
01033    dtv = (double)rtp->drxcore + (double)(prog);
01034    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01035    transit = current_time - dtv;
01036    d = transit - rtp->rxtransit;
01037    rtp->rxtransit = transit;
01038    if (d<0)
01039       d=-d;
01040    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01041    if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
01042       rtp->rtcp->maxrxjitter = rtp->rxjitter;
01043    if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01044       rtp->rtcp->minrxjitter = rtp->rxjitter;
01045 }

static unsigned int calc_txstamp ( struct ast_rtp rtp,
struct timeval *  delivery 
) [static]

Definition at line 2136 of file rtp.c.

References t, and ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

02137 {
02138    struct timeval t;
02139    long ms;
02140    if (ast_tvzero(rtp->txcore)) {
02141       rtp->txcore = ast_tvnow();
02142       /* Round to 20ms for nice, pretty timestamps */
02143       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02144    }
02145    /* Use previous txcore if available */
02146    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02147    ms = ast_tvdiff_ms(t, rtp->txcore);
02148    if (ms < 0)
02149       ms = 0;
02150    /* Use what we just got for next time */
02151    rtp->txcore = t;
02152    return (unsigned int) ms;
02153 }

static struct ast_rtp_protocol* get_proto ( struct ast_channel chan  )  [static]

Get channel driver interface structure.

Definition at line 1468 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, protos, ast_channel::tech, ast_channel_tech::type, and ast_rtp_protocol::type.

Referenced by ast_rtp_bridge(), ast_rtp_early_bridge(), ast_rtp_make_compatible(), and ast_udptl_bridge().

01469 {
01470    struct ast_rtp_protocol *cur = NULL;
01471 
01472    AST_LIST_LOCK(&protos);
01473    AST_LIST_TRAVERSE(&protos, cur, list) {
01474       if (cur->type == chan->tech->type)
01475          break;
01476    }
01477    AST_LIST_UNLOCK(&protos);
01478 
01479    return cur;
01480 }

static int p2p_callback_disable ( struct ast_channel chan,
struct ast_rtp rtp,
int *  fds,
int **  iod 
) [static]

Helper function to switch a channel and RTP stream out of callback mode.

Definition at line 3061 of file rtp.c.

References ast_channel_lock, ast_channel_unlock, ast_io_add(), AST_IO_IN, ast_io_remove(), ast_test_flag, ast_channel::fds, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, rtpread(), and ast_rtp::s.

Referenced by bridge_p2p_loop().

03062 {
03063    ast_channel_lock(chan);
03064 
03065    /* Remove the callback from the IO context */
03066    ast_io_remove(rtp->io, iod[0]);
03067 
03068    /* Restore file descriptors */
03069    chan->fds[0] = fds[0];
03070    ast_channel_unlock(chan);
03071 
03072    /* Restore callback mode if previously used */
03073    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03074       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03075 
03076    return 0;
03077 }

static int p2p_callback_enable ( struct ast_channel chan,
struct ast_rtp rtp,
int *  fds,
int **  iod 
) [static]

P2P RTP Callback.

Definition at line 3054 of file rtp.c.

Referenced by bridge_p2p_loop().

03055 {
03056    return 0;
03057 }

static void p2p_set_bridge ( struct ast_rtp rtp0,
struct ast_rtp rtp1 
) [static]

Helper function that sets what an RTP structure is bridged to.

Definition at line 3080 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.

Referenced by bridge_p2p_loop().

03081 {
03082    ast_mutex_lock(&rtp0->bridge_lock);
03083    rtp0->bridged = rtp1;
03084    ast_mutex_unlock(&rtp0->bridge_lock);
03085 
03086    return;
03087 }

static struct ast_frame* process_cisco_dtmf ( struct ast_rtp rtp,
unsigned char *  data,
int  len 
) [static]

Definition at line 669 of file rtp.c.

References AST_FRAME_DTMF_END, ast_log(), ast_rtp::dtmfcount, event, f, LOG_DEBUG, option_debug, ast_rtp::resp, and send_dtmf().

Referenced by ast_rtp_read().

00670 {
00671    unsigned int event;
00672    char resp = 0;
00673    struct ast_frame *f = NULL;
00674    event = ntohl(*((unsigned int *)(data)));
00675    event &= 0x001F;
00676    if (option_debug > 2 || rtpdebug)
00677       ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len);
00678    if (event < 10) {
00679       resp = '0' + event;
00680    } else if (event < 11) {
00681       resp = '*';
00682    } else if (event < 12) {
00683       resp = '#';
00684    } else if (event < 16) {
00685       resp = 'A' + (event - 12);
00686    } else if (event < 17) {
00687       resp = 'X';
00688    }
00689    if (rtp->resp && (rtp->resp != resp)) {
00690       f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00691    }
00692    rtp->resp = resp;
00693    rtp->dtmfcount = dtmftimeout;
00694    return f;
00695 }

static struct ast_frame* process_rfc2833 ( struct ast_rtp rtp,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp 
) [static]

Process RTP DTMF and events according to RFC 2833.

RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".

Parameters:
rtp 
data 
len 
seqno 
Returns:

Definition at line 708 of file rtp.c.

References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_test_flag, ast_rtp::dtmfcount, ast_rtp::dtmfsamples, event, f, FLAG_DTMF_COMPENSATE, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, ast_frame::samples, and send_dtmf().

Referenced by ast_rtp_read().

00709 {
00710    unsigned int event;
00711    unsigned int event_end;
00712    unsigned int samples;
00713    char resp = 0;
00714    struct ast_frame *f = NULL;
00715 
00716    /* Figure out event, event end, and samples */
00717    event = ntohl(*((unsigned int *)(data)));
00718    event >>= 24;
00719    event_end = ntohl(*((unsigned int *)(data)));
00720    event_end <<= 8;
00721    event_end >>= 24;
00722    samples = ntohl(*((unsigned int *)(data)));
00723    samples &= 0xFFFF;
00724 
00725    /* Print out debug if turned on */
00726    if (rtpdebug || option_debug > 2)
00727       ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
00728 
00729    /* Figure out what digit was pressed */
00730    if (event < 10) {
00731       resp = '0' + event;
00732    } else if (event < 11) {
00733       resp = '*';
00734    } else if (event < 12) {
00735       resp = '#';
00736    } else if (event < 16) {
00737       resp = 'A' + (event - 12);
00738    } else if (event < 17) {   /* Event 16: Hook flash */
00739       resp = 'X'; 
00740    }
00741 
00742    if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
00743       if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
00744          rtp->resp = resp;
00745          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00746          f->len = 0;
00747          rtp->lastevent = timestamp;
00748       }
00749    } else {
00750       if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) {
00751          rtp->resp = resp;
00752          f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
00753       } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) {
00754          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00755          f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
00756          rtp->resp = 0;
00757          rtp->lastevent = seqno;
00758       }
00759    }
00760 
00761    rtp->dtmfcount = dtmftimeout;
00762    rtp->dtmfsamples = samples;
00763 
00764    return f;
00765 }

static struct ast_frame* process_rfc3389 ( struct ast_rtp rtp,
unsigned char *  data,
int  len 
) [static]

Process Comfort Noise RTP.

This is incomplete at the moment.

Definition at line 773 of file rtp.c.

References AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, f, FLAG_3389_WARNING, ast_frame::frametype, ast_rtp::lastrxformat, LOG_DEBUG, LOG_NOTICE, ast_frame::offset, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_read().

00774 {
00775    struct ast_frame *f = NULL;
00776    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
00777       totally help us out becuase we don't have an engine to keep it going and we are not
00778       guaranteed to have it every 20ms or anything */
00779    if (rtpdebug)
00780       ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
00781 
00782    if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
00783       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
00784          ast_inet_ntoa(rtp->them.sin_addr));
00785       ast_set_flag(rtp, FLAG_3389_WARNING);
00786    }
00787 
00788    /* Must have at least one byte */
00789    if (!len)
00790       return NULL;
00791    if (len < 24) {
00792       rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
00793       rtp->f.datalen = len - 1;
00794       rtp->f.offset = AST_FRIENDLY_OFFSET;
00795       memcpy(rtp->f.data, data + 1, len - 1);
00796    } else {
00797       rtp->f.data = NULL;
00798       rtp->f.offset = 0;
00799       rtp->f.datalen = 0;
00800    }
00801    rtp->f.frametype = AST_FRAME_CNG;
00802    rtp->f.subclass = data[0] & 0x7f;
00803    rtp->f.datalen = len - 1;
00804    rtp->f.samples = 0;
00805    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
00806    f = &rtp->f;
00807    return f;
00808 }

static int rtcp_debug_test_addr ( struct sockaddr_in *  addr  )  [inline, static]

Definition at line 655 of file rtp.c.

Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().

00656 {
00657    if (rtcpdebug == 0)
00658       return 0;
00659    if (rtcpdebugaddr.sin_addr.s_addr) {
00660       if (((ntohs(rtcpdebugaddr.sin_port) != 0)
00661          && (rtcpdebugaddr.sin_port != addr->sin_port))
00662          || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00663       return 0;
00664    }
00665    return 1;
00666 }

static int rtcp_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3484 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip().

03484                                                          {
03485    if (argc != 2) {
03486       if (argc != 4)
03487          return RESULT_SHOWUSAGE;
03488       return rtcp_do_debug_ip(fd, argc, argv);
03489    }
03490    rtcpdebug = 1;
03491    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03492    ast_cli(fd, "RTCP Debugging Enabled\n");
03493    return RESULT_SUCCESS;
03494 }

static int rtcp_do_debug_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3472 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip_deprecated().

03472                                                                     {
03473    if (argc != 3) {
03474       if (argc != 5)
03475          return RESULT_SHOWUSAGE;
03476       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03477    }
03478    rtcpdebug = 1;
03479    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03480    ast_cli(fd, "RTCP Debugging Enabled\n");
03481    return RESULT_SUCCESS;
03482 }

static int rtcp_do_debug_ip ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3429 of file rtp.c.

References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

Referenced by rtcp_do_debug().

03430 {
03431    struct hostent *hp;
03432    struct ast_hostent ahp;
03433    int port = 0;
03434    char *p, *arg;
03435    if (argc != 4)
03436       return RESULT_SHOWUSAGE;
03437 
03438    arg = argv[3];
03439    p = strstr(arg, ":");
03440    if (p) {
03441       *p = '\0';
03442       p++;
03443       port = atoi(p);
03444    }
03445    hp = ast_gethostbyname(arg, &ahp);
03446    if (hp == NULL)
03447       return RESULT_SHOWUSAGE;
03448    rtcpdebugaddr.sin_family = AF_INET;
03449    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03450    rtcpdebugaddr.sin_port = htons(port);
03451    if (port == 0)
03452       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03453    else
03454       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03455    rtcpdebug = 1;
03456    return RESULT_SUCCESS;
03457 }

static int rtcp_do_debug_ip_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3399 of file rtp.c.

References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

Referenced by rtcp_do_debug_deprecated().

03400 {
03401    struct hostent *hp;
03402    struct ast_hostent ahp;
03403    int port = 0;
03404    char *p, *arg;
03405    if (argc != 5)
03406       return RESULT_SHOWUSAGE;
03407 
03408    arg = argv[4];
03409    p = strstr(arg, ":");
03410    if (p) {
03411       *p = '\0';
03412       p++;
03413       port = atoi(p);
03414    }
03415    hp = ast_gethostbyname(arg, &ahp);
03416    if (hp == NULL)
03417       return RESULT_SHOWUSAGE;
03418    rtcpdebugaddr.sin_family = AF_INET;
03419    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03420    rtcpdebugaddr.sin_port = htons(port);
03421    if (port == 0)
03422       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03423    else
03424       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03425    rtcpdebug = 1;
03426    return RESULT_SUCCESS;
03427 }

static int rtcp_do_stats ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3505 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03505                                                          {
03506    if (argc != 2) {
03507       return RESULT_SHOWUSAGE;
03508    }
03509    rtcpstats = 1;
03510    ast_cli(fd, "RTCP Stats Enabled\n");
03511    return RESULT_SUCCESS;
03512 }

static int rtcp_do_stats_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3496 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03496                                                                     {
03497    if (argc != 3) {
03498       return RESULT_SHOWUSAGE;
03499    }
03500    rtcpstats = 1;
03501    ast_cli(fd, "RTCP Stats Enabled\n");
03502    return RESULT_SUCCESS;
03503 }

static int rtcp_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3532 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03533 {
03534    if (argc != 3)
03535       return RESULT_SHOWUSAGE;
03536    rtcpdebug = 0;
03537    ast_cli(fd,"RTCP Debugging Disabled\n");
03538    return RESULT_SUCCESS;
03539 }

static int rtcp_no_debug_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3523 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03524 {
03525    if (argc != 4)
03526       return RESULT_SHOWUSAGE;
03527    rtcpdebug = 0;
03528    ast_cli(fd,"RTCP Debugging Disabled\n");
03529    return RESULT_SUCCESS;
03530 }

static int rtcp_no_stats ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3550 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03551 {
03552    if (argc != 3)
03553       return RESULT_SHOWUSAGE;
03554    rtcpstats = 0;
03555    ast_cli(fd,"RTCP Stats Disabled\n");
03556    return RESULT_SUCCESS;
03557 }

static int rtcp_no_stats_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3541 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03542 {
03543    if (argc != 4)
03544       return RESULT_SHOWUSAGE;
03545    rtcpstats = 0;
03546    ast_cli(fd,"RTCP Stats Disabled\n");
03547    return RESULT_SUCCESS;
03548 }

static int rtp_debug_test_addr ( struct sockaddr_in *  addr  )  [inline, static]

Definition at line 642 of file rtp.c.

Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_senddigit_continuation(), ast_rtp_senddigit_end(), and bridge_p2p_rtp_write().

00643 {
00644    if (rtpdebug == 0)
00645       return 0;
00646    if (rtpdebugaddr.sin_addr.s_addr) {
00647       if (((ntohs(rtpdebugaddr.sin_port) != 0)
00648          && (rtpdebugaddr.sin_port != addr->sin_port))
00649          || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00650       return 0;
00651    }
00652    return 1;
00653 }

static int rtp_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3459 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtp_do_debug_ip().

03460 {
03461    if (argc != 2) {
03462       if (argc != 4)
03463          return RESULT_SHOWUSAGE;
03464       return rtp_do_debug_ip(fd, argc, argv);
03465    }
03466    rtpdebug = 1;
03467    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03468    ast_cli(fd, "RTP Debugging Enabled\n");
03469    return RESULT_SUCCESS;
03470 }

static int rtp_do_debug_ip ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3369 of file rtp.c.

References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

Referenced by rtp_do_debug().

03370 {
03371    struct hostent *hp;
03372    struct ast_hostent ahp;
03373    int port = 0;
03374    char *p, *arg;
03375 
03376    if (argc != 4)
03377       return RESULT_SHOWUSAGE;
03378    arg = argv[3];
03379    p = strstr(arg, ":");
03380    if (p) {
03381       *p = '\0';
03382       p++;
03383       port = atoi(p);
03384    }
03385    hp = ast_gethostbyname(arg, &ahp);
03386    if (hp == NULL)
03387       return RESULT_SHOWUSAGE;
03388    rtpdebugaddr.sin_family = AF_INET;
03389    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
03390    rtpdebugaddr.sin_port = htons(port);
03391    if (port == 0)
03392       ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
03393    else
03394       ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
03395    rtpdebug = 1;
03396    return RESULT_SUCCESS;
03397 }

static int rtp_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3514 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03515 {
03516    if (argc != 3)
03517       return RESULT_SHOWUSAGE;
03518    rtpdebug = 0;
03519    ast_cli(fd,"RTP Debugging Disabled\n");
03520    return RESULT_SUCCESS;
03521 }

static int rtp_socket ( void   )  [static]

Definition at line 1828 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01829 {
01830    int s;
01831    long flags;
01832    s = socket(AF_INET, SOCK_DGRAM, 0);
01833    if (s > -1) {
01834       flags = fcntl(s, F_GETFL);
01835       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01836 #ifdef SO_NO_CHECK
01837       if (nochecksums)
01838          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01839 #endif
01840    }
01841    return s;
01842 }

static int rtpread ( int *  id,
int  fd,
short  events,
void *  cbdata 
) [static]

Definition at line 810 of file rtp.c.

References ast_rtp_read(), ast_rtp::callback, and f.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

00811 {
00812    struct ast_rtp *rtp = cbdata;
00813    struct ast_frame *f;
00814    f = ast_rtp_read(rtp);
00815    if (f) {
00816       if (rtp->callback)
00817          rtp->callback(rtp, f, rtp->data);
00818    }
00819    return 1;
00820 }

static struct ast_frame* send_dtmf ( struct ast_rtp rtp,
enum ast_frame_type  type 
) [static]

Definition at line 615 of file rtp.c.

References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_test_flag, ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::f, FLAG_DTMF_COMPENSATE, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, option_debug, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.

Referenced by process_cisco_dtmf(), and process_rfc2833().

00616 {
00617    if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
00618         (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
00619       if (option_debug)
00620          ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
00621       rtp->resp = 0;
00622       rtp->dtmfsamples = 0;
00623       return &ast_null_frame;
00624    }
00625    if (option_debug)
00626       ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
00627    if (rtp->resp == 'X') {
00628       rtp->f.frametype = AST_FRAME_CONTROL;
00629       rtp->f.subclass = AST_CONTROL_FLASH;
00630    } else {
00631       rtp->f.frametype = type;
00632       rtp->f.subclass = rtp->resp;
00633    }
00634    rtp->f.datalen = 0;
00635    rtp->f.samples = 0;
00636    rtp->f.mallocd = 0;
00637    rtp->f.src = "RTP";
00638    return &rtp->f;
00639    
00640 }

static const char* stun_attr2str ( int  msg  )  [static]

Definition at line 299 of file rtp.c.

References STUN_CHANGE_REQUEST, STUN_CHANGED_ADDRESS, STUN_ERROR_CODE, STUN_MAPPED_ADDRESS, STUN_MESSAGE_INTEGRITY, STUN_PASSWORD, STUN_REFLECTED_FROM, STUN_RESPONSE_ADDRESS, STUN_SOURCE_ADDRESS, STUN_UNKNOWN_ATTRIBUTES, and STUN_USERNAME.

Referenced by stun_handle_packet(), and stun_process_attr().

00300 {
00301    switch(msg) {
00302    case STUN_MAPPED_ADDRESS:
00303       return "Mapped Address";
00304    case STUN_RESPONSE_ADDRESS:
00305       return "Response Address";
00306    case STUN_CHANGE_REQUEST:
00307       return "Change Request";
00308    case STUN_SOURCE_ADDRESS:
00309       return "Source Address";
00310    case STUN_CHANGED_ADDRESS:
00311       return "Changed Address";
00312    case STUN_USERNAME:
00313       return "Username";
00314    case STUN_PASSWORD:
00315       return "Password";
00316    case STUN_MESSAGE_INTEGRITY:
00317       return "Message Integrity";
00318    case STUN_ERROR_CODE:
00319       return "Error Code";
00320    case STUN_UNKNOWN_ATTRIBUTES:
00321       return "Unknown Attributes";
00322    case STUN_REFLECTED_FROM:
00323       return "Reflected From";
00324    }
00325    return "Non-RFC3489 Attribute";
00326 }

static int stun_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3559 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03560 {
03561    if (argc != 2) {
03562       return RESULT_SHOWUSAGE;
03563    }
03564    stundebug = 1;
03565    ast_cli(fd, "STUN Debugging Enabled\n");
03566    return RESULT_SUCCESS;
03567 }

static int stun_handle_packet ( int  s,
struct sockaddr_in *  src,
unsigned char *  data,
size_t  len 
) [static]

Definition at line 423 of file rtp.c.

References append_attr_address(), append_attr_string(), ast_log(), ast_verbose(), stun_attr::attr, stun_header::id, stun_header::ies, LOG_DEBUG, stun_header::msglen, stun_header::msgtype, option_debug, STUN_ACCEPT, stun_attr2str(), STUN_BINDREQ, STUN_BINDRESP, STUN_IGNORE, STUN_MAPPED_ADDRESS, stun_msg2str(), stun_process_attr(), stun_send(), and STUN_USERNAME.

Referenced by ast_rtp_read().

00424 {
00425    struct stun_header *resp, *hdr = (struct stun_header *)data;
00426    struct stun_attr *attr;
00427    struct stun_state st;
00428    int ret = STUN_IGNORE;  
00429    unsigned char respdata[1024];
00430    int resplen, respleft;
00431    
00432    if (len < sizeof(struct stun_header)) {
00433       if (option_debug)
00434          ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header));
00435       return -1;
00436    }
00437    if (stundebug)
00438       ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen));
00439    if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) {
00440       if (option_debug)
00441          ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header));
00442    } else
00443       len = ntohs(hdr->msglen);
00444    data += sizeof(struct stun_header);
00445    memset(&st, 0, sizeof(st));
00446    while(len) {
00447       if (len < sizeof(struct stun_attr)) {
00448          if (option_debug)
00449             ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr));
00450          break;
00451       }
00452       attr = (struct stun_attr *)data;
00453       if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) {
00454          if (option_debug)
00455             ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len);
00456          break;
00457       }
00458       if (stun_process_attr(&st, attr)) {
00459          if (option_debug)
00460             ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
00461          break;
00462       }
00463       /* Clear attribute in case previous entry was a string */
00464       attr->attr = 0;
00465       data += ntohs(attr->len) + sizeof(struct stun_attr);
00466       len -= ntohs(attr->len) + sizeof(struct stun_attr);
00467    }
00468    /* Null terminate any string */
00469    *data = '\0';
00470    resp = (struct stun_header *)respdata;
00471    resplen = 0;
00472    respleft = sizeof(respdata) - sizeof(struct stun_header);
00473    resp->id = hdr->id;
00474    resp->msgtype = 0;
00475    resp->msglen = 0;
00476    attr = (struct stun_attr *)resp->ies;
00477    if (!len) {
00478       switch(ntohs(hdr->msgtype)) {
00479       case STUN_BINDREQ:
00480          if (stundebug)
00481             ast_verbose("STUN Bind Request, username: %s\n", 
00482                st.username ? st.username : "<none>");
00483          if (st.username)
00484             append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
00485          append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
00486          resp->msglen = htons(resplen);
00487          resp->msgtype = htons(STUN_BINDRESP);
00488          stun_send(s, src, resp);
00489          ret = STUN_ACCEPT;
00490          break;
00491       default:
00492          if (stundebug)
00493             ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
00494       }
00495    }
00496    return ret;
00497 }

static const char* stun_msg2str ( int  msg  )  [static]

Definition at line 280 of file rtp.c.

References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.

Referenced by stun_handle_packet().

00281 {
00282    switch(msg) {
00283    case STUN_BINDREQ:
00284       return "Binding Request";
00285    case STUN_BINDRESP:
00286       return "Binding Response";
00287    case STUN_BINDERR:
00288       return "Binding Error Response";
00289    case STUN_SECREQ:
00290       return "Shared Secret Request";
00291    case STUN_SECRESP:
00292       return "Shared Secret Response";
00293    case STUN_SECERR:
00294       return "Shared Secret Error Response";
00295    }
00296    return "Non-RFC3489 Message";
00297 }

static int stun_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3569 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03570 {
03571    if (argc != 3)
03572       return RESULT_SHOWUSAGE;
03573    stundebug = 0;
03574    ast_cli(fd, "STUN Debugging Disabled\n");
03575    return RESULT_SUCCESS;
03576 }

static int stun_process_attr ( struct stun_state state,
struct stun_attr attr 
) [static]

Definition at line 333 of file rtp.c.

References ast_verbose(), stun_attr::attr, stun_attr::len, stun_state::password, stun_attr2str(), STUN_PASSWORD, STUN_USERNAME, stun_state::username, and stun_attr::value.

Referenced by stun_handle_packet().

00334 {
00335    if (stundebug)
00336       ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
00337          stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00338    switch(ntohs(attr->attr)) {
00339    case STUN_USERNAME:
00340       state->username = (const char *) (attr->value);
00341       break;
00342    case STUN_PASSWORD:
00343       state->password = (const char *) (attr->value);
00344       break;
00345    default:
00346       if (stundebug)
00347          ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 
00348             stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00349    }
00350    return 0;
00351 }

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 390 of file rtp.c.

References ast_random(), and stun_header::id.

Referenced by ast_rtp_stun_request().

00391 {
00392    int x;
00393    for (x=0;x<4;x++)
00394       req->id.id[x] = ast_random();
00395 }

static int stun_send ( int  s,
struct sockaddr_in *  dst,
struct stun_header resp 
) [static]

Definition at line 384 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

00385 {
00386    return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00387       (struct sockaddr *)dst, sizeof(*dst));
00388 }

static void timeval2ntp ( struct timeval  tv,
unsigned int *  msw,
unsigned int *  lsw 
) [static]

Definition at line 502 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

00503 {
00504    unsigned int sec, usec, frac;
00505    sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
00506    usec = tv.tv_usec;
00507    frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
00508    *msw = sec;
00509    *lsw = frac;
00510 }


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3645 of file rtp.c.

Referenced by ast_rtp_init().

struct ast_cli_entry cli_rtp_no_debug_deprecated [static]

Initial value:

 {
   { "rtp", "no", "debug", NULL },
   rtp_no_debug, NULL,
        NULL }

Definition at line 3610 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_debug_deprecated [static]

Initial value:

 {
   { "rtp", "rtcp", "debug", NULL },
   rtcp_do_debug_deprecated, NULL,
        NULL }

Definition at line 3620 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated [static]

Initial value:

 {
   { "rtp", "rtcp", "debug", "ip", NULL },
   rtcp_do_debug_deprecated, NULL,
        NULL }

Definition at line 3615 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated [static]

Initial value:

 {
   { "rtp", "rtcp", "no", "debug", NULL },
   rtcp_no_debug_deprecated, NULL,
        NULL }

Definition at line 3625 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated [static]

Initial value:

 {
   { "rtp", "rtcp", "no", "stats", NULL },
   rtcp_no_stats_deprecated, NULL,
        NULL }

Definition at line 3635 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_stats_deprecated [static]

Initial value:

 {
   { "rtp", "rtcp", "stats", NULL },
   rtcp_do_stats_deprecated, NULL,
        NULL }

Definition at line 3630 of file rtp.c.

struct ast_cli_entry cli_stun_no_debug_deprecated [static]

Initial value:

 {
   { "stun", "no", "debug", NULL },
   stun_no_debug, NULL,
   NULL }

Definition at line 3640 of file rtp.c.

char debug_usage[] [static]

Initial value:

  "Usage: rtp debug [ip host[:port]]\n"
  "       Enable dumping of all RTP packets to and from host.\n"

Definition at line 3578 of file rtp.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 78 of file rtp.c.

struct { ... } mimeTypes[] [static]

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

char no_debug_usage[] [static]

Initial value:

  "Usage: rtp debug off\n"
  "       Disable all RTP debugging\n"

Definition at line 3582 of file rtp.c.

struct stun_addr packed

struct stun_attr packed

struct stun_header packed

Referenced by get_unaligned_uint16(), get_unaligned_uint32(), put_unaligned_uint16(), and put_unaligned_uint32().

struct rtpPayloadType payloadType

Definition at line 1341 of file rtp.c.

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

char rtcp_debug_usage[] [static]

Initial value:

  "Usage: rtcp debug [ip host[:port]]\n"
  "       Enable dumping of all RTCP packets to and from host.\n"

Definition at line 3594 of file rtp.c.

char rtcp_no_debug_usage[] [static]

Initial value:

  "Usage: rtcp debug off\n"
  "       Disable all RTCP debugging\n"

Definition at line 3598 of file rtp.c.

char rtcp_no_stats_usage[] [static]

Initial value:

  "Usage: rtcp stats off\n"
  "       Disable all RTCP stats\n"

Definition at line 3606 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

  "Usage: rtcp stats\n"
  "       Enable dumping of RTCP stats.\n"

Definition at line 3602 of file rtp.c.

int rtcpdebug [static]

Are we debugging RTCP?

Definition at line 83 of file rtp.c.

struct sockaddr_in rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 88 of file rtp.c.

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 85 of file rtp.c.

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 84 of file rtp.c.

int rtpdebug [static]

Are we debugging?

Definition at line 82 of file rtp.c.

struct sockaddr_in rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 87 of file rtp.c.

int rtpend [static]

Last port for RTP sessions (set in rtp.conf)

Definition at line 81 of file rtp.c.

int rtpstart [static]

First port for RTP sessions (set in rtp.conf)

Definition at line 80 of file rtp.c.

struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static]

Definition at line 1373 of file rtp.c.

Referenced by ast_rtp_codec_getformat(), ast_rtp_lookup_pt(), ast_rtp_pt_default(), and ast_rtp_set_m_type().

char stun_debug_usage[] [static]

Initial value:

  "Usage: stun debug\n"
  "       Enable STUN (Simple Traversal of UDP through NATs) debugging\n"

Definition at line 3586 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

  "Usage: stun debug off\n"
  "       Disable STUN debugging\n"

Definition at line 3590 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1343 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1342 of file rtp.c.

Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), find_subscription_type(), g723_len(), iax2_show_threads(), misdn_cfg_get(), misdn_cfg_get_config_string(), parse_information(), parse_setup(), schedule_delivery(), sla_load_config(), subscription_type2str(), and yyparse().


Generated on Fri Aug 24 02:28:11 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1