Fri Sep 25 19:28:43 2009

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. 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.
struct ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Public function: Send an H.261 fast update request, some devices need this rather than SIP XML.
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)
struct 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)
struct 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):.
struct 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)
struct 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.
struct 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)
struct ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
static int ast_rtp_senddigit_continuation (struct ast_rtp *rtp)
 Send continuation frame for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 remove setting from payload type list if the rtpmap header indicates an unknown media 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 {
   struct rtpPayloadType   payloadType
   char *   subtype
   char *   type
mimeTypes []
static char no_debug_usage []
struct stun_header packed
static char rtcp_debug_usage []
static char rtcp_no_debug_usage []
static char rtcp_no_stats_usage []
static char rtcp_stats_usage []
static int rtcpdebug
static struct sockaddr_in rtcpdebugaddr
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static int rtcpstats
static int rtpdebug
static struct sockaddr_in rtpdebugaddr
static int rtpend
static int rtpstart
static struct rtpPayloadType static_RTP_PT [MAX_RTP_PT]
static char stun_debug_usage []
static char stun_no_debug_usage []
static int stundebug


Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

#define DEFAULT_DTMF_TIMEOUT   3000

samples

Definition at line 76 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 186 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 193 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 194 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

Definition at line 190 of file rtp.c.

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

#define FLAG_HAS_STUN   (1 << 8)

Definition at line 195 of file rtp.c.

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 188 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 189 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_P2P_NEED_DTMF   (1 << 5)

Definition at line 192 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 191 of file rtp.c.

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

#define MAX_TIMESTAMP_SKEW   640

Definition at line 60 of file rtp.c.

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

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 63 of file rtp.c.

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 65 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 64 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 72 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 71 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

Definition at line 67 of file rtp.c.

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

#define RTCP_PT_RR   201

Definition at line 69 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

Definition at line 70 of file rtp.c.

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

#define RTCP_PT_SR   200

Definition at line 68 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 74 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 62 of file rtp.c.

Referenced by ast_rtp_read().

#define STUN_ACCEPT   (1)

Definition at line 259 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 263 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 261 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 262 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 258 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 268 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 269 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 264 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 273 of file rtp.c.

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


Function Documentation

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

Definition at line 366 of file rtp.c.

References stun_addr::addr, stun_addr::family, stun_addr::port, and stun_addr::unused.

Referenced by stun_handle_packet().

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

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

Definition at line 353 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

static AST_LIST_HEAD_STATIC ( protos  ,
ast_rtp_protocol   
) [static]

List of current sessions.

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Todo:
XXX Do a more reasonable calculation on this one Look in RFC 3550 Section A.7 for an example

Definition at line 524 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 517 of file rtp.c.

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

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static, read]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1854 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

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

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  )  [read]

Definition at line 826 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, ast_rtp::f, 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().

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

int ast_rtcp_send_h261fur ( void *  data  ) 

Public function: Send an H.261 fast update request, some devices need this rather than SIP XML.

Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.

Definition at line 2333 of file rtp.c.

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

02334 {
02335    struct ast_rtp *rtp = data;
02336    int res;
02337 
02338    rtp->rtcp->sendfur = 1;
02339    res = ast_rtcp_write(data);
02340    
02341    return res;
02342 }

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

Write and RTCP packet to the far end.

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

Definition at line 2558 of file rtp.c.

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

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

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

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

Send RTCP recepient's report.

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

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

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

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

Send RTCP sender's report.

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

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

size_t ast_rtp_alloc_size ( void   ) 

Get the amount of space required to hold an RTP session.

Returns:
number of bytes required

Definition at line 397 of file rtp.c.

Referenced by process_sdp().

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

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

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

Definition at line 3253 of file rtp.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_codec_pref_getsize(), ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_DTMF_COMPENSATE, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, 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.

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

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2716 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp().

02717 {
02718    if (pt < 0 || pt > MAX_RTP_PT)
02719       return 0; /* bogus payload type */
02720 
02721    if (static_RTP_PT[pt].isAstFormat)
02722       return static_RTP_PT[pt].code;
02723    else
02724       return 0;
02725 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  )  [read]

Definition at line 2711 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02712 {
02713    return &rtp->pref;
02714 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2698 of file rtp.c.

References ast_smoother_free(), ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, 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().

02699 {
02700    int x;
02701    for (x = 0; x < 32; x++) {  /* Ugly way */
02702       rtp->pref.order[x] = prefs->order[x];
02703       rtp->pref.framing[x] = prefs->framing[x];
02704    }
02705    if (rtp->smoother)
02706       ast_smoother_free(rtp->smoother);
02707    rtp->smoother = NULL;
02708    return 0;
02709 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 2115 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_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by __oh323_destroy(), __sip_destroy(), check_user_full(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().

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

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

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 512 of file rtp.c.

References ast_rtp::s.

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

00513 {
00514    return rtp->s;
00515 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  )  [read]

Definition at line 2023 of file rtp.c.

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

Referenced by ast_rtp_read().

02024 {
02025    struct ast_rtp *bridged = NULL;
02026 
02027    ast_mutex_lock(&rtp->bridge_lock);
02028    bridged = rtp->bridged;
02029    ast_mutex_unlock(&rtp->bridge_lock);
02030 
02031    return bridged;
02032 }

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

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

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

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

02006 {
02007    if ((them->sin_family != AF_INET) ||
02008       (them->sin_port != rtp->them.sin_port) ||
02009       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02010       them->sin_family = AF_INET;
02011       them->sin_port = rtp->them.sin_port;
02012       them->sin_addr = rtp->them.sin_addr;
02013       return 1;
02014    }
02015    return 0;
02016 }

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

Return RTCP quality string.

Definition at line 2071 of file rtp.c.

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

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

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

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 567 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 575 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00576 {
00577    return rtp->rtpkeepalive;
00578 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 559 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

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

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

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

02019 {
02020    *us = rtp->us;
02021 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 595 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3783 of file rtp.c.

References ast_cli_register_multiple(), and ast_rtp_reload().

Referenced by main().

03784 {
03785    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03786    ast_rtp_reload();
03787 }

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

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

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

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

Referenced by process_sdp().

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

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

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

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
) [read]

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1714 of file rtp.c.

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

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

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

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

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

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

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

Initializate a RTP session.

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

Definition at line 1977 of file rtp.c.

References ast_rtp_new_with_bindaddr().

01978 {
01979    struct in_addr ia;
01980 
01981    memset(&ia, 0, sizeof(ia));
01982    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01983 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

01878 {
01879    ast_mutex_init(&rtp->bridge_lock);
01880 
01881    rtp->them.sin_family = AF_INET;
01882    rtp->us.sin_family = AF_INET;
01883    rtp->ssrc = ast_random();
01884    rtp->seqno = ast_random() & 0xffff;
01885    ast_set_flag(rtp, FLAG_HAS_DTMF);
01886 
01887    return;
01888 }

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

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 1890 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, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::us, and ast_rtp::us.

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

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

02817 {
02818    struct ast_rtp_protocol *cur;
02819 
02820    AST_LIST_LOCK(&protos);
02821    AST_LIST_TRAVERSE(&protos, cur, list) {   
02822       if (!strcmp(cur->type, proto->type)) {
02823          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02824          AST_LIST_UNLOCK(&protos);
02825          return -1;
02826       }
02827    }
02828    AST_LIST_INSERT_HEAD(&protos, proto, list);
02829    AST_LIST_UNLOCK(&protos);
02830    
02831    return 0;
02832 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2808 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.

Referenced by load_module(), and unload_module().

02809 {
02810    AST_LIST_LOCK(&protos);
02811    AST_LIST_REMOVE(&protos, proto, list);
02812    AST_LIST_UNLOCK(&protos);
02813 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

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

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

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

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

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

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

Definition at line 2609 of file rtp.c.

References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_frame::has_timing_info, 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_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, ast_rtp::them, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

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

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  )  [read]

Definition at line 1101 of file rtp.c.

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

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

int ast_rtp_reload ( void   ) 

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

03719 {
03720    struct ast_config *cfg;
03721    const char *s;
03722 
03723    rtpstart = 5000;
03724    rtpend = 31000;
03725    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03726    cfg = ast_config_load("rtp.conf");
03727    if (cfg) {
03728       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03729          rtpstart = atoi(s);
03730          if (rtpstart < 1024)
03731             rtpstart = 1024;
03732          if (rtpstart > 65535)
03733             rtpstart = 65535;
03734       }
03735       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03736          rtpend = atoi(s);
03737          if (rtpend < 1024)
03738             rtpend = 1024;
03739          if (rtpend > 65535)
03740             rtpend = 65535;
03741       }
03742       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03743          rtcpinterval = atoi(s);
03744          if (rtcpinterval == 0)
03745             rtcpinterval = 0; /* Just so we're clear... it's zero */
03746          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03747             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03748          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03749             rtcpinterval = RTCP_MAX_INTERVALMS;
03750       }
03751       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03752 #ifdef SO_NO_CHECK
03753          if (ast_false(s))
03754             nochecksums = 1;
03755          else
03756             nochecksums = 0;
03757 #else
03758          if (ast_false(s))
03759             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03760 #endif
03761       }
03762       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03763          dtmftimeout = atoi(s);
03764          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03765             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03766                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03767             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03768          };
03769       }
03770       ast_config_destroy(cfg);
03771    }
03772    if (rtpstart >= rtpend) {
03773       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03774       rtpstart = 5000;
03775       rtpend = 31000;
03776    }
03777    if (option_verbose > 1)
03778       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03779    return 0;
03780 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

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

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2575 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2175 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 oh323_digit_begin(), and sip_senddigit_begin().

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2276 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 oh323_digit_end(), and sip_senddigit_end().

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

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 585 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 580 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

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

Activate payload type.

Definition at line 1634 of file rtp.c.

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

Referenced by gtalk_newcall(), and process_sdp().

01635 {
01636    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01637       return; /* bogus payload type */
01638 
01639    ast_mutex_lock(&rtp->bridge_lock);
01640    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01641    ast_mutex_unlock(&rtp->bridge_lock);
01642 } 

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

Definition at line 1994 of file rtp.c.

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

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

01995 {
01996    rtp->them.sin_port = them->sin_port;
01997    rtp->them.sin_addr = them->sin_addr;
01998    if (rtp->rtcp) {
01999       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02000       rtp->rtcp->them.sin_addr = them->sin_addr;
02001    }
02002    rtp->rxseqno = 0;
02003 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 547 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

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

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 553 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

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

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

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

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

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

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 541 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 534 of file rtp.c.

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

Referenced by handle_response_invite().

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

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

Definition at line 600 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_DTMF.

Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), sip_alloc(), and sip_dtmfmode().

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

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

Definition at line 605 of file rtp.c.

References ast_set2_flag, and FLAG_DTMF_COMPENSATE.

Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), and sip_alloc().

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

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 590 of file rtp.c.

References ast_rtp::nat.

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

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

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 610 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 1985 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

01986 {
01987    int res;
01988 
01989    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
01990       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01991    return res;
01992 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Definition at line 2034 of file rtp.c.

References ast_clear_flag, ast_sched_del(), FLAG_P2P_SENT_MARK, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, ast_rtcp::them, and ast_rtp::them.

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

02035 {
02036    if (rtp->rtcp && rtp->rtcp->schedid > 0) {
02037       ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02038       rtp->rtcp->schedid = -1;
02039    }
02040 
02041    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02042    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02043    if (rtp->rtcp) {
02044       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02045       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02046    }
02047    
02048    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02049 }

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

Definition at line 402 of file rtp.c.

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

Referenced by gtalk_update_stun().

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

remove setting from payload type list if the rtpmap header indicates an unknown media type

clear payload type

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

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

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2727 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_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_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().

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

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

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), AST_CONTROL_HOLD, 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_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_channel::spies, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

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

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

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF_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_log(), ast_read(), ast_waitfor_n(), ast_write(), ast_frame::data, ast_frame::datalen, FLAG_P2P_SENT_MARK, ast_frame::frametype, LOG_DEBUG, LOG_NOTICE, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, option_debug, p2p_callback_disable(), p2p_callback_enable(), p2p_set_bridge(), ast_channel::spies, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

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

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

Perform a Packet2Packet RTP write.

Definition at line 1052 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Definition at line 1003 of file rtp.c.

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

Referenced by ast_rtp_read(), and schedule_delivery().

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

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

Definition at line 2155 of file rtp.c.

References ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

02156 {
02157    struct timeval t;
02158    long ms;
02159    if (ast_tvzero(rtp->txcore)) {
02160       rtp->txcore = ast_tvnow();
02161       /* Round to 20ms for nice, pretty timestamps */
02162       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02163    }
02164    /* Use previous txcore if available */
02165    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02166    ms = ast_tvdiff_ms(t, rtp->txcore);
02167    if (ms < 0)
02168       ms = 0;
02169    /* Use what we just got for next time */
02170    rtp->txcore = t;
02171    return (unsigned int) ms;
02172 }

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

Get channel driver interface structure.

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

01458 {
01459    struct ast_rtp_protocol *cur = NULL;
01460 
01461    AST_LIST_LOCK(&protos);
01462    AST_LIST_TRAVERSE(&protos, cur, list) {
01463       if (cur->type == chan->tech->type)
01464          break;
01465    }
01466    AST_LIST_UNLOCK(&protos);
01467 
01468    return cur;
01469 }

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

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

Referenced by bridge_p2p_loop().

03092 {
03093    ast_channel_lock(chan);
03094 
03095    /* Remove the callback from the IO context */
03096    ast_io_remove(rtp->io, iod[0]);
03097 
03098    /* Restore file descriptors */
03099    chan->fds[0] = fds[0];
03100    ast_channel_unlock(chan);
03101 
03102    /* Restore callback mode if previously used */
03103    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03104       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03105 
03106    return 0;
03107 }

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

P2P RTP Callback.

Definition at line 3084 of file rtp.c.

Referenced by bridge_p2p_loop().

03085 {
03086    return 0;
03087 }

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

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

Referenced by bridge_p2p_loop().

03111 {
03112    ast_mutex_lock(&rtp0->bridge_lock);
03113    rtp0->bridged = rtp1;
03114    ast_mutex_unlock(&rtp0->bridge_lock);
03115 
03116    return;
03117 }

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

Definition at line 669 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Process RTP DTMF and events according to RFC 2833.

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

Parameters:
rtp 
data 
len 
seqno 
Returns:

Definition at line 708 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Process Comfort Noise RTP.

This is incomplete at the moment.

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

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

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

Definition at line 655 of file rtp.c.

References rtcpdebugaddr.

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

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

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

Definition at line 3515 of file rtp.c.

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

03515                                                          {
03516    if (argc != 2) {
03517       if (argc != 4)
03518          return RESULT_SHOWUSAGE;
03519       return rtcp_do_debug_ip(fd, argc, argv);
03520    }
03521    rtcpdebug = 1;
03522    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03523    ast_cli(fd, "RTCP Debugging Enabled\n");
03524    return RESULT_SUCCESS;
03525 }

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

Definition at line 3503 of file rtp.c.

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

03503                                                                     {
03504    if (argc != 3) {
03505       if (argc != 5)
03506          return RESULT_SHOWUSAGE;
03507       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03508    }
03509    rtcpdebug = 1;
03510    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03511    ast_cli(fd, "RTCP Debugging Enabled\n");
03512    return RESULT_SUCCESS;
03513 }

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

Definition at line 3460 of file rtp.c.

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

Referenced by rtcp_do_debug().

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

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

Definition at line 3430 of file rtp.c.

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

Referenced by rtcp_do_debug_deprecated().

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

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

Definition at line 3536 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03536                                                          {
03537    if (argc != 2) {
03538       return RESULT_SHOWUSAGE;
03539    }
03540    rtcpstats = 1;
03541    ast_cli(fd, "RTCP Stats Enabled\n");
03542    return RESULT_SUCCESS;
03543 }

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

Definition at line 3527 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03527                                                                     {
03528    if (argc != 3) {
03529       return RESULT_SHOWUSAGE;
03530    }
03531    rtcpstats = 1;
03532    ast_cli(fd, "RTCP Stats Enabled\n");
03533    return RESULT_SUCCESS;
03534 }

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

Definition at line 3563 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03564 {
03565    if (argc != 3)
03566       return RESULT_SHOWUSAGE;
03567    rtcpdebug = 0;
03568    ast_cli(fd,"RTCP Debugging Disabled\n");
03569    return RESULT_SUCCESS;
03570 }

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

Definition at line 3554 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03555 {
03556    if (argc != 4)
03557       return RESULT_SHOWUSAGE;
03558    rtcpdebug = 0;
03559    ast_cli(fd,"RTCP Debugging Disabled\n");
03560    return RESULT_SUCCESS;
03561 }

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

Definition at line 3581 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03582 {
03583    if (argc != 3)
03584       return RESULT_SHOWUSAGE;
03585    rtcpstats = 0;
03586    ast_cli(fd,"RTCP Stats Disabled\n");
03587    return RESULT_SUCCESS;
03588 }

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

Definition at line 3572 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03573 {
03574    if (argc != 4)
03575       return RESULT_SHOWUSAGE;
03576    rtcpstats = 0;
03577    ast_cli(fd,"RTCP Stats Disabled\n");
03578    return RESULT_SUCCESS;
03579 }

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

Definition at line 642 of file rtp.c.

References rtpdebugaddr.

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

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

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

Definition at line 3490 of file rtp.c.

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

03491 {
03492    if (argc != 2) {
03493       if (argc != 4)
03494          return RESULT_SHOWUSAGE;
03495       return rtp_do_debug_ip(fd, argc, argv);
03496    }
03497    rtpdebug = 1;
03498    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03499    ast_cli(fd, "RTP Debugging Enabled\n");
03500    return RESULT_SUCCESS;
03501 }

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

Definition at line 3400 of file rtp.c.

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

Referenced by rtp_do_debug().

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

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

Definition at line 3545 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03546 {
03547    if (argc != 3)
03548       return RESULT_SHOWUSAGE;
03549    rtpdebug = 0;
03550    ast_cli(fd,"RTP Debugging Disabled\n");
03551    return RESULT_SUCCESS;
03552 }

static int rtp_socket ( void   )  [static]

Definition at line 1833 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

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

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

Definition at line 814 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

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

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

Definition at line 615 of file rtp.c.

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

Referenced by process_cisco_dtmf(), and process_rfc2833().

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

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

Definition at line 299 of file rtp.c.

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

Referenced by stun_handle_packet(), and stun_process_attr().

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

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

Definition at line 3590 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03591 {
03592    if (argc != 2) {
03593       return RESULT_SHOWUSAGE;
03594    }
03595    stundebug = 1;
03596    ast_cli(fd, "STUN Debugging Enabled\n");
03597    return RESULT_SUCCESS;
03598 }

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

Definition at line 423 of file rtp.c.

References append_attr_address(), append_attr_string(), ast_log(), ast_verbose(), stun_attr::attr, stun_header::id, stun_header::ies, stun_attr::len, 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(), STUN_USERNAME, and stun_state::username.

Referenced by ast_rtp_read().

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

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

Definition at line 280 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3600 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03601 {
03602    if (argc != 3)
03603       return RESULT_SHOWUSAGE;
03604    stundebug = 0;
03605    ast_cli(fd, "STUN Debugging Disabled\n");
03606    return RESULT_SUCCESS;
03607 }

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

Definition at line 333 of file rtp.c.

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

Referenced by stun_handle_packet().

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

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 390 of file rtp.c.

References ast_random(), and stun_header::id.

Referenced by ast_rtp_stun_request().

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

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

Definition at line 384 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Definition at line 502 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3676 of file rtp.c.

Initial value:

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

Definition at line 3641 of file rtp.c.

Initial value:

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

Definition at line 3651 of file rtp.c.

Initial value:

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

Definition at line 3646 of file rtp.c.

Initial value:

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

Definition at line 3656 of file rtp.c.

Initial value:

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

Definition at line 3666 of file rtp.c.

Initial value:

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

Definition at line 3661 of file rtp.c.

Initial value:

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

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

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 78 of file rtp.c.

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

char no_debug_usage[] [static]

Initial value:

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

Definition at line 3613 of file rtp.c.

struct stun_addr packed

Definition at line 1331 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 3625 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 3629 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 3637 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

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

Referenced by rtcp_debug_test_addr(), rtcp_do_debug(), rtcp_do_debug_deprecated(), rtcp_do_debug_ip(), and rtcp_do_debug_ip_deprecated().

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.

Referenced by rtp_debug_test_addr(), rtp_do_debug(), and rtp_do_debug_ip().

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

char stun_debug_usage[] [static]

Initial value:

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

Definition at line 3617 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3621 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1333 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type


Generated on Fri Sep 25 19:28:44 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.5