Mon Mar 31 07:42:29 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_bridge(), 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 1877 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().

01878 {
01879    struct ast_rtcp *rtcp;
01880 
01881    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01882       return NULL;
01883    rtcp->s = rtp_socket();
01884    rtcp->us.sin_family = AF_INET;
01885    rtcp->them.sin_family = AF_INET;
01886    rtcp->schedid = -1;
01887 
01888    if (rtcp->s < 0) {
01889       free(rtcp);
01890       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01891       return NULL;
01892    }
01893 
01894    return rtcp;
01895 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 827 of file rtp.c.

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

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

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

02361 {
02362    struct ast_rtp *rtp = data;
02363    int res;
02364 
02365    rtp->rtcp->sendfur = 1;
02366    res = ast_rtcp_write(data);
02367    
02368    return res;
02369 }

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

02578 {
02579    struct ast_rtp *rtp = (struct ast_rtp *)data;
02580    int res;
02581    
02582    if (!rtp || !rtp->rtcp)
02583       return 0;
02584 
02585    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02586       res = ast_rtcp_write_sr(data);
02587    else
02588       res = ast_rtcp_write_rr(data);
02589    
02590    return res;
02591 }

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

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

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

Send RTCP sender's report.

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

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

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 3287 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_DTMF_COMPENSATE, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, option_debug, option_verbose, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

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

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2742 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

02743 {
02744    if (pt < 0 || pt > MAX_RTP_PT)
02745       return 0; /* bogus payload type */
02746 
02747    if (static_RTP_PT[pt].isAstFormat)
02748       return static_RTP_PT[pt].code;
02749    else
02750       return 0;
02751 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2737 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02738 {
02739    return &rtp->pref;
02740 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2724 of file rtp.c.

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

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

02725 {
02726    int x;
02727    for (x = 0; x < 32; x++) {  /* Ugly way */
02728       rtp->pref.order[x] = prefs->order[x];
02729       rtp->pref.framing[x] = prefs->framing[x];
02730    }
02731    if (rtp->smoother)
02732       ast_smoother_free(rtp->smoother);
02733    rtp->smoother = NULL;
02734    return 0;
02735 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

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

02144 {
02145    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02146       /*Print some info on the call here */
02147       ast_verbose("  RTP-stats\n");
02148       ast_verbose("* Our Receiver:\n");
02149       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02150       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02151       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02152       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02153       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02154       ast_verbose("  RR-count:    %u\n", rtp->rtcp->rr_count);
02155       ast_verbose("* Our Sender:\n");
02156       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02157       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02158       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->reported_lost);
02159       ast_verbose("  Jitter:      %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0);
02160       ast_verbose("  SR-count:    %u\n", rtp->rtcp->sr_count);
02161       ast_verbose("  RTT:      %f\n", rtp->rtcp->rtt);
02162    }
02163 
02164    if (rtp->smoother)
02165       ast_smoother_free(rtp->smoother);
02166    if (rtp->ioid)
02167       ast_io_remove(rtp->io, rtp->ioid);
02168    if (rtp->s > -1)
02169       close(rtp->s);
02170    if (rtp->rtcp) {
02171       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02172       close(rtp->rtcp->s);
02173       free(rtp->rtcp);
02174       rtp->rtcp=NULL;
02175    }
02176 
02177    ast_mutex_destroy(&rtp->bridge_lock);
02178 
02179    free(rtp);
02180 }

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

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

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

02055 {
02056    struct ast_rtp *bridged = NULL;
02057 
02058    ast_mutex_lock(&rtp->bridge_lock);
02059    bridged = rtp->bridged;
02060    ast_mutex_unlock(&rtp->bridge_lock);
02061 
02062    return bridged;
02063 }

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

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

Referenced by process_sdp().

01718 {
01719    int pt;
01720    
01721    ast_mutex_lock(&rtp->bridge_lock);
01722    
01723    *astFormats = *nonAstFormats = 0;
01724    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01725       if (rtp->current_RTP_PT[pt].isAstFormat) {
01726          *astFormats |= rtp->current_RTP_PT[pt].code;
01727       } else {
01728          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01729       }
01730    }
01731    
01732    ast_mutex_unlock(&rtp->bridge_lock);
01733    
01734    return;
01735 }

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

Definition at line 2036 of file rtp.c.

References ast_rtp::them.

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

02037 {
02038    if ((them->sin_family != AF_INET) ||
02039       (them->sin_port != rtp->them.sin_port) ||
02040       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02041       them->sin_family = AF_INET;
02042       them->sin_port = rtp->them.sin_port;
02043       them->sin_addr = rtp->them.sin_addr;
02044       return 1;
02045    }
02046    return 0;
02047 }

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

Return RTCP quality string.

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

02100 {
02101    /*
02102    *ssrc          our ssrc
02103    *themssrc      their ssrc
02104    *lp            lost packets
02105    *rxjitter      our calculated jitter(rx)
02106    *rxcount       no. received packets
02107    *txjitter      reported jitter of the other end
02108    *txcount       transmitted packets
02109    *rlp           remote lost packets
02110    *rtt           round trip time
02111    */
02112 
02113    if (qual && rtp) {
02114       qual->local_ssrc = rtp->ssrc;
02115       qual->local_jitter = rtp->rxjitter;
02116       qual->local_count = rtp->rxcount;
02117       qual->remote_ssrc = rtp->themssrc;
02118       qual->remote_count = rtp->txcount;
02119       if (rtp->rtcp) {
02120          qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02121          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02122          qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02123          qual->rtt = rtp->rtcp->rtt;
02124       }
02125    }
02126    if (rtp->rtcp) {
02127       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02128          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02129          rtp->ssrc,
02130          rtp->themssrc,
02131          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02132          rtp->rxjitter,
02133          rtp->rxcount,
02134          (double)rtp->rtcp->reported_jitter / 65536.0,
02135          rtp->txcount,
02136          rtp->rtcp->reported_lost,
02137          rtp->rtcp->rtt);
02138       return rtp->rtcp->quality;
02139    } else
02140       return "<Unknown> - RTP/RTCP has already been destroyed";
02141 }

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

02050 {
02051    *us = rtp->us;
02052 }

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

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

Referenced by main().

03826 {
03827    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03828    ast_rtp_reload();
03829 }

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

01760 {
01761    int pt = 0;
01762 
01763    ast_mutex_lock(&rtp->bridge_lock);
01764 
01765    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
01766       code == rtp->rtp_lookup_code_cache_code) {
01767       /* Use our cached mapping, to avoid the overhead of the loop below */
01768       pt = rtp->rtp_lookup_code_cache_result;
01769       ast_mutex_unlock(&rtp->bridge_lock);
01770       return pt;
01771    }
01772 
01773    /* Check the dynamic list first */
01774    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01775       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
01776          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01777          rtp->rtp_lookup_code_cache_code = code;
01778          rtp->rtp_lookup_code_cache_result = pt;
01779          ast_mutex_unlock(&rtp->bridge_lock);
01780          return pt;
01781       }
01782    }
01783 
01784    /* Then the static list */
01785    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01786       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
01787          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01788          rtp->rtp_lookup_code_cache_code = code;
01789          rtp->rtp_lookup_code_cache_result = pt;
01790          ast_mutex_unlock(&rtp->bridge_lock);
01791          return pt;
01792       }
01793    }
01794 
01795    ast_mutex_unlock(&rtp->bridge_lock);
01796 
01797    return -1;
01798 }

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

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

Referenced by process_sdp().

01821 {
01822    int format;
01823    unsigned len;
01824    char *end = buf;
01825    char *start = buf;
01826 
01827    if (!buf || !size)
01828       return NULL;
01829 
01830    snprintf(end, size, "0x%x (", capability);
01831 
01832    len = strlen(end);
01833    end += len;
01834    size -= len;
01835    start = end;
01836 
01837    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01838       if (capability & format) {
01839          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01840 
01841          snprintf(end, size, "%s|", name);
01842          len = strlen(end);
01843          end += len;
01844          size -= len;
01845       }
01846    }
01847 
01848    if (start == end)
01849       snprintf(start, size, "nothing)"); 
01850    else if (size > 1)
01851       *(end -1) = ')';
01852    
01853    return buf;
01854 }

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

01802 {
01803    unsigned int i;
01804 
01805    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01806       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01807          if (isAstFormat &&
01808              (code == AST_FORMAT_G726_AAL2) &&
01809              (options & AST_RTP_OPT_G726_NONSTANDARD))
01810             return "G726-32";
01811          else
01812             return mimeTypes[i].subtype;
01813       }
01814    }
01815 
01816    return "";
01817 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1737 of file rtp.c.

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

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

01738 {
01739    struct rtpPayloadType result;
01740 
01741    result.isAstFormat = result.code = 0;
01742 
01743    if (pt < 0 || pt > MAX_RTP_PT) 
01744       return result; /* bogus payload type */
01745 
01746    /* Start with negotiated codecs */
01747    ast_mutex_lock(&rtp->bridge_lock);
01748    result = rtp->current_RTP_PT[pt];
01749    ast_mutex_unlock(&rtp->bridge_lock);
01750 
01751    /* If it doesn't exist, check our static RTP type list, just in case */
01752    if (!result.code) 
01753       result = static_RTP_PT[pt];
01754 
01755    return result;
01756 }

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

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

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

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02002 {
02003    struct in_addr ia;
02004 
02005    memset(&ia, 0, sizeof(ia));
02006    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02007 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

01902 {
01903    ast_mutex_init(&rtp->bridge_lock);
01904 
01905    rtp->them.sin_family = AF_INET;
01906    rtp->us.sin_family = AF_INET;
01907    rtp->ssrc = ast_random();
01908    rtp->seqno = ast_random() & 0xffff;
01909    ast_set_flag(rtp, FLAG_HAS_DTMF);
01910 
01911    return;
01912 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2018 of file rtp.c.

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

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

02019 {
02020    rtp->set_marker_bit = 1;
02021    rtp->ssrc = ast_random();
02022    return;
02023 }

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

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

02843 {
02844    struct ast_rtp_protocol *cur;
02845 
02846    AST_LIST_LOCK(&protos);
02847    AST_LIST_TRAVERSE(&protos, cur, list) {   
02848       if (!strcmp(cur->type, proto->type)) {
02849          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02850          AST_LIST_UNLOCK(&protos);
02851          return -1;
02852       }
02853    }
02854    AST_LIST_INSERT_HEAD(&protos, proto, list);
02855    AST_LIST_UNLOCK(&protos);
02856    
02857    return 0;
02858 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2834 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.

Referenced by load_module(), and unload_module().

02835 {
02836    AST_LIST_LOCK(&protos);
02837    AST_LIST_REMOVE(&protos, proto, list);
02838    AST_LIST_UNLOCK(&protos);
02839 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1418 of file rtp.c.

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

Referenced by process_sdp().

01419 {
01420    int i;
01421 
01422    if (!rtp)
01423       return;
01424 
01425    ast_mutex_lock(&rtp->bridge_lock);
01426 
01427    for (i = 0; i < MAX_RTP_PT; ++i) {
01428       rtp->current_RTP_PT[i].isAstFormat = 0;
01429       rtp->current_RTP_PT[i].code = 0;
01430    }
01431 
01432    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01433    rtp->rtp_lookup_code_cache_code = 0;
01434    rtp->rtp_lookup_code_cache_result = 0;
01435 
01436    ast_mutex_unlock(&rtp->bridge_lock);
01437 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01459 {
01460    unsigned int i;
01461 
01462    ast_mutex_lock(&dest->bridge_lock);
01463    ast_mutex_lock(&src->bridge_lock);
01464 
01465    for (i=0; i < MAX_RTP_PT; ++i) {
01466       dest->current_RTP_PT[i].isAstFormat = 
01467          src->current_RTP_PT[i].isAstFormat;
01468       dest->current_RTP_PT[i].code = 
01469          src->current_RTP_PT[i].code; 
01470    }
01471    dest->rtp_lookup_code_cache_isAstFormat = 0;
01472    dest->rtp_lookup_code_cache_code = 0;
01473    dest->rtp_lookup_code_cache_result = 0;
01474 
01475    ast_mutex_unlock(&src->bridge_lock);
01476    ast_mutex_unlock(&dest->bridge_lock);
01477 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

01440 {
01441    int i;
01442 
01443    ast_mutex_lock(&rtp->bridge_lock);
01444 
01445    /* Initialize to default payload types */
01446    for (i = 0; i < MAX_RTP_PT; ++i) {
01447       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01448       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01449    }
01450 
01451    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01452    rtp->rtp_lookup_code_cache_code = 0;
01453    rtp->rtp_lookup_code_cache_result = 0;
01454 
01455    ast_mutex_unlock(&rtp->bridge_lock);
01456 }

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

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

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

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1106 of file rtp.c.

References ast_backtrace(), 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, CRASH, 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_ERROR, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::rtcp, rtp_debug_test_addr(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtp::them, ast_rtcp::them, ast_rtp::themssrc, and ast_frame::ts.

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

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

int ast_rtp_reload ( void   ) 

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

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

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

02080 {
02081    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02082    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02083    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02084    rtp->lastts = 0;
02085    rtp->lastdigitts = 0;
02086    rtp->lastrxts = 0;
02087    rtp->lastividtimestamp = 0;
02088    rtp->lastovidtimestamp = 0;
02089    rtp->lasteventseqn = 0;
02090    rtp->lastevent = 0;
02091    rtp->lasttxformat = 0;
02092    rtp->lastrxformat = 0;
02093    rtp->dtmfcount = 0;
02094    rtp->dtmfsamples = 0;
02095    rtp->seqno = 0;
02096    rtp->rxseqno = 0;
02097 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

02595 {
02596    unsigned int *rtpheader;
02597    int hdrlen = 12;
02598    int res;
02599    int payload;
02600    char data[256];
02601    level = 127 - (level & 0x7f);
02602    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
02603 
02604    /* If we have no peer, return immediately */ 
02605    if (!rtp->them.sin_addr.s_addr)
02606       return 0;
02607 
02608    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02609 
02610    /* Get a pointer to the header */
02611    rtpheader = (unsigned int *)data;
02612    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02613    rtpheader[1] = htonl(rtp->lastts);
02614    rtpheader[2] = htonl(rtp->ssrc); 
02615    data[12] = level;
02616    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02617       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02618       if (res <0) 
02619          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));
02620       if (rtp_debug_test_addr(&rtp->them))
02621          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
02622                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
02623          
02624    }
02625    return 0;
02626 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

02267 {
02268    unsigned int *rtpheader;
02269    int hdrlen = 12, res = 0;
02270    char data[256];
02271 
02272    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02273       return 0;
02274 
02275    /* Setup packet to send */
02276    rtpheader = (unsigned int *)data;
02277         rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02278         rtpheader[1] = htonl(rtp->lastdigitts);
02279         rtpheader[2] = htonl(rtp->ssrc);
02280         rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
02281    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02282    
02283    /* Transmit */
02284    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02285    if (res < 0)
02286       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02287          ast_inet_ntoa(rtp->them.sin_addr),
02288          ntohs(rtp->them.sin_port), strerror(errno));
02289    if (rtp_debug_test_addr(&rtp->them))
02290       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02291              ast_inet_ntoa(rtp->them.sin_addr),
02292              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02293 
02294    /* Increment sequence number */
02295    rtp->seqno++;
02296    /* Increment duration */
02297    rtp->send_duration += 160;
02298 
02299    return 0;
02300 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

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

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

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

Referenced by gtalk_newcall(), and process_sdp().

01658 {
01659    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01660       return; /* bogus payload type */
01661 
01662    ast_mutex_lock(&rtp->bridge_lock);
01663    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01664    ast_mutex_unlock(&rtp->bridge_lock);
01665 } 

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

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

02026 {
02027    rtp->them.sin_port = them->sin_port;
02028    rtp->them.sin_addr = them->sin_addr;
02029    if (rtp->rtcp) {
02030       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02031       rtp->rtcp->them.sin_addr = them->sin_addr;
02032    }
02033    rtp->rxseqno = 0;
02034 }

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

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

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

01687 {
01688    unsigned int i;
01689    int found = 0;
01690 
01691    if (pt < 0 || pt > MAX_RTP_PT) 
01692       return -1; /* bogus payload type */
01693    
01694    ast_mutex_lock(&rtp->bridge_lock);
01695 
01696    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01697       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01698           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01699          found = 1;
01700          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01701          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01702              mimeTypes[i].payloadType.isAstFormat &&
01703              (options & AST_RTP_OPT_G726_NONSTANDARD))
01704             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01705          break;
01706       }
01707    }
01708 
01709    ast_mutex_unlock(&rtp->bridge_lock);
01710 
01711    return (found ? 0 : -1);
01712 } 

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

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

Referenced by __oh323_rtp_create(), and sip_alloc().

02010 {
02011    int res;
02012 
02013    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
02014       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
02015    return res;
02016 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

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

02066 {
02067    AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02068 
02069    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02070    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02071    if (rtp->rtcp) {
02072       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02073       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02074    }
02075    
02076    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02077 }

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

01670 {
01671    if (pt < 0 || pt > MAX_RTP_PT)
01672       return; /* bogus payload type */
01673 
01674    ast_mutex_lock(&rtp->bridge_lock);
01675    rtp->current_RTP_PT[pt].isAstFormat = 0;
01676    rtp->current_RTP_PT[pt].code = 0;
01677    ast_mutex_unlock(&rtp->bridge_lock);
01678 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2753 of file rtp.c.

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2182 of file rtp.c.

References t, and ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

02183 {
02184    struct timeval t;
02185    long ms;
02186    if (ast_tvzero(rtp->txcore)) {
02187       rtp->txcore = ast_tvnow();
02188       /* Round to 20ms for nice, pretty timestamps */
02189       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02190    }
02191    /* Use previous txcore if available */
02192    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02193    ms = ast_tvdiff_ms(t, rtp->txcore);
02194    if (ms < 0)
02195       ms = 0;
02196    /* Use what we just got for next time */
02197    rtp->txcore = t;
02198    return (unsigned int) ms;
02199 }

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

Get channel driver interface structure.

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

01481 {
01482    struct ast_rtp_protocol *cur = NULL;
01483 
01484    AST_LIST_LOCK(&protos);
01485    AST_LIST_TRAVERSE(&protos, cur, list) {
01486       if (cur->type == chan->tech->type)
01487          break;
01488    }
01489    AST_LIST_UNLOCK(&protos);
01490 
01491    return cur;
01492 }

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

03119 {
03120    ast_channel_lock(chan);
03121 
03122    /* Remove the callback from the IO context */
03123    ast_io_remove(rtp->io, iod[0]);
03124 
03125    /* Restore file descriptors */
03126    chan->fds[0] = fds[0];
03127    ast_channel_unlock(chan);
03128 
03129    /* Restore callback mode if previously used */
03130    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03131       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03132 
03133    return 0;
03134 }

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

P2P RTP Callback.

Definition at line 3111 of file rtp.c.

Referenced by bridge_p2p_loop().

03112 {
03113    return 0;
03114 }

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

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

Referenced by bridge_p2p_loop().

03138 {
03139    ast_mutex_lock(&rtp0->bridge_lock);
03140    rtp0->bridged = rtp1;
03141    ast_mutex_unlock(&rtp0->bridge_lock);
03142 
03143    return;
03144 }

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

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

03557                                                          {
03558    if (argc != 2) {
03559       if (argc != 4)
03560          return RESULT_SHOWUSAGE;
03561       return rtcp_do_debug_ip(fd, argc, argv);
03562    }
03563    rtcpdebug = 1;
03564    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03565    ast_cli(fd, "RTCP Debugging Enabled\n");
03566    return RESULT_SUCCESS;
03567 }

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

Definition at line 3545 of file rtp.c.

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

03545                                                                     {
03546    if (argc != 3) {
03547       if (argc != 5)
03548          return RESULT_SHOWUSAGE;
03549       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03550    }
03551    rtcpdebug = 1;
03552    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03553    ast_cli(fd, "RTCP Debugging Enabled\n");
03554    return RESULT_SUCCESS;
03555 }

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

Definition at line 3502 of file rtp.c.

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

Referenced by rtcp_do_debug().

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

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

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

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

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

Definition at line 3578 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03578                                                          {
03579    if (argc != 2) {
03580       return RESULT_SHOWUSAGE;
03581    }
03582    rtcpstats = 1;
03583    ast_cli(fd, "RTCP Stats Enabled\n");
03584    return RESULT_SUCCESS;
03585 }

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

Definition at line 3569 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 3605 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03606 {
03607    if (argc != 3)
03608       return RESULT_SHOWUSAGE;
03609    rtcpdebug = 0;
03610    ast_cli(fd,"RTCP Debugging Disabled\n");
03611    return RESULT_SUCCESS;
03612 }

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

Definition at line 3596 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 3623 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03624 {
03625    if (argc != 3)
03626       return RESULT_SHOWUSAGE;
03627    rtcpstats = 0;
03628    ast_cli(fd,"RTCP Stats Disabled\n");
03629    return RESULT_SUCCESS;
03630 }

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

Definition at line 3614 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

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

03533 {
03534    if (argc != 2) {
03535       if (argc != 4)
03536          return RESULT_SHOWUSAGE;
03537       return rtp_do_debug_ip(fd, argc, argv);
03538    }
03539    rtpdebug = 1;
03540    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03541    ast_cli(fd, "RTP Debugging Enabled\n");
03542    return RESULT_SUCCESS;
03543 }

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

Definition at line 3442 of file rtp.c.

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

Referenced by rtp_do_debug().

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

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

Definition at line 3587 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03588 {
03589    if (argc != 3)
03590       return RESULT_SHOWUSAGE;
03591    rtpdebug = 0;
03592    ast_cli(fd,"RTP Debugging Disabled\n");
03593    return RESULT_SUCCESS;
03594 }

static int rtp_socket ( void   )  [static]

Definition at line 1856 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01857 {
01858    int s;
01859    long flags;
01860    s = socket(AF_INET, SOCK_DGRAM, 0);
01861    if (s > -1) {
01862       flags = fcntl(s, F_GETFL);
01863       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01864 #ifdef SO_NO_CHECK
01865       if (nochecksums)
01866          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01867 #endif
01868    }
01869    return s;
01870 }

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

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03633 {
03634    if (argc != 2) {
03635       return RESULT_SHOWUSAGE;
03636    }
03637    stundebug = 1;
03638    ast_cli(fd, "STUN Debugging Enabled\n");
03639    return RESULT_SUCCESS;
03640 }

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

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03643 {
03644    if (argc != 3)
03645       return RESULT_SHOWUSAGE;
03646    stundebug = 0;
03647    ast_cli(fd, "STUN Debugging Disabled\n");
03648    return RESULT_SUCCESS;
03649 }

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 3718 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 3683 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 3693 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 3688 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 3698 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 3708 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 3703 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 3713 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 3651 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 3655 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 1350 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 3667 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 3671 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 3679 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

Definition at line 3675 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 1385 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 3659 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3663 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1352 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

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


Generated on Mon Mar 31 07:42:30 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1