Sat Jul 26 06:14:28 2008

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 (const void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (const void *data)
 Send RTCP recepient's report.
static int ast_rtcp_write_sr (const 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.
void ast_rtp_new_source (struct ast_rtp *rtp)
ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr 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)
 Activate payload type.
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Initiate payload type to a known MIME media type for a codec.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
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)
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 clear payload type
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
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 187 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 194 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 195 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

Definition at line 191 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 196 of file rtp.c.

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 188 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 189 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 190 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 193 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 192 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 260 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 264 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 262 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 263 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 273 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 259 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 269 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 279 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 267 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 274 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 367 of file rtp.c.

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Definition at line 354 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1859 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

01860 {
01861    struct ast_rtcp *rtcp;
01862 
01863    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01864       return NULL;
01865    rtcp->s = rtp_socket();
01866    rtcp->us.sin_family = AF_INET;
01867    rtcp->them.sin_family = AF_INET;
01868    rtcp->schedid = -1;
01869 
01870    if (rtcp->s < 0) {
01871       free(rtcp);
01872       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01873       return NULL;
01874    }
01875 
01876    return rtcp;
01877 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 827 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, 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().

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

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

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

02342 {
02343    struct ast_rtp *rtp = data;
02344    int res;
02345 
02346    rtp->rtcp->sendfur = 1;
02347    res = ast_rtcp_write(data);
02348    
02349    return res;
02350 }

static int ast_rtcp_write ( const 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 2558 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().

02559 {
02560    struct ast_rtp *rtp = (struct ast_rtp *)data;
02561    int res;
02562    
02563    if (!rtp || !rtp->rtcp)
02564       return 0;
02565 
02566    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02567       res = ast_rtcp_write_sr(data);
02568    else
02569       res = ast_rtcp_write_rr(data);
02570    
02571    return res;
02572 }

static int ast_rtcp_write_rr ( const void *  data  )  [static]

Send RTCP recepient'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 2463 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), ast_rtp::cycles, errno, 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().

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

static int ast_rtcp_write_sr ( const void *  data  )  [static]

Send RTCP sender's report.

Definition at line 2353 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), ast_rtp::cycles, errno, 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().

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

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

Referenced by process_sdp().

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

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

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

03280 {
03281    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03282    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03283    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03284    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03285    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03286    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03287    int codec0 = 0, codec1 = 0;
03288    void *pvt0 = NULL, *pvt1 = NULL;
03289 
03290    /* Lock channels */
03291    ast_channel_lock(c0);
03292    while(ast_channel_trylock(c1)) {
03293       ast_channel_unlock(c0);
03294       usleep(1);
03295       ast_channel_lock(c0);
03296    }
03297 
03298    /* Ensure neither channel got hungup during lock avoidance */
03299    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03300       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
03301       ast_channel_unlock(c0);
03302       ast_channel_unlock(c1);
03303       return AST_BRIDGE_FAILED;
03304    }
03305       
03306    /* Find channel driver interfaces */
03307    if (!(pr0 = get_proto(c0))) {
03308       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03309       ast_channel_unlock(c0);
03310       ast_channel_unlock(c1);
03311       return AST_BRIDGE_FAILED;
03312    }
03313    if (!(pr1 = get_proto(c1))) {
03314       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03315       ast_channel_unlock(c0);
03316       ast_channel_unlock(c1);
03317       return AST_BRIDGE_FAILED;
03318    }
03319 
03320    /* Get channel specific interface structures */
03321    pvt0 = c0->tech_pvt;
03322    pvt1 = c1->tech_pvt;
03323 
03324    /* Get audio and video interface (if native bridge is possible) */
03325    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03326    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03327    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03328    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03329 
03330    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03331    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03332       audio_p0_res = AST_RTP_GET_FAILED;
03333    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03334       audio_p1_res = AST_RTP_GET_FAILED;
03335 
03336    /* Check if a bridge is possible (partial/native) */
03337    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03338       /* Somebody doesn't want to play... */
03339       ast_channel_unlock(c0);
03340       ast_channel_unlock(c1);
03341       return AST_BRIDGE_FAILED_NOWARN;
03342    }
03343 
03344    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03345    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03346       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03347       audio_p0_res = AST_RTP_TRY_PARTIAL;
03348    }
03349 
03350    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03351       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03352       audio_p1_res = AST_RTP_TRY_PARTIAL;
03353    }
03354 
03355    /* If both sides are not using the same method of DTMF transmission 
03356     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03357     * --------------------------------------------------
03358     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03359     * |-----------|------------|-----------------------|
03360     * | Inband    | False      | True                  |
03361     * | RFC2833   | True       | True                  |
03362     * | SIP INFO  | False      | False                 |
03363     * --------------------------------------------------
03364     * However, if DTMF from both channels is being monitored by the core, then
03365     * we can still do packet-to-packet bridging, because passing through the 
03366     * core will handle DTMF mode translation.
03367     */
03368    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03369        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03370       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03371          ast_channel_unlock(c0);
03372          ast_channel_unlock(c1);
03373          return AST_BRIDGE_FAILED_NOWARN;
03374       }
03375       audio_p0_res = AST_RTP_TRY_PARTIAL;
03376       audio_p1_res = AST_RTP_TRY_PARTIAL;
03377    }
03378 
03379    /* If we need to feed frames into the core don't do a P2P bridge */
03380    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
03381        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
03382       ast_channel_unlock(c0);
03383       ast_channel_unlock(c1);
03384       return AST_BRIDGE_FAILED_NOWARN;
03385    }
03386 
03387    /* Get codecs from both sides */
03388    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03389    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03390    if (codec0 && codec1 && !(codec0 & codec1)) {
03391       /* Hey, we can't do native bridging if both parties speak different codecs */
03392       if (option_debug)
03393          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03394       ast_channel_unlock(c0);
03395       ast_channel_unlock(c1);
03396       return AST_BRIDGE_FAILED_NOWARN;
03397    }
03398 
03399    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03400    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03401       struct ast_format_list fmt0, fmt1;
03402 
03403       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03404       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03405          if (option_debug)
03406             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03407          ast_channel_unlock(c0);
03408          ast_channel_unlock(c1);
03409          return AST_BRIDGE_FAILED_NOWARN;
03410       }
03411       /* They must also be using the same packetization */
03412       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
03413       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
03414       if (fmt0.cur_ms != fmt1.cur_ms) {
03415          if (option_debug)
03416             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n");
03417          ast_channel_unlock(c0);
03418          ast_channel_unlock(c1);
03419          return AST_BRIDGE_FAILED_NOWARN;
03420       }
03421 
03422       if (option_verbose > 2)
03423          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03424       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03425    } else {
03426       if (option_verbose > 2) 
03427          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03428       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03429    }
03430 
03431    return res;
03432 }

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2723 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

02724 {
02725    if (pt < 0 || pt > MAX_RTP_PT)
02726       return 0; /* bogus payload type */
02727 
02728    if (static_RTP_PT[pt].isAstFormat)
02729       return static_RTP_PT[pt].code;
02730    else
02731       return 0;
02732 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2718 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02719 {
02720    return &rtp->pref;
02721 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2705 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(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

02706 {
02707    int x;
02708    for (x = 0; x < 32; x++) {  /* Ugly way */
02709       rtp->pref.order[x] = prefs->order[x];
02710       rtp->pref.framing[x] = prefs->framing[x];
02711    }
02712    if (rtp->smoother)
02713       ast_smoother_free(rtp->smoother);
02714    rtp->smoother = NULL;
02715    return 0;
02716 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

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

02125 {
02126    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02127       /*Print some info on the call here */
02128       ast_verbose("  RTP-stats\n");
02129       ast_verbose("* Our Receiver:\n");
02130       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02131       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02132       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02133       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02134       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02135       ast_verbose("  RR-count:    %u\n", rtp->rtcp->rr_count);
02136       ast_verbose("* Our Sender:\n");
02137       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02138       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02139       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->reported_lost);
02140       ast_verbose("  Jitter:      %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0);
02141       ast_verbose("  SR-count:    %u\n", rtp->rtcp->sr_count);
02142       ast_verbose("  RTT:      %f\n", rtp->rtcp->rtt);
02143    }
02144 
02145    if (rtp->smoother)
02146       ast_smoother_free(rtp->smoother);
02147    if (rtp->ioid)
02148       ast_io_remove(rtp->io, rtp->ioid);
02149    if (rtp->s > -1)
02150       close(rtp->s);
02151    if (rtp->rtcp) {
02152       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02153       close(rtp->rtcp->s);
02154       free(rtp->rtcp);
02155       rtp->rtcp=NULL;
02156    }
02157 
02158    ast_mutex_destroy(&rtp->bridge_lock);
02159 
02160    free(rtp);
02161 }

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

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00514 {
00515    return rtp->s;
00516 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

Definition at line 2035 of file rtp.c.

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

Referenced by __sip_destroy(), and ast_rtp_read().

02036 {
02037    struct ast_rtp *bridged = NULL;
02038 
02039    ast_mutex_lock(&rtp->bridge_lock);
02040    bridged = rtp->bridged;
02041    ast_mutex_unlock(&rtp->bridge_lock);
02042 
02043    return bridged;
02044 }

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

01700 {
01701    int pt;
01702    
01703    ast_mutex_lock(&rtp->bridge_lock);
01704    
01705    *astFormats = *nonAstFormats = 0;
01706    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01707       if (rtp->current_RTP_PT[pt].isAstFormat) {
01708          *astFormats |= rtp->current_RTP_PT[pt].code;
01709       } else {
01710          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01711       }
01712    }
01713    
01714    ast_mutex_unlock(&rtp->bridge_lock);
01715    
01716    return;
01717 }

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

Definition at line 2017 of file rtp.c.

References ast_rtp::them.

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

02018 {
02019    if ((them->sin_family != AF_INET) ||
02020       (them->sin_port != rtp->them.sin_port) ||
02021       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02022       them->sin_family = AF_INET;
02023       them->sin_port = rtp->them.sin_port;
02024       them->sin_addr = rtp->them.sin_addr;
02025       return 1;
02026    }
02027    return 0;
02028 }

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

Return RTCP quality string.

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

02081 {
02082    /*
02083    *ssrc          our ssrc
02084    *themssrc      their ssrc
02085    *lp            lost packets
02086    *rxjitter      our calculated jitter(rx)
02087    *rxcount       no. received packets
02088    *txjitter      reported jitter of the other end
02089    *txcount       transmitted packets
02090    *rlp           remote lost packets
02091    *rtt           round trip time
02092    */
02093 
02094    if (qual && rtp) {
02095       qual->local_ssrc = rtp->ssrc;
02096       qual->local_jitter = rtp->rxjitter;
02097       qual->local_count = rtp->rxcount;
02098       qual->remote_ssrc = rtp->themssrc;
02099       qual->remote_count = rtp->txcount;
02100       if (rtp->rtcp) {
02101          qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02102          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02103          qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02104          qual->rtt = rtp->rtcp->rtt;
02105       }
02106    }
02107    if (rtp->rtcp) {
02108       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02109          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02110          rtp->ssrc,
02111          rtp->themssrc,
02112          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02113          rtp->rxjitter,
02114          rtp->rxcount,
02115          (double)rtp->rtcp->reported_jitter / 65536.0,
02116          rtp->txcount,
02117          rtp->rtcp->reported_lost,
02118          rtp->rtcp->rtt);
02119       return rtp->rtcp->quality;
02120    } else
02121       return "<Unknown> - RTP/RTCP has already been destroyed";
02122 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 568 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 576 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00577 {
00578    return rtp->rtpkeepalive;
00579 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 560 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

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

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

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

02031 {
02032    *us = rtp->us;
02033 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 596 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3817 of file rtp.c.

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

Referenced by main().

03818 {
03819    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03820    ast_rtp_reload();
03821 }

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

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

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

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

Referenced by process_sdp().

01803 {
01804    int format;
01805    unsigned len;
01806    char *end = buf;
01807    char *start = buf;
01808 
01809    if (!buf || !size)
01810       return NULL;
01811 
01812    snprintf(end, size, "0x%x (", capability);
01813 
01814    len = strlen(end);
01815    end += len;
01816    size -= len;
01817    start = end;
01818 
01819    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01820       if (capability & format) {
01821          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01822 
01823          snprintf(end, size, "%s|", name);
01824          len = strlen(end);
01825          end += len;
01826          size -= len;
01827       }
01828    }
01829 
01830    if (start == end)
01831       snprintf(start, size, "nothing)"); 
01832    else if (size > 1)
01833       *(end -1) = ')';
01834    
01835    return buf;
01836 }

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

01784 {
01785    unsigned int i;
01786 
01787    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01788       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01789          if (isAstFormat &&
01790              (code == AST_FORMAT_G726_AAL2) &&
01791              (options & AST_RTP_OPT_G726_NONSTANDARD))
01792             return "G726-32";
01793          else
01794             return mimeTypes[i].subtype;
01795       }
01796    }
01797 
01798    return "";
01799 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1719 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), rtpPayloadType::isAstFormat, MAX_RTP_PT, and static_RTP_PT.

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

01720 {
01721    struct rtpPayloadType result;
01722 
01723    result.isAstFormat = result.code = 0;
01724 
01725    if (pt < 0 || pt > MAX_RTP_PT) 
01726       return result; /* bogus payload type */
01727 
01728    /* Start with negotiated codecs */
01729    ast_mutex_lock(&rtp->bridge_lock);
01730    result = rtp->current_RTP_PT[pt];
01731    ast_mutex_unlock(&rtp->bridge_lock);
01732 
01733    /* If it doesn't exist, check our static RTP type list, just in case */
01734    if (!result.code) 
01735       result = static_RTP_PT[pt];
01736 
01737    return result;
01738 }

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

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

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

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

References ast_rtp_new_with_bindaddr(), io, and sched.

01984 {
01985    struct in_addr ia;
01986 
01987    memset(&ia, 0, sizeof(ia));
01988    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01989 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

01884 {
01885    ast_mutex_init(&rtp->bridge_lock);
01886 
01887    rtp->them.sin_family = AF_INET;
01888    rtp->us.sin_family = AF_INET;
01889    rtp->ssrc = ast_random();
01890    rtp->seqno = ast_random() & 0xffff;
01891    ast_set_flag(rtp, FLAG_HAS_DTMF);
01892 
01893    return;
01894 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2000 of file rtp.c.

References ast_rtp::set_marker_bit.

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

02001 {
02002    rtp->set_marker_bit = 1;
02003    return;
02004 }

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 1896 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, errno, 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().

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

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

02835 {
02836    struct ast_rtp_protocol *cur;
02837 
02838    AST_LIST_LOCK(&protos);
02839    AST_LIST_TRAVERSE(&protos, cur, list) {   
02840       if (!strcmp(cur->type, proto->type)) {
02841          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02842          AST_LIST_UNLOCK(&protos);
02843          return -1;
02844       }
02845    }
02846    AST_LIST_INSERT_HEAD(&protos, proto, list);
02847    AST_LIST_UNLOCK(&protos);
02848    
02849    return 0;
02850 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2826 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.

Referenced by load_module(), and unload_module().

02827 {
02828    AST_LIST_LOCK(&protos);
02829    AST_LIST_REMOVE(&protos, proto, list);
02830    AST_LIST_UNLOCK(&protos);
02831 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1400 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 gtalk_alloc(), and process_sdp().

01401 {
01402    int i;
01403 
01404    if (!rtp)
01405       return;
01406 
01407    ast_mutex_lock(&rtp->bridge_lock);
01408 
01409    for (i = 0; i < MAX_RTP_PT; ++i) {
01410       rtp->current_RTP_PT[i].isAstFormat = 0;
01411       rtp->current_RTP_PT[i].code = 0;
01412    }
01413 
01414    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01415    rtp->rtp_lookup_code_cache_code = 0;
01416    rtp->rtp_lookup_code_cache_result = 0;
01417 
01418    ast_mutex_unlock(&rtp->bridge_lock);
01419 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01441 {
01442    unsigned int i;
01443 
01444    ast_mutex_lock(&dest->bridge_lock);
01445    ast_mutex_lock(&src->bridge_lock);
01446 
01447    for (i=0; i < MAX_RTP_PT; ++i) {
01448       dest->current_RTP_PT[i].isAstFormat = 
01449          src->current_RTP_PT[i].isAstFormat;
01450       dest->current_RTP_PT[i].code = 
01451          src->current_RTP_PT[i].code; 
01452    }
01453    dest->rtp_lookup_code_cache_isAstFormat = 0;
01454    dest->rtp_lookup_code_cache_code = 0;
01455    dest->rtp_lookup_code_cache_result = 0;
01456 
01457    ast_mutex_unlock(&src->bridge_lock);
01458    ast_mutex_unlock(&dest->bridge_lock);
01459 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

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

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

Definition at line 2609 of file rtp.c.

References AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, 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(), errno, 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::set_marker_bit, ast_rtp::ssrc, ast_rtp::them, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

02610 {
02611    unsigned char *rtpheader;
02612    int hdrlen = 12;
02613    int res;
02614    unsigned int ms;
02615    int pred;
02616    int mark = 0;
02617 
02618    ms = calc_txstamp(rtp, &f->delivery);
02619    /* Default prediction */
02620    if (f->frametype == AST_FRAME_VOICE) {
02621       pred = rtp->lastts + f->samples;
02622 
02623       /* Re-calculate last TS */
02624       rtp->lastts = rtp->lastts + ms * 8;
02625       if (ast_tvzero(f->delivery)) {
02626          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
02627             and if so, go with our prediction */
02628          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
02629             rtp->lastts = pred;
02630          else {
02631             if (option_debug > 2)
02632                ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
02633             mark = 1;
02634          }
02635       }
02636    } else if (f->frametype == AST_FRAME_VIDEO) {
02637       mark = f->subclass & 0x1;
02638       pred = rtp->lastovidtimestamp + f->samples;
02639       /* Re-calculate last TS */
02640       rtp->lastts = rtp->lastts + ms * 90;
02641       /* If it's close to our prediction, go for it */
02642       if (ast_tvzero(f->delivery)) {
02643          if (abs(rtp->lastts - pred) < 7200) {
02644             rtp->lastts = pred;
02645             rtp->lastovidtimestamp += f->samples;
02646          } else {
02647             if (option_debug > 2)
02648                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);
02649             rtp->lastovidtimestamp = rtp->lastts;
02650          }
02651       }
02652    }
02653 
02654    /* If we have been explicitly told to set the marker bit do so */
02655    if (rtp->set_marker_bit) {
02656       mark = 1;
02657       rtp->set_marker_bit = 0;
02658    }
02659 
02660    /* If the timestamp for non-digit packets has moved beyond the timestamp
02661       for digits, update the digit timestamp.
02662    */
02663    if (rtp->lastts > rtp->lastdigitts)
02664       rtp->lastdigitts = rtp->lastts;
02665 
02666    if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
02667       rtp->lastts = f->ts * 8;
02668 
02669    /* Get a pointer to the header */
02670    rtpheader = (unsigned char *)(f->data - hdrlen);
02671 
02672    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
02673    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
02674    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
02675 
02676    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02677       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02678       if (res <0) {
02679          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
02680             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));
02681          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
02682             /* Only give this error message once if we are not RTP debugging */
02683             if (option_debug || rtpdebug)
02684                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));
02685             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
02686          }
02687       } else {
02688          rtp->txcount++;
02689          rtp->txoctetcount +=(res - hdrlen);
02690          
02691          if (rtp->rtcp && rtp->rtcp->schedid < 1) 
02692              rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
02693       }
02694             
02695       if (rtp_debug_test_addr(&rtp->them))
02696          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02697                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
02698    }
02699 
02700    rtp->seqno++;
02701 
02702    return 0;
02703 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1105 of file rtp.c.

References ast_assert, ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, event, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len, ast_frame::len, LOG_DEBUG, 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().

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

int ast_rtp_reload ( void   ) 

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

03753 {
03754    struct ast_config *cfg;
03755    const char *s;
03756 
03757    rtpstart = 5000;
03758    rtpend = 31000;
03759    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03760    cfg = ast_config_load("rtp.conf");
03761    if (cfg) {
03762       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03763          rtpstart = atoi(s);
03764          if (rtpstart < 1024)
03765             rtpstart = 1024;
03766          if (rtpstart > 65535)
03767             rtpstart = 65535;
03768       }
03769       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03770          rtpend = atoi(s);
03771          if (rtpend < 1024)
03772             rtpend = 1024;
03773          if (rtpend > 65535)
03774             rtpend = 65535;
03775       }
03776       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03777          rtcpinterval = atoi(s);
03778          if (rtcpinterval == 0)
03779             rtcpinterval = 0; /* Just so we're clear... it's zero */
03780          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03781             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03782          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03783             rtcpinterval = RTCP_MAX_INTERVALMS;
03784       }
03785       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03786 #ifdef SO_NO_CHECK
03787          if (ast_false(s))
03788             nochecksums = 1;
03789          else
03790             nochecksums = 0;
03791 #else
03792          if (ast_false(s))
03793             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03794 #endif
03795       }
03796       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03797          dtmftimeout = atoi(s);
03798          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03799             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03800                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03801             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03802          };
03803       }
03804       ast_config_destroy(cfg);
03805    }
03806    if (rtpstart >= rtpend) {
03807       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03808       rtpstart = 5000;
03809       rtpend = 31000;
03810    }
03811    if (option_verbose > 1)
03812       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03813    return 0;
03814 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

02061 {
02062    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02063    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02064    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02065    rtp->lastts = 0;
02066    rtp->lastdigitts = 0;
02067    rtp->lastrxts = 0;
02068    rtp->lastividtimestamp = 0;
02069    rtp->lastovidtimestamp = 0;
02070    rtp->lasteventseqn = 0;
02071    rtp->lastevent = 0;
02072    rtp->lasttxformat = 0;
02073    rtp->lastrxformat = 0;
02074    rtp->dtmfcount = 0;
02075    rtp->dtmfsamples = 0;
02076    rtp->seqno = 0;
02077    rtp->rxseqno = 0;
02078 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2575 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, errno, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by do_monitor().

02576 {
02577    unsigned int *rtpheader;
02578    int hdrlen = 12;
02579    int res;
02580    int payload;
02581    char data[256];
02582    level = 127 - (level & 0x7f);
02583    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
02584 
02585    /* If we have no peer, return immediately */ 
02586    if (!rtp->them.sin_addr.s_addr)
02587       return 0;
02588 
02589    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02590 
02591    /* Get a pointer to the header */
02592    rtpheader = (unsigned int *)data;
02593    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02594    rtpheader[1] = htonl(rtp->lastts);
02595    rtpheader[2] = htonl(rtp->ssrc); 
02596    data[12] = level;
02597    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02598       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02599       if (res <0) 
02600          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));
02601       if (rtp_debug_test_addr(&rtp->them))
02602          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
02603                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
02604          
02605    }
02606    return 0;
02607 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2183 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, 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 mgcp_senddigit_begin(), oh323_digit_begin(), and sip_senddigit_begin().

02184 {
02185    unsigned int *rtpheader;
02186    int hdrlen = 12, res = 0, i = 0, payload = 0;
02187    char data[256];
02188 
02189    if ((digit <= '9') && (digit >= '0'))
02190       digit -= '0';
02191    else if (digit == '*')
02192       digit = 10;
02193    else if (digit == '#')
02194       digit = 11;
02195    else if ((digit >= 'A') && (digit <= 'D'))
02196       digit = digit - 'A' + 12;
02197    else if ((digit >= 'a') && (digit <= 'd'))
02198       digit = digit - 'a' + 12;
02199    else {
02200       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02201       return 0;
02202    }
02203 
02204    /* If we have no peer, return immediately */ 
02205    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02206       return 0;
02207 
02208    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02209 
02210    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02211    rtp->send_duration = 160;
02212    
02213    /* Get a pointer to the header */
02214    rtpheader = (unsigned int *)data;
02215    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02216    rtpheader[1] = htonl(rtp->lastdigitts);
02217    rtpheader[2] = htonl(rtp->ssrc); 
02218 
02219    for (i = 0; i < 2; i++) {
02220       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02221       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02222       if (res < 0) 
02223          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02224             ast_inet_ntoa(rtp->them.sin_addr),
02225             ntohs(rtp->them.sin_port), strerror(errno));
02226       if (rtp_debug_test_addr(&rtp->them))
02227          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02228                 ast_inet_ntoa(rtp->them.sin_addr),
02229                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02230       /* Increment sequence number */
02231       rtp->seqno++;
02232       /* Increment duration */
02233       rtp->send_duration += 160;
02234       /* Clear marker bit and set seqno */
02235       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02236    }
02237 
02238    /* Since we received a begin, we can safely store the digit and disable any compensation */
02239    rtp->sending_digit = 1;
02240    rtp->send_digit = digit;
02241    rtp->send_payload = payload;
02242 
02243    return 0;
02244 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

Definition at line 2247 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_verbose(), errno, 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().

02248 {
02249    unsigned int *rtpheader;
02250    int hdrlen = 12, res = 0;
02251    char data[256];
02252 
02253    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02254       return 0;
02255 
02256    /* Setup packet to send */
02257    rtpheader = (unsigned int *)data;
02258         rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02259         rtpheader[1] = htonl(rtp->lastdigitts);
02260         rtpheader[2] = htonl(rtp->ssrc);
02261         rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
02262    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02263    
02264    /* Transmit */
02265    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02266    if (res < 0)
02267       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02268          ast_inet_ntoa(rtp->them.sin_addr),
02269          ntohs(rtp->them.sin_port), strerror(errno));
02270    if (rtp_debug_test_addr(&rtp->them))
02271       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02272              ast_inet_ntoa(rtp->them.sin_addr),
02273              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02274 
02275    /* Increment sequence number */
02276    rtp->seqno++;
02277    /* Increment duration */
02278    rtp->send_duration += 160;
02279 
02280    return 0;
02281 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2284 of file rtp.c.

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

02285 {
02286    unsigned int *rtpheader;
02287    int hdrlen = 12, res = 0, i = 0;
02288    char data[256];
02289    
02290    /* If no address, then bail out */
02291    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02292       return 0;
02293    
02294    if ((digit <= '9') && (digit >= '0'))
02295       digit -= '0';
02296    else if (digit == '*')
02297       digit = 10;
02298    else if (digit == '#')
02299       digit = 11;
02300    else if ((digit >= 'A') && (digit <= 'D'))
02301       digit = digit - 'A' + 12;
02302    else if ((digit >= 'a') && (digit <= 'd'))
02303       digit = digit - 'a' + 12;
02304    else {
02305       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02306       return 0;
02307    }
02308 
02309    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02310 
02311    rtpheader = (unsigned int *)data;
02312    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02313    rtpheader[1] = htonl(rtp->lastdigitts);
02314    rtpheader[2] = htonl(rtp->ssrc);
02315    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02316    /* Set end bit */
02317    rtpheader[3] |= htonl((1 << 23));
02318    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02319    /* Send 3 termination packets */
02320    for (i = 0; i < 3; i++) {
02321       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02322       if (res < 0)
02323          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02324             ast_inet_ntoa(rtp->them.sin_addr),
02325             ntohs(rtp->them.sin_port), strerror(errno));
02326       if (rtp_debug_test_addr(&rtp->them))
02327          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02328                 ast_inet_ntoa(rtp->them.sin_addr),
02329                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02330    }
02331    rtp->sending_digit = 0;
02332    rtp->send_digit = 0;
02333    /* Increment lastdigitts */
02334    rtp->lastdigitts += 960;
02335    rtp->seqno++;
02336 
02337    return res;
02338 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 586 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 581 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

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

01640 {
01641    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01642       return; /* bogus payload type */
01643 
01644    ast_mutex_lock(&rtp->bridge_lock);
01645    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01646    ast_mutex_unlock(&rtp->bridge_lock);
01647 } 

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

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

02007 {
02008    rtp->them.sin_port = them->sin_port;
02009    rtp->them.sin_addr = them->sin_addr;
02010    if (rtp->rtcp) {
02011       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02012       rtp->rtcp->them.sin_addr = them->sin_addr;
02013    }
02014    rtp->rxseqno = 0;
02015 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 548 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

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

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 554 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

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

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

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

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

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

01669 {
01670    unsigned int i;
01671    int found = 0;
01672 
01673    if (pt < 0 || pt > MAX_RTP_PT) 
01674       return -1; /* bogus payload type */
01675    
01676    ast_mutex_lock(&rtp->bridge_lock);
01677 
01678    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01679       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01680           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01681          found = 1;
01682          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01683          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01684              mimeTypes[i].payloadType.isAstFormat &&
01685              (options & AST_RTP_OPT_G726_NONSTANDARD))
01686             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01687          break;
01688       }
01689    }
01690 
01691    ast_mutex_unlock(&rtp->bridge_lock);
01692 
01693    return (found ? 0 : -1);
01694 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 542 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 535 of file rtp.c.

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

Referenced by handle_response_invite().

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

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

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

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

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

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 591 of file rtp.c.

References ast_rtp::nat.

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

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

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 611 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 1991 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

01992 {
01993    int res;
01994 
01995    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
01996       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01997    return res;
01998 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

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

02047 {
02048    AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02049 
02050    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02051    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02052    if (rtp->rtcp) {
02053       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02054       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02055    }
02056    
02057    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02058 }

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

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

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

Definition at line 1651 of file rtp.c.

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

Referenced by process_sdp().

01652 {
01653    if (pt < 0 || pt > MAX_RTP_PT)
01654       return; /* bogus payload type */
01655 
01656    ast_mutex_lock(&rtp->bridge_lock);
01657    rtp->current_RTP_PT[pt].isAstFormat = 0;
01658    rtp->current_RTP_PT[pt].code = 0;
01659    ast_mutex_unlock(&rtp->bridge_lock);
01660 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2734 of file rtp.c.

References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, 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().

02735 {
02736    struct ast_frame *f;
02737    int codec;
02738    int hdrlen = 12;
02739    int subclass;
02740    
02741 
02742    /* If we have no peer, return immediately */ 
02743    if (!rtp->them.sin_addr.s_addr)
02744       return 0;
02745 
02746    /* If there is no data length, return immediately */
02747    if (!_f->datalen) 
02748       return 0;
02749    
02750    /* Make sure we have enough space for RTP header */
02751    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02752       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02753       return -1;
02754    }
02755 
02756    subclass = _f->subclass;
02757    if (_f->frametype == AST_FRAME_VIDEO)
02758       subclass &= ~0x1;
02759 
02760    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02761    if (codec < 0) {
02762       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02763       return -1;
02764    }
02765 
02766    if (rtp->lasttxformat != subclass) {
02767       /* New format, reset the smoother */
02768       if (option_debug)
02769          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02770       rtp->lasttxformat = subclass;
02771       if (rtp->smoother)
02772          ast_smoother_free(rtp->smoother);
02773       rtp->smoother = NULL;
02774    }
02775 
02776    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
02777       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02778       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02779          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02780             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));
02781             return -1;
02782          }
02783          if (fmt.flags)
02784             ast_smoother_set_flags(rtp->smoother, fmt.flags);
02785          if (option_debug)
02786             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));
02787       }
02788    }
02789    if (rtp->smoother) {
02790       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
02791          ast_smoother_feed_be(rtp->smoother, _f);
02792       } else {
02793          ast_smoother_feed(rtp->smoother, _f);
02794       }
02795 
02796       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
02797          if (f->subclass == AST_FORMAT_G722) {
02798             /* G.722 is silllllllllllllly */
02799             f->samples /= 2;
02800          }
02801 
02802          ast_rtp_raw_write(rtp, f, codec);
02803       }
02804    } else {
02805       /* Don't buffer outgoing frames; send them one-per-packet: */
02806       if (_f->offset < hdrlen) {
02807          f = ast_frdup(_f);
02808       } else {
02809          f = _f;
02810       }
02811       if (f->data) {
02812          if (f->subclass == AST_FORMAT_G722) {
02813             /* G.722 is silllllllllllllly */
02814             f->samples /= 2;
02815          }
02816          ast_rtp_raw_write(rtp, f, codec);
02817       }
02818       if (f != _f)
02819          ast_frfree(f);
02820    }
02821       
02822    return 0;
02823 }

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 2853 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_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, 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_channel::audiohooks, 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, ast_channel::monitor, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

02854 {
02855    struct ast_frame *fr = NULL;
02856    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
02857    int oldcodec0 = codec0, oldcodec1 = codec1;
02858    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
02859    struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
02860    
02861    /* Set it up so audio goes directly between the two endpoints */
02862 
02863    /* Test the first channel */
02864    if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
02865       ast_rtp_get_peer(p1, &ac1);
02866       if (vp1)
02867          ast_rtp_get_peer(vp1, &vac1);
02868    } else
02869       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
02870    
02871    /* Test the second channel */
02872    if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
02873       ast_rtp_get_peer(p0, &ac0);
02874       if (vp0)
02875          ast_rtp_get_peer(vp0, &vac0);
02876    } else
02877       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
02878 
02879    /* Now we can unlock and move into our loop */
02880    ast_channel_unlock(c0);
02881    ast_channel_unlock(c1);
02882 
02883    /* Throw our channels into the structure and enter the loop */
02884    cs[0] = c0;
02885    cs[1] = c1;
02886    cs[2] = NULL;
02887    for (;;) {
02888       /* Check if anything changed */
02889       if ((c0->tech_pvt != pvt0) ||
02890           (c1->tech_pvt != pvt1) ||
02891           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
02892           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
02893          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
02894          if (c0->tech_pvt == pvt0)
02895             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02896                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02897          if (c1->tech_pvt == pvt1)
02898             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02899                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02900          return AST_BRIDGE_RETRY;
02901       }
02902 
02903       /* Check if they have changed their address */
02904       ast_rtp_get_peer(p1, &t1);
02905       if (vp1)
02906          ast_rtp_get_peer(vp1, &vt1);
02907       if (pr1->get_codec)
02908          codec1 = pr1->get_codec(c1);
02909       ast_rtp_get_peer(p0, &t0);
02910       if (vp0)
02911          ast_rtp_get_peer(vp0, &vt0);
02912       if (pr0->get_codec)
02913          codec0 = pr0->get_codec(c0);
02914       if ((inaddrcmp(&t1, &ac1)) ||
02915           (vp1 && inaddrcmp(&vt1, &vac1)) ||
02916           (codec1 != oldcodec1)) {
02917          if (option_debug > 1) {
02918             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02919                c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
02920             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
02921                c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
02922             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02923                c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
02924             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02925                c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
02926          }
02927          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)))
02928             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
02929          memcpy(&ac1, &t1, sizeof(ac1));
02930          memcpy(&vac1, &vt1, sizeof(vac1));
02931          oldcodec1 = codec1;
02932       }
02933       if ((inaddrcmp(&t0, &ac0)) ||
02934           (vp0 && inaddrcmp(&vt0, &vac0))) {
02935          if (option_debug > 1) {
02936             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02937                c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
02938             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02939                c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
02940          }
02941          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)))
02942             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
02943          memcpy(&ac0, &t0, sizeof(ac0));
02944          memcpy(&vac0, &vt0, sizeof(vac0));
02945          oldcodec0 = codec0;
02946       }
02947 
02948       /* Wait for frame to come in on the channels */
02949       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
02950          if (!timeoutms) {
02951             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02952                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02953             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02954                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02955             return AST_BRIDGE_RETRY;
02956          }
02957          if (option_debug)
02958             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
02959          if (ast_check_hangup(c0) || ast_check_hangup(c1))
02960             break;
02961          continue;
02962       }
02963       fr = ast_read(who);
02964       other = (who == c0) ? c1 : c0;
02965       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
02966              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
02967               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
02968          /* Break out of bridge */
02969          *fo = fr;
02970          *rc = who;
02971          if (option_debug)
02972             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
02973          if (c0->tech_pvt == pvt0)
02974             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02975                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02976          if (c1->tech_pvt == pvt1)
02977             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02978                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02979          return AST_BRIDGE_COMPLETE;
02980       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02981          if ((fr->subclass == AST_CONTROL_HOLD) ||
02982              (fr->subclass == AST_CONTROL_UNHOLD) ||
02983              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
02984              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
02985             if (fr->subclass == AST_CONTROL_HOLD) {
02986                /* If we someone went on hold we want the other side to reinvite back to us */
02987                if (who == c0)
02988                   pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
02989                else
02990                   pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
02991             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
02992                /* If they went off hold they should go back to being direct */
02993                if (who == c0)
02994                   pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
02995                else
02996                   pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
02997             }
02998             /* Update local address information */
02999             ast_rtp_get_peer(p0, &t0);
03000             memcpy(&ac0, &t0, sizeof(ac0));
03001             ast_rtp_get_peer(p1, &t1);
03002             memcpy(&ac1, &t1, sizeof(ac1));
03003             /* Update codec information */
03004             if (pr0->get_codec && c0->tech_pvt)
03005                oldcodec0 = codec0 = pr0->get_codec(c0);
03006             if (pr1->get_codec && c1->tech_pvt)
03007                oldcodec1 = codec1 = pr1->get_codec(c1);
03008             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03009             ast_frfree(fr);
03010          } else {
03011             *fo = fr;
03012             *rc = who;
03013             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03014             return AST_BRIDGE_COMPLETE;
03015          }
03016       } else {
03017          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03018              (fr->frametype == AST_FRAME_DTMF_END) ||
03019              (fr->frametype == AST_FRAME_VOICE) ||
03020              (fr->frametype == AST_FRAME_VIDEO) ||
03021              (fr->frametype == AST_FRAME_IMAGE) ||
03022              (fr->frametype == AST_FRAME_HTML) ||
03023              (fr->frametype == AST_FRAME_MODEM) ||
03024              (fr->frametype == AST_FRAME_TEXT)) {
03025             ast_write(other, fr);
03026          }
03027          ast_frfree(fr);
03028       }
03029       /* Swap priority */
03030       cs[2] = cs[0];
03031       cs[0] = cs[1];
03032       cs[1] = cs[2];
03033    }
03034 
03035    if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03036       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03037    if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03038       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03039 
03040    return AST_BRIDGE_FAILED;
03041 }

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

References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_unlock, ast_clear_flag, ast_frfree, ast_log(), ast_read(), ast_channel::audiohooks, FLAG_P2P_SENT_MARK, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, p2p_callback_enable(), p2p_set_bridge(), ast_channel::rawreadformat, ast_channel::rawwriteformat, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

03140 {
03141    struct ast_frame *fr = NULL;
03142    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03143    int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
03144    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03145    int p0_callback = 0, p1_callback = 0;
03146    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03147 
03148    /* Okay, setup each RTP structure to do P2P forwarding */
03149    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03150    p2p_set_bridge(p0, p1);
03151    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03152    p2p_set_bridge(p1, p0);
03153 
03154    /* Activate callback modes if possible */
03155    p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03156    p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03157 
03158    /* Now let go of the channel locks and be on our way */
03159    ast_channel_unlock(c0);
03160    ast_channel_unlock(c1);
03161 
03162    /* Go into a loop forwarding frames until we don't need to anymore */
03163    cs[0] = c0;
03164    cs[1] = c1;
03165    cs[2] = NULL;
03166    for (;;) {
03167       /* If the underlying formats have changed force this bridge to break */
03168       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
03169          ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n");
03170          res = AST_BRIDGE_FAILED_NOWARN;
03171          break;
03172       }
03173       /* Check if anything changed */
03174       if ((c0->tech_pvt != pvt0) ||
03175           (c1->tech_pvt != pvt1) ||
03176           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03177           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03178          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03179          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03180             ast_frfree(fr);
03181          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03182             ast_frfree(fr);
03183          res = AST_BRIDGE_RETRY;
03184          break;
03185       }
03186       /* Wait on a channel to feed us a frame */
03187       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03188          if (!timeoutms) {
03189             res = AST_BRIDGE_RETRY;
03190             break;
03191          }
03192          if (option_debug)
03193             ast_log(LOG_NOTICE, "Ooh, empty read...\n");
03194          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03195             break;
03196          continue;
03197       }
03198       /* Read in frame from channel */
03199       fr = ast_read(who);
03200       other = (who == c0) ? c1 : c0;
03201       /* Dependong on the frame we may need to break out of our bridge */
03202       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03203              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03204              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03205          /* Record received frame and who */
03206          *fo = fr;
03207          *rc = who;
03208          if (option_debug)
03209             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03210          res = AST_BRIDGE_COMPLETE;
03211          break;
03212       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03213          if ((fr->subclass == AST_CONTROL_HOLD) ||
03214              (fr->subclass == AST_CONTROL_UNHOLD) ||
03215              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03216              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03217             /* If we are going on hold, then break callback mode and P2P bridging */
03218             if (fr->subclass == AST_CONTROL_HOLD) {
03219                if (p0_callback)
03220                   p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03221                if (p1_callback)
03222                   p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03223                p2p_set_bridge(p0, NULL);
03224                p2p_set_bridge(p1, NULL);
03225             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03226                /* If we are off hold, then go back to callback mode and P2P bridging */
03227                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03228                p2p_set_bridge(p0, p1);
03229                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03230                p2p_set_bridge(p1, p0);
03231                p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03232                p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03233             }
03234             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03235             ast_frfree(fr);
03236          } else {
03237             *fo = fr;
03238             *rc = who;
03239             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03240             res = AST_BRIDGE_COMPLETE;
03241             break;
03242          }
03243       } else {
03244          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03245              (fr->frametype == AST_FRAME_DTMF_END) ||
03246              (fr->frametype == AST_FRAME_VOICE) ||
03247              (fr->frametype == AST_FRAME_VIDEO) ||
03248              (fr->frametype == AST_FRAME_IMAGE) ||
03249              (fr->frametype == AST_FRAME_HTML) ||
03250              (fr->frametype == AST_FRAME_MODEM) ||
03251              (fr->frametype == AST_FRAME_TEXT)) {
03252             ast_write(other, fr);
03253          }
03254 
03255          ast_frfree(fr);
03256       }
03257       /* Swap priority */
03258       cs[2] = cs[0];
03259       cs[0] = cs[1];
03260       cs[1] = cs[2];
03261    }
03262 
03263    /* If we are totally avoiding the core, then restore our link to it */
03264    if (p0_callback)
03265       p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03266    if (p1_callback)
03267       p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03268 
03269    /* Break out of the direct bridge */
03270    p2p_set_bridge(p0, NULL);
03271    p2p_set_bridge(p1, NULL);
03272 
03273    return res;
03274 }

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 1052 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, ast_rtp::current_RTP_PT, errno, 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().

01053 {
01054    int res = 0, payload = 0, bridged_payload = 0, mark;
01055    struct rtpPayloadType rtpPT;
01056    int reconstruct = ntohl(rtpheader[0]);
01057 
01058    /* Get fields from packet */
01059    payload = (reconstruct & 0x7f0000) >> 16;
01060    mark = (((reconstruct & 0x800000) >> 23) != 0);
01061 
01062    /* Check what the payload value should be */
01063    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01064 
01065    /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
01066    if (!bridged->current_RTP_PT[payload].code)
01067       return -1;
01068 
01069    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01070    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01071       return -1;
01072 
01073    /* Otherwise adjust bridged payload to match */
01074    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01075 
01076    /* If the mark bit has not been sent yet... do it now */
01077    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01078       mark = 1;
01079       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01080    }
01081 
01082    /* Reconstruct part of the packet */
01083    reconstruct &= 0xFF80FFFF;
01084    reconstruct |= (bridged_payload << 16);
01085    reconstruct |= (mark << 23);
01086    rtpheader[0] = htonl(reconstruct);
01087 
01088    /* Send the packet back out */
01089    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01090    if (res < 0) {
01091       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01092          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));
01093       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01094          if (option_debug || rtpdebug)
01095             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));
01096          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01097       }
01098       return 0;
01099    } else if (rtp_debug_test_addr(&bridged->them))
01100          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);
01101 
01102    return 0;
01103 }

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

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

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

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

Definition at line 2163 of file rtp.c.

References t, and ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

02164 {
02165    struct timeval t;
02166    long ms;
02167    if (ast_tvzero(rtp->txcore)) {
02168       rtp->txcore = ast_tvnow();
02169       /* Round to 20ms for nice, pretty timestamps */
02170       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02171    }
02172    /* Use previous txcore if available */
02173    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02174    ms = ast_tvdiff_ms(t, rtp->txcore);
02175    if (ms < 0)
02176       ms = 0;
02177    /* Use what we just got for next time */
02178    rtp->txcore = t;
02179    return (unsigned int) ms;
02180 }

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

Get channel driver interface structure.

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

01463 {
01464    struct ast_rtp_protocol *cur = NULL;
01465 
01466    AST_LIST_LOCK(&protos);
01467    AST_LIST_TRAVERSE(&protos, cur, list) {
01468       if (cur->type == chan->tech->type)
01469          break;
01470    }
01471    AST_LIST_UNLOCK(&protos);
01472 
01473    return cur;
01474 }

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

03111 {
03112    ast_channel_lock(chan);
03113 
03114    /* Remove the callback from the IO context */
03115    ast_io_remove(rtp->io, iod[0]);
03116 
03117    /* Restore file descriptors */
03118    chan->fds[0] = fds[0];
03119    ast_channel_unlock(chan);
03120 
03121    /* Restore callback mode if previously used */
03122    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03123       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03124 
03125    return 0;
03126 }

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

P2P RTP Callback.

Definition at line 3103 of file rtp.c.

Referenced by bridge_p2p_loop().

03104 {
03105    return 0;
03106 }

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

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

Referenced by bridge_p2p_loop().

03130 {
03131    ast_mutex_lock(&rtp0->bridge_lock);
03132    rtp0->bridged = rtp1;
03133    ast_mutex_unlock(&rtp0->bridge_lock);
03134 
03135    return;
03136 }

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

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

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

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

References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_null_frame, 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().

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

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

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

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

Definition at line 656 of file rtp.c.

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

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

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

Definition at line 3549 of file rtp.c.

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

03549                                                          {
03550    if (argc != 2) {
03551       if (argc != 4)
03552          return RESULT_SHOWUSAGE;
03553       return rtcp_do_debug_ip(fd, argc, argv);
03554    }
03555    rtcpdebug = 1;
03556    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03557    ast_cli(fd, "RTCP Debugging Enabled\n");
03558    return RESULT_SUCCESS;
03559 }

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

Definition at line 3537 of file rtp.c.

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

03537                                                                     {
03538    if (argc != 3) {
03539       if (argc != 5)
03540          return RESULT_SHOWUSAGE;
03541       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03542    }
03543    rtcpdebug = 1;
03544    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03545    ast_cli(fd, "RTCP Debugging Enabled\n");
03546    return RESULT_SUCCESS;
03547 }

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

Definition at line 3494 of file rtp.c.

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

Referenced by rtcp_do_debug().

03495 {
03496    struct hostent *hp;
03497    struct ast_hostent ahp;
03498    int port = 0;
03499    char *p, *arg;
03500    if (argc != 4)
03501       return RESULT_SHOWUSAGE;
03502 
03503    arg = argv[3];
03504    p = strstr(arg, ":");
03505    if (p) {
03506       *p = '\0';
03507       p++;
03508       port = atoi(p);
03509    }
03510    hp = ast_gethostbyname(arg, &ahp);
03511    if (hp == NULL)
03512       return RESULT_SHOWUSAGE;
03513    rtcpdebugaddr.sin_family = AF_INET;
03514    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03515    rtcpdebugaddr.sin_port = htons(port);
03516    if (port == 0)
03517       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03518    else
03519       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03520    rtcpdebug = 1;
03521    return RESULT_SUCCESS;
03522 }

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

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

03465 {
03466    struct hostent *hp;
03467    struct ast_hostent ahp;
03468    int port = 0;
03469    char *p, *arg;
03470    if (argc != 5)
03471       return RESULT_SHOWUSAGE;
03472 
03473    arg = argv[4];
03474    p = strstr(arg, ":");
03475    if (p) {
03476       *p = '\0';
03477       p++;
03478       port = atoi(p);
03479    }
03480    hp = ast_gethostbyname(arg, &ahp);
03481    if (hp == NULL)
03482       return RESULT_SHOWUSAGE;
03483    rtcpdebugaddr.sin_family = AF_INET;
03484    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03485    rtcpdebugaddr.sin_port = htons(port);
03486    if (port == 0)
03487       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03488    else
03489       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03490    rtcpdebug = 1;
03491    return RESULT_SUCCESS;
03492 }

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

Definition at line 3570 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03570                                                          {
03571    if (argc != 2) {
03572       return RESULT_SHOWUSAGE;
03573    }
03574    rtcpstats = 1;
03575    ast_cli(fd, "RTCP Stats Enabled\n");
03576    return RESULT_SUCCESS;
03577 }

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

Definition at line 3561 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03561                                                                     {
03562    if (argc != 3) {
03563       return RESULT_SHOWUSAGE;
03564    }
03565    rtcpstats = 1;
03566    ast_cli(fd, "RTCP Stats Enabled\n");
03567    return RESULT_SUCCESS;
03568 }

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

Definition at line 3597 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03598 {
03599    if (argc != 3)
03600       return RESULT_SHOWUSAGE;
03601    rtcpdebug = 0;
03602    ast_cli(fd,"RTCP Debugging Disabled\n");
03603    return RESULT_SUCCESS;
03604 }

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

Definition at line 3588 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03589 {
03590    if (argc != 4)
03591       return RESULT_SHOWUSAGE;
03592    rtcpdebug = 0;
03593    ast_cli(fd,"RTCP Debugging Disabled\n");
03594    return RESULT_SUCCESS;
03595 }

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

Definition at line 3615 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03616 {
03617    if (argc != 3)
03618       return RESULT_SHOWUSAGE;
03619    rtcpstats = 0;
03620    ast_cli(fd,"RTCP Stats Disabled\n");
03621    return RESULT_SUCCESS;
03622 }

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

Definition at line 3606 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03607 {
03608    if (argc != 4)
03609       return RESULT_SHOWUSAGE;
03610    rtcpstats = 0;
03611    ast_cli(fd,"RTCP Stats Disabled\n");
03612    return RESULT_SUCCESS;
03613 }

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

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

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

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

Definition at line 3524 of file rtp.c.

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

03525 {
03526    if (argc != 2) {
03527       if (argc != 4)
03528          return RESULT_SHOWUSAGE;
03529       return rtp_do_debug_ip(fd, argc, argv);
03530    }
03531    rtpdebug = 1;
03532    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03533    ast_cli(fd, "RTP Debugging Enabled\n");
03534    return RESULT_SUCCESS;
03535 }

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

Definition at line 3434 of file rtp.c.

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

Referenced by rtp_do_debug().

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

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

Definition at line 3579 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03580 {
03581    if (argc != 3)
03582       return RESULT_SHOWUSAGE;
03583    rtpdebug = 0;
03584    ast_cli(fd,"RTP Debugging Disabled\n");
03585    return RESULT_SUCCESS;
03586 }

static int rtp_socket ( void   )  [static]

Definition at line 1838 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01839 {
01840    int s;
01841    long flags;
01842    s = socket(AF_INET, SOCK_DGRAM, 0);
01843    if (s > -1) {
01844       flags = fcntl(s, F_GETFL);
01845       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01846 #ifdef SO_NO_CHECK
01847       if (nochecksums)
01848          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01849 #endif
01850    }
01851    return s;
01852 }

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

Definition at line 815 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

00816 {
00817    struct ast_rtp *rtp = cbdata;
00818    struct ast_frame *f;
00819    f = ast_rtp_read(rtp);
00820    if (f) {
00821       if (rtp->callback)
00822          rtp->callback(rtp, f, rtp->data);
00823    }
00824    return 1;
00825 }

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

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

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

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

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

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

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

Definition at line 3624 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03625 {
03626    if (argc != 2) {
03627       return RESULT_SHOWUSAGE;
03628    }
03629    stundebug = 1;
03630    ast_cli(fd, "STUN Debugging Enabled\n");
03631    return RESULT_SUCCESS;
03632 }

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

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

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

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

Definition at line 281 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3634 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03635 {
03636    if (argc != 3)
03637       return RESULT_SHOWUSAGE;
03638    stundebug = 0;
03639    ast_cli(fd, "STUN Debugging Disabled\n");
03640    return RESULT_SUCCESS;
03641 }

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

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

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

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 391 of file rtp.c.

References ast_random(), and stun_header::id.

Referenced by ast_rtp_stun_request().

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

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

Definition at line 385 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Definition at line 503 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3710 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 3675 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 3685 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 3680 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 3690 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 3700 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 3695 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 3705 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 3643 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 3647 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 1334 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 3659 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 3663 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 3671 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

Definition at line 3667 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 1368 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 3651 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3655 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1336 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1335 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(), load_module(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), parse_information(), parse_setup(), schedule_delivery(), sla_load_config(), subscription_type2str(), and yyparse().


Generated on Sat Jul 26 06:14:29 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1