Thu May 14 14:50:15 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"

Go to the source code of this file.

Data Structures

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

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 unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
static int ast_rtcp_write (const void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (const void *data)
 Send RTCP recepient's report.
static int ast_rtcp_write_sr (const void *data)
 Send RTCP sender's report.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
enum ast_bridge_result ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
int ast_rtp_codec_getformat (int pt)
ast_codec_prefast_rtp_codec_getpref (struct ast_rtp *rtp)
int ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs)
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_early_bridge (struct ast_channel *dest, struct ast_channel *src)
 If possible, create an early bridge directly between the devices without having to send a re-invite later.
int ast_rtp_fd (struct ast_rtp *rtp)
ast_rtpast_rtp_get_bridged (struct ast_rtp *rtp)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
 Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
int ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
char * ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual)
 Return RTCP quality string.
int ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp)
 Get rtp hold timeout.
int ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp)
 Get RTP keepalive interval.
int ast_rtp_get_rtptimeout (struct ast_rtp *rtp)
 Get rtp timeout.
void ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us)
int ast_rtp_getnat (struct ast_rtp *rtp)
void ast_rtp_init (void)
 Initialize the RTP system in Asterisk.
int ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code)
 Looks up an RTP code out of our *static* outbound list.
char * ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options)
 Build a string of MIME subtype names from a capability list.
const char * ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code, enum ast_rtp_options options)
 Mapping an Asterisk code into a MIME subtype (string):.
rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
 Mapping between RTP payload format codes and Asterisk codes:.
int ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media)
ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
void ast_rtp_new_init (struct ast_rtp *rtp)
 Initialize a new RTP structure.
void ast_rtp_new_source (struct ast_rtp *rtp)
ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
 Initializate a RTP session using an in_addr structure.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register interface to channel driver.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister interface to channel driver.
void ast_rtp_pt_clear (struct ast_rtp *rtp)
 Setting RTP payload types from lines in a SDP description:.
void ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src)
 Copy payload types between RTP structures.
void ast_rtp_pt_default (struct ast_rtp *rtp)
 Set payload types to defaults.
static int ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec)
ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
static int ast_rtp_senddigit_continuation (struct ast_rtp *rtp)
 Send continuation frame for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Activate payload type.
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Initiate payload type to a known MIME media type for a codec.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 clear payload type
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
static enum ast_bridge_result bridge_native_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for true native bridge (reinvite).
static enum ast_bridge_result bridge_p2p_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for partial native bridge (packet2packet).
static int bridge_p2p_rtp_write (struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen)
 Perform a Packet2Packet RTP write.
static void calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
static struct ast_rtp_protocolget_proto (struct ast_channel *chan)
 Get channel driver interface structure.
static int p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
 Helper function to switch a channel and RTP stream out of callback mode.
static int p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
 P2P RTP Callback.
static void p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1)
 Helper function that sets what an RTP structure is bridged to.
static struct ast_frameprocess_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len)
static struct ast_frameprocess_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp)
 Process RTP DTMF and events according to RFC 2833.
static struct ast_frameprocess_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len)
 Process Comfort Noise RTP.
static int rtcp_debug_test_addr (struct sockaddr_in *addr)
static int rtcp_do_debug (int fd, int argc, char *argv[])
static int rtcp_do_debug_deprecated (int fd, int argc, char *argv[])
static int rtcp_do_debug_ip (int fd, int argc, char *argv[])
static int rtcp_do_debug_ip_deprecated (int fd, int argc, char *argv[])
static int rtcp_do_stats (int fd, int argc, char *argv[])
static int rtcp_do_stats_deprecated (int fd, int argc, char *argv[])
static int rtcp_no_debug (int fd, int argc, char *argv[])
static int rtcp_no_debug_deprecated (int fd, int argc, char *argv[])
static int rtcp_no_stats (int fd, int argc, char *argv[])
static int rtcp_no_stats_deprecated (int fd, int argc, char *argv[])
static int rtp_debug_test_addr (struct sockaddr_in *addr)
static int rtp_do_debug (int fd, int argc, char *argv[])
static int rtp_do_debug_ip (int fd, int argc, char *argv[])
static int rtp_no_debug (int fd, int argc, char *argv[])
static int rtp_socket (void)
static int rtpread (int *id, int fd, short events, void *cbdata)
static struct ast_framesend_dtmf (struct ast_rtp *rtp, enum ast_frame_type type)
static const char * stun_attr2str (int msg)
static int stun_do_debug (int fd, int argc, char *argv[])
static int stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len)
static const char * stun_msg2str (int msg)
static int stun_no_debug (int fd, int argc, char *argv[])
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
static void stun_req_id (struct stun_header *req)
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)

Variables

static struct ast_cli_entry cli_rtp []
static struct ast_cli_entry cli_rtp_no_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated
static struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated
static struct ast_cli_entry cli_rtp_rtcp_stats_deprecated
static struct ast_cli_entry cli_stun_no_debug_deprecated
static char debug_usage []
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
struct {
   rtpPayloadType   payloadType
   char *   subtype
   char *   type
mimeTypes []
static char no_debug_usage []
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 p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 194 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

Definition at line 190 of file rtp.c.

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

#define FLAG_HAS_STUN   (1 << 8)

Definition at line 195 of file rtp.c.

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 187 of file rtp.c.

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

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 188 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 189 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_P2P_NEED_DTMF   (1 << 5)

Definition at line 192 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 191 of file rtp.c.

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

#define MAX_TIMESTAMP_SKEW   640

Definition at line 60 of file rtp.c.

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

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 63 of file rtp.c.

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 65 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 64 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 72 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 71 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

Definition at line 67 of file rtp.c.

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

#define RTCP_PT_RR   201

Definition at line 69 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

Definition at line 70 of file rtp.c.

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

#define RTCP_PT_SR   200

Definition at line 68 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 74 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 62 of file rtp.c.

Referenced by ast_rtp_read().

#define STUN_ACCEPT   (1)

Definition at line 259 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 263 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 261 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 262 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 258 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 268 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 269 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 264 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 273 of file rtp.c.

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


Function Documentation

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

Definition at line 366 of file rtp.c.

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Definition at line 353 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 524 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 517 of file rtp.c.

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

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1876 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

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

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 825 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, f, ast_rtp::f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::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().

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

int ast_rtcp_send_h261fur ( void *  data  ) 

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

Definition at line 2369 of file rtp.c.

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

02370 {
02371    struct ast_rtp *rtp = data;
02372    int res;
02373 
02374    rtp->rtcp->sendfur = 1;
02375    res = ast_rtcp_write(data);
02376    
02377    return res;
02378 }

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

02587 {
02588    struct ast_rtp *rtp = (struct ast_rtp *)data;
02589    int res;
02590    
02591    if (!rtp || !rtp->rtcp)
02592       return 0;
02593 
02594    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02595       res = ast_rtcp_write_sr(data);
02596    else
02597       res = ast_rtcp_write_rr(data);
02598    
02599    return res;
02600 }

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

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

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

Send RTCP sender's report.

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

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

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

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

03348 {
03349    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03350    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03351    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03352    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03353    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03354    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03355    int codec0 = 0, codec1 = 0;
03356    void *pvt0 = NULL, *pvt1 = NULL;
03357 
03358    /* Lock channels */
03359    ast_channel_lock(c0);
03360    while(ast_channel_trylock(c1)) {
03361       ast_channel_unlock(c0);
03362       usleep(1);
03363       ast_channel_lock(c0);
03364    }
03365 
03366    /* Ensure neither channel got hungup during lock avoidance */
03367    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03368       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
03369       ast_channel_unlock(c0);
03370       ast_channel_unlock(c1);
03371       return AST_BRIDGE_FAILED;
03372    }
03373       
03374    /* Find channel driver interfaces */
03375    if (!(pr0 = get_proto(c0))) {
03376       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03377       ast_channel_unlock(c0);
03378       ast_channel_unlock(c1);
03379       return AST_BRIDGE_FAILED;
03380    }
03381    if (!(pr1 = get_proto(c1))) {
03382       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03383       ast_channel_unlock(c0);
03384       ast_channel_unlock(c1);
03385       return AST_BRIDGE_FAILED;
03386    }
03387 
03388    /* Get channel specific interface structures */
03389    pvt0 = c0->tech_pvt;
03390    pvt1 = c1->tech_pvt;
03391 
03392    /* Get audio and video interface (if native bridge is possible) */
03393    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03394    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03395    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03396    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03397 
03398    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03399    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03400       audio_p0_res = AST_RTP_GET_FAILED;
03401    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03402       audio_p1_res = AST_RTP_GET_FAILED;
03403 
03404    /* Check if a bridge is possible (partial/native) */
03405    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03406       /* Somebody doesn't want to play... */
03407       ast_channel_unlock(c0);
03408       ast_channel_unlock(c1);
03409       return AST_BRIDGE_FAILED_NOWARN;
03410    }
03411 
03412    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03413    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03414       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03415       audio_p0_res = AST_RTP_TRY_PARTIAL;
03416    }
03417 
03418    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03419       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03420       audio_p1_res = AST_RTP_TRY_PARTIAL;
03421    }
03422 
03423    /* If both sides are not using the same method of DTMF transmission 
03424     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03425     * --------------------------------------------------
03426     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03427     * |-----------|------------|-----------------------|
03428     * | Inband    | False      | True                  |
03429     * | RFC2833   | True       | True                  |
03430     * | SIP INFO  | False      | False                 |
03431     * --------------------------------------------------
03432     * However, if DTMF from both channels is being monitored by the core, then
03433     * we can still do packet-to-packet bridging, because passing through the 
03434     * core will handle DTMF mode translation.
03435     */
03436    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03437        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03438       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03439          ast_channel_unlock(c0);
03440          ast_channel_unlock(c1);
03441          return AST_BRIDGE_FAILED_NOWARN;
03442       }
03443       audio_p0_res = AST_RTP_TRY_PARTIAL;
03444       audio_p1_res = AST_RTP_TRY_PARTIAL;
03445    }
03446 
03447    /* If we need to feed frames into the core don't do a P2P bridge */
03448    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
03449        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
03450       ast_channel_unlock(c0);
03451       ast_channel_unlock(c1);
03452       return AST_BRIDGE_FAILED_NOWARN;
03453    }
03454 
03455    /* Get codecs from both sides */
03456    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03457    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03458    if (codec0 && codec1 && !(codec0 & codec1)) {
03459       /* Hey, we can't do native bridging if both parties speak different codecs */
03460       if (option_debug)
03461          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03462       ast_channel_unlock(c0);
03463       ast_channel_unlock(c1);
03464       return AST_BRIDGE_FAILED_NOWARN;
03465    }
03466 
03467    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03468    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03469       struct ast_format_list fmt0, fmt1;
03470 
03471       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03472       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03473          if (option_debug)
03474             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03475          ast_channel_unlock(c0);
03476          ast_channel_unlock(c1);
03477          return AST_BRIDGE_FAILED_NOWARN;
03478       }
03479       /* They must also be using the same packetization */
03480       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
03481       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
03482       if (fmt0.cur_ms != fmt1.cur_ms) {
03483          if (option_debug)
03484             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n");
03485          ast_channel_unlock(c0);
03486          ast_channel_unlock(c1);
03487          return AST_BRIDGE_FAILED_NOWARN;
03488       }
03489 
03490       if (option_verbose > 2)
03491          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03492       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03493    } else {
03494       if (option_verbose > 2) 
03495          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03496       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03497    }
03498 
03499    return res;
03500 }

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2791 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

02792 {
02793    if (pt < 0 || pt > MAX_RTP_PT)
02794       return 0; /* bogus payload type */
02795 
02796    if (static_RTP_PT[pt].isAstFormat)
02797       return static_RTP_PT[pt].code;
02798    else
02799       return 0;
02800 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2786 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02787 {
02788    return &rtp->pref;
02789 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2739 of file rtp.c.

References ast_codec_pref_getsize(), ast_log(), ast_smoother_new(), ast_smoother_reconfigure(), ast_smoother_set_flags(), ast_format_list::cur_ms, ast_format_list::flags, ast_format_list::fr_len, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, option_debug, ast_rtp::pref, prefs, and ast_rtp::smoother.

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

02740 {
02741    struct ast_format_list current_format_old, current_format_new;
02742 
02743    /* if no packets have been sent through this session yet, then
02744     *  changing preferences does not require any extra work
02745     */
02746    if (rtp->lasttxformat == 0) {
02747       rtp->pref = *prefs;
02748       return 0;
02749    }
02750 
02751    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
02752 
02753    rtp->pref = *prefs;
02754 
02755    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
02756 
02757    /* if the framing desired for the current format has changed, we may have to create
02758     * or adjust the smoother for this session
02759     */
02760    if ((current_format_new.inc_ms != 0) &&
02761        (current_format_new.cur_ms != current_format_old.cur_ms)) {
02762       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
02763 
02764       if (rtp->smoother) {
02765          ast_smoother_reconfigure(rtp->smoother, new_size);
02766          if (option_debug) {
02767             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
02768          }
02769       } else {
02770          if (!(rtp->smoother = ast_smoother_new(new_size))) {
02771             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
02772             return -1;
02773          }
02774          if (current_format_new.flags) {
02775             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
02776          }
02777          if (option_debug) {
02778             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
02779          }
02780       }
02781    }
02782 
02783    return 0;
02784 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 2152 of file rtp.c.

References ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose(), ast_rtp::bridge_lock, ast_rtcp::expected_prior, free, ast_rtp::io, ast_rtp::ioid, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtp::s, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.

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

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

int ast_rtp_early_bridge ( struct ast_channel dest,
struct ast_channel src 
)

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

Definition at line 1494 of file rtp.c.

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

Referenced by wait_for_answer().

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 512 of file rtp.c.

References ast_rtp::s.

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

00513 {
00514    return rtp->s;
00515 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

Definition at line 2062 of file rtp.c.

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

Referenced by __sip_destroy(), and ast_rtp_read().

02063 {
02064    struct ast_rtp *bridged = NULL;
02065 
02066    ast_mutex_lock(&rtp->bridge_lock);
02067    bridged = rtp->bridged;
02068    ast_mutex_unlock(&rtp->bridge_lock);
02069 
02070    return bridged;
02071 }

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

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

Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().

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

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

Definition at line 2044 of file rtp.c.

References ast_rtp::them.

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

02045 {
02046    if ((them->sin_family != AF_INET) ||
02047       (them->sin_port != rtp->them.sin_port) ||
02048       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02049       them->sin_family = AF_INET;
02050       them->sin_port = rtp->them.sin_port;
02051       them->sin_addr = rtp->them.sin_addr;
02052       return 1;
02053    }
02054    return 0;
02055 }

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

Return RTCP quality string.

Definition at line 2108 of file rtp.c.

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

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

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

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

02058 {
02059    *us = rtp->us;
02060 }

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

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

Referenced by main().

03886 {
03887    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03888    ast_rtp_reload();
03889 }

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

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

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

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

Referenced by process_sdp().

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

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

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

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1736 of file rtp.c.

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

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

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

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

Definition at line 1581 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, ast_channel::name, option_debug, and ast_rtp_protocol::set_rtp_peer.

Referenced by wait_for_answer().

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

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

Initializate a RTP session.

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

Definition at line 2008 of file rtp.c.

References ast_rtp_new_with_bindaddr(), io, and sched.

02009 {
02010    struct in_addr ia;
02011 
02012    memset(&ia, 0, sizeof(ia));
02013    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02014 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

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

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2025 of file rtp.c.

References ast_rtp::set_marker_bit.

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

02026 {
02027    if (rtp) {
02028       rtp->set_marker_bit = 1;
02029    }
02030    return;
02031 }

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

Initializate a RTP session using an in_addr structure.

This fuction gets called by ast_rtp_new().

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

Definition at line 1915 of file rtp.c.

References ast_calloc, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), errno, first, free, LOG_DEBUG, LOG_ERROR, option_debug, rtp_socket(), and sched.

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Definition at line 2902 of file rtp.c.

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

Referenced by load_module().

02903 {
02904    struct ast_rtp_protocol *cur;
02905 
02906    AST_LIST_LOCK(&protos);
02907    AST_LIST_TRAVERSE(&protos, cur, list) {   
02908       if (!strcmp(cur->type, proto->type)) {
02909          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02910          AST_LIST_UNLOCK(&protos);
02911          return -1;
02912       }
02913    }
02914    AST_LIST_INSERT_HEAD(&protos, proto, list);
02915    AST_LIST_UNLOCK(&protos);
02916    
02917    return 0;
02918 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2894 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by load_module(), and unload_module().

02895 {
02896    AST_LIST_LOCK(&protos);
02897    AST_LIST_REMOVE(&protos, proto, list);
02898    AST_LIST_UNLOCK(&protos);
02899 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1418 of file rtp.c.

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

Referenced by gtalk_alloc(), and process_sdp().

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

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

Definition at line 1458 of file rtp.c.

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

Referenced by ast_rtp_make_compatible(), and process_sdp().

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

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 1439 of file rtp.c.

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

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

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

Definition at line 2637 of file rtp.c.

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

Referenced by ast_rtp_write().

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

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1108 of file rtp.c.

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

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

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

int ast_rtp_reload ( void   ) 

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

03821 {
03822    struct ast_config *cfg;
03823    const char *s;
03824 
03825    rtpstart = 5000;
03826    rtpend = 31000;
03827    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03828    cfg = ast_config_load("rtp.conf");
03829    if (cfg) {
03830       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03831          rtpstart = atoi(s);
03832          if (rtpstart < 1024)
03833             rtpstart = 1024;
03834          if (rtpstart > 65535)
03835             rtpstart = 65535;
03836       }
03837       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03838          rtpend = atoi(s);
03839          if (rtpend < 1024)
03840             rtpend = 1024;
03841          if (rtpend > 65535)
03842             rtpend = 65535;
03843       }
03844       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03845          rtcpinterval = atoi(s);
03846          if (rtcpinterval == 0)
03847             rtcpinterval = 0; /* Just so we're clear... it's zero */
03848          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03849             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03850          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03851             rtcpinterval = RTCP_MAX_INTERVALMS;
03852       }
03853       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03854 #ifdef SO_NO_CHECK
03855          if (ast_false(s))
03856             nochecksums = 1;
03857          else
03858             nochecksums = 0;
03859 #else
03860          if (ast_false(s))
03861             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03862 #endif
03863       }
03864       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03865          dtmftimeout = atoi(s);
03866          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03867             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03868                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03869             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03870          };
03871       }
03872       ast_config_destroy(cfg);
03873    }
03874    if (rtpstart >= rtpend) {
03875       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03876       rtpstart = 5000;
03877       rtpend = 31000;
03878    }
03879    if (option_verbose > 1)
03880       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03881    return 0;
03882 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2089 of file rtp.c.

References ast_rtp::dtmfcount, ast_rtp::dtmfmute, 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.

02090 {
02091    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02092    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02093    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02094    rtp->lastts = 0;
02095    rtp->lastdigitts = 0;
02096    rtp->lastrxts = 0;
02097    rtp->lastividtimestamp = 0;
02098    rtp->lastovidtimestamp = 0;
02099    rtp->lasteventseqn = 0;
02100    rtp->lastevent = 0;
02101    rtp->lasttxformat = 0;
02102    rtp->lastrxformat = 0;
02103    rtp->dtmfcount = 0;
02104    rtp->seqno = 0;
02105    rtp->rxseqno = 0;
02106 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2603 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2211 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by mgcp_senddigit_begin(), oh323_digit_begin(), and sip_senddigit_begin().

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2313 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by mgcp_senddigit_end(), oh323_digit_end(), and sip_senddigit_end().

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

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 
)

Activate payload type.

Definition at line 1656 of file rtp.c.

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

Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().

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

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

Definition at line 2033 of file rtp.c.

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

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

02034 {
02035    rtp->them.sin_port = them->sin_port;
02036    rtp->them.sin_addr = them->sin_addr;
02037    if (rtp->rtcp) {
02038       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02039       rtp->rtcp->them.sin_addr = them->sin_addr;
02040    }
02041    rtp->rxseqno = 0;
02042 }

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 
)

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

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

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

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

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

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

Referenced by __oh323_rtp_create(), and sip_alloc().

02017 {
02018    int res;
02019 
02020    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
02021       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
02022    return res;
02023 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Definition at line 2073 of file rtp.c.

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

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

02074 {
02075    if (rtp->rtcp) {
02076       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02077    }
02078 
02079    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02080    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02081    if (rtp->rtcp) {
02082       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02083       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02084    }
02085    
02086    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02087 }

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

Definition at line 402 of file rtp.c.

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

Referenced by gtalk_update_stun().

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

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

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

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2802 of file rtp.c.

References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_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().

02803 {
02804    struct ast_frame *f;
02805    int codec;
02806    int hdrlen = 12;
02807    int subclass;
02808    
02809 
02810    /* If we have no peer, return immediately */ 
02811    if (!rtp->them.sin_addr.s_addr)
02812       return 0;
02813 
02814    /* If there is no data length, return immediately */
02815    if (!_f->datalen) 
02816       return 0;
02817    
02818    /* Make sure we have enough space for RTP header */
02819    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02820       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02821       return -1;
02822    }
02823 
02824    subclass = _f->subclass;
02825    if (_f->frametype == AST_FRAME_VIDEO)
02826       subclass &= ~0x1;
02827 
02828    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02829    if (codec < 0) {
02830       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02831       return -1;
02832    }
02833 
02834    if (rtp->lasttxformat != subclass) {
02835       /* New format, reset the smoother */
02836       if (option_debug)
02837          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02838       rtp->lasttxformat = subclass;
02839       if (rtp->smoother)
02840          ast_smoother_free(rtp->smoother);
02841       rtp->smoother = NULL;
02842    }
02843 
02844    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
02845       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02846       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02847          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02848             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));
02849             return -1;
02850          }
02851          if (fmt.flags)
02852             ast_smoother_set_flags(rtp->smoother, fmt.flags);
02853          if (option_debug)
02854             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));
02855       }
02856    }
02857    if (rtp->smoother) {
02858       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
02859          ast_smoother_feed_be(rtp->smoother, _f);
02860       } else {
02861          ast_smoother_feed(rtp->smoother, _f);
02862       }
02863 
02864       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
02865          if (f->subclass == AST_FORMAT_G722) {
02866             /* G.722 is silllllllllllllly */
02867             f->samples /= 2;
02868          }
02869 
02870          ast_rtp_raw_write(rtp, f, codec);
02871       }
02872    } else {
02873       /* Don't buffer outgoing frames; send them one-per-packet: */
02874       if (_f->offset < hdrlen) {
02875          f = ast_frdup(_f);
02876       } else {
02877          f = _f;
02878       }
02879       if (f->data) {
02880          if (f->subclass == AST_FORMAT_G722) {
02881             /* G.722 is silllllllllllllly */
02882             f->samples /= 2;
02883          }
02884          ast_rtp_raw_write(rtp, f, codec);
02885       }
02886       if (f != _f)
02887          ast_frfree(f);
02888    }
02889       
02890    return 0;
02891 }

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

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

Referenced by ast_rtp_bridge().

02922 {
02923    struct ast_frame *fr = NULL;
02924    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
02925    int oldcodec0 = codec0, oldcodec1 = codec1;
02926    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
02927    struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
02928    
02929    /* Set it up so audio goes directly between the two endpoints */
02930 
02931    /* Test the first channel */
02932    if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
02933       ast_rtp_get_peer(p1, &ac1);
02934       if (vp1)
02935          ast_rtp_get_peer(vp1, &vac1);
02936    } else
02937       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
02938    
02939    /* Test the second channel */
02940    if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
02941       ast_rtp_get_peer(p0, &ac0);
02942       if (vp0)
02943          ast_rtp_get_peer(vp0, &vac0);
02944    } else
02945       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
02946 
02947    /* Now we can unlock and move into our loop */
02948    ast_channel_unlock(c0);
02949    ast_channel_unlock(c1);
02950 
02951    /* Throw our channels into the structure and enter the loop */
02952    cs[0] = c0;
02953    cs[1] = c1;
02954    cs[2] = NULL;
02955    for (;;) {
02956       /* Check if anything changed */
02957       if ((c0->tech_pvt != pvt0) ||
02958           (c1->tech_pvt != pvt1) ||
02959           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
02960           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
02961          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
02962          if (c0->tech_pvt == pvt0)
02963             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02964                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02965          if (c1->tech_pvt == pvt1)
02966             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02967                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02968          return AST_BRIDGE_RETRY;
02969       }
02970 
02971       /* Check if they have changed their address */
02972       ast_rtp_get_peer(p1, &t1);
02973       if (vp1)
02974          ast_rtp_get_peer(vp1, &vt1);
02975       if (pr1->get_codec)
02976          codec1 = pr1->get_codec(c1);
02977       ast_rtp_get_peer(p0, &t0);
02978       if (vp0)
02979          ast_rtp_get_peer(vp0, &vt0);
02980       if (pr0->get_codec)
02981          codec0 = pr0->get_codec(c0);
02982       if ((inaddrcmp(&t1, &ac1)) ||
02983           (vp1 && inaddrcmp(&vt1, &vac1)) ||
02984           (codec1 != oldcodec1)) {
02985          if (option_debug > 1) {
02986             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02987                c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
02988             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
02989                c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
02990             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02991                c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
02992             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02993                c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
02994          }
02995          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)))
02996             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
02997          memcpy(&ac1, &t1, sizeof(ac1));
02998          memcpy(&vac1, &vt1, sizeof(vac1));
02999          oldcodec1 = codec1;
03000       }
03001       if ((inaddrcmp(&t0, &ac0)) ||
03002           (vp0 && inaddrcmp(&vt0, &vac0))) {
03003          if (option_debug > 1) {
03004             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03005                c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
03006             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
03007                c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
03008          }
03009          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)))
03010             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
03011          memcpy(&ac0, &t0, sizeof(ac0));
03012          memcpy(&vac0, &vt0, sizeof(vac0));
03013          oldcodec0 = codec0;
03014       }
03015 
03016       /* Wait for frame to come in on the channels */
03017       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03018          if (!timeoutms) {
03019             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03020                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03021             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03022                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03023             return AST_BRIDGE_RETRY;
03024          }
03025          if (option_debug)
03026             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03027          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03028             break;
03029          continue;
03030       }
03031       fr = ast_read(who);
03032       other = (who == c0) ? c1 : c0;
03033       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03034              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
03035               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
03036          /* Break out of bridge */
03037          *fo = fr;
03038          *rc = who;
03039          if (option_debug)
03040             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03041          if (c0->tech_pvt == pvt0)
03042             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03043                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03044          if (c1->tech_pvt == pvt1)
03045             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03046                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03047          return AST_BRIDGE_COMPLETE;
03048       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03049          if ((fr->subclass == AST_CONTROL_HOLD) ||
03050              (fr->subclass == AST_CONTROL_UNHOLD) ||
03051              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03052              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03053             if (fr->subclass == AST_CONTROL_HOLD) {
03054                /* If we someone went on hold we want the other side to reinvite back to us */
03055                if (who == c0)
03056                   pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
03057                else
03058                   pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
03059             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03060                /* If they went off hold they should go back to being direct */
03061                if (who == c0)
03062                   pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
03063                else
03064                   pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
03065             }
03066             /* Update local address information */
03067             ast_rtp_get_peer(p0, &t0);
03068             memcpy(&ac0, &t0, sizeof(ac0));
03069             ast_rtp_get_peer(p1, &t1);
03070             memcpy(&ac1, &t1, sizeof(ac1));
03071             /* Update codec information */
03072             if (pr0->get_codec && c0->tech_pvt)
03073                oldcodec0 = codec0 = pr0->get_codec(c0);
03074             if (pr1->get_codec && c1->tech_pvt)
03075                oldcodec1 = codec1 = pr1->get_codec(c1);
03076             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03077             ast_frfree(fr);
03078          } else {
03079             *fo = fr;
03080             *rc = who;
03081             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03082             return AST_BRIDGE_COMPLETE;
03083          }
03084       } else {
03085          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03086              (fr->frametype == AST_FRAME_DTMF_END) ||
03087              (fr->frametype == AST_FRAME_VOICE) ||
03088              (fr->frametype == AST_FRAME_VIDEO) ||
03089              (fr->frametype == AST_FRAME_IMAGE) ||
03090              (fr->frametype == AST_FRAME_HTML) ||
03091              (fr->frametype == AST_FRAME_MODEM) ||
03092              (fr->frametype == AST_FRAME_TEXT)) {
03093             ast_write(other, fr);
03094          }
03095          ast_frfree(fr);
03096       }
03097       /* Swap priority */
03098       cs[2] = cs[0];
03099       cs[0] = cs[1];
03100       cs[1] = cs[2];
03101    }
03102 
03103    if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03104       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03105    if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03106       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03107 
03108    return AST_BRIDGE_FAILED;
03109 }

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

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

Referenced by ast_rtp_bridge().

03208 {
03209    struct ast_frame *fr = NULL;
03210    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03211    int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
03212    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03213    int p0_callback = 0, p1_callback = 0;
03214    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03215 
03216    /* Okay, setup each RTP structure to do P2P forwarding */
03217    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03218    p2p_set_bridge(p0, p1);
03219    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03220    p2p_set_bridge(p1, p0);
03221 
03222    /* Activate callback modes if possible */
03223    p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03224    p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03225 
03226    /* Now let go of the channel locks and be on our way */
03227    ast_channel_unlock(c0);
03228    ast_channel_unlock(c1);
03229 
03230    /* Go into a loop forwarding frames until we don't need to anymore */
03231    cs[0] = c0;
03232    cs[1] = c1;
03233    cs[2] = NULL;
03234    for (;;) {
03235       /* If the underlying formats have changed force this bridge to break */
03236       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
03237          ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n");
03238          res = AST_BRIDGE_FAILED_NOWARN;
03239          break;
03240       }
03241       /* Check if anything changed */
03242       if ((c0->tech_pvt != pvt0) ||
03243           (c1->tech_pvt != pvt1) ||
03244           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03245           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03246          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03247          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03248             ast_frfree(fr);
03249          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03250             ast_frfree(fr);
03251          res = AST_BRIDGE_RETRY;
03252          break;
03253       }
03254       /* Wait on a channel to feed us a frame */
03255       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03256          if (!timeoutms) {
03257             res = AST_BRIDGE_RETRY;
03258             break;
03259          }
03260          if (option_debug)
03261             ast_log(LOG_NOTICE, "Ooh, empty read...\n");
03262          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03263             break;
03264          continue;
03265       }
03266       /* Read in frame from channel */
03267       fr = ast_read(who);
03268       other = (who == c0) ? c1 : c0;
03269       /* Dependong on the frame we may need to break out of our bridge */
03270       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03271              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03272              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03273          /* Record received frame and who */
03274          *fo = fr;
03275          *rc = who;
03276          if (option_debug)
03277             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03278          res = AST_BRIDGE_COMPLETE;
03279          break;
03280       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03281          if ((fr->subclass == AST_CONTROL_HOLD) ||
03282              (fr->subclass == AST_CONTROL_UNHOLD) ||
03283              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03284              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03285             /* If we are going on hold, then break callback mode and P2P bridging */
03286             if (fr->subclass == AST_CONTROL_HOLD) {
03287                if (p0_callback)
03288                   p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03289                if (p1_callback)
03290                   p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03291                p2p_set_bridge(p0, NULL);
03292                p2p_set_bridge(p1, NULL);
03293             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03294                /* If we are off hold, then go back to callback mode and P2P bridging */
03295                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03296                p2p_set_bridge(p0, p1);
03297                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03298                p2p_set_bridge(p1, p0);
03299                p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03300                p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03301             }
03302             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03303             ast_frfree(fr);
03304          } else {
03305             *fo = fr;
03306             *rc = who;
03307             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03308             res = AST_BRIDGE_COMPLETE;
03309             break;
03310          }
03311       } else {
03312          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03313              (fr->frametype == AST_FRAME_DTMF_END) ||
03314              (fr->frametype == AST_FRAME_VOICE) ||
03315              (fr->frametype == AST_FRAME_VIDEO) ||
03316              (fr->frametype == AST_FRAME_IMAGE) ||
03317              (fr->frametype == AST_FRAME_HTML) ||
03318              (fr->frametype == AST_FRAME_MODEM) ||
03319              (fr->frametype == AST_FRAME_TEXT)) {
03320             ast_write(other, fr);
03321          }
03322 
03323          ast_frfree(fr);
03324       }
03325       /* Swap priority */
03326       cs[2] = cs[0];
03327       cs[0] = cs[1];
03328       cs[1] = cs[2];
03329    }
03330 
03331    /* If we are totally avoiding the core, then restore our link to it */
03332    if (p0_callback)
03333       p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03334    if (p1_callback)
03335       p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03336 
03337    /* Break out of the direct bridge */
03338    p2p_set_bridge(p0, NULL);
03339    p2p_set_bridge(p1, NULL);
03340 
03341    return res;
03342 }

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

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

Referenced by ast_rtp_read().

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

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

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

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

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

Definition at line 2191 of file rtp.c.

References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), t, and ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

02192 {
02193    struct timeval t;
02194    long ms;
02195    if (ast_tvzero(rtp->txcore)) {
02196       rtp->txcore = ast_tvnow();
02197       /* Round to 20ms for nice, pretty timestamps */
02198       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02199    }
02200    /* Use previous txcore if available */
02201    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02202    ms = ast_tvdiff_ms(t, rtp->txcore);
02203    if (ms < 0)
02204       ms = 0;
02205    /* Use what we just got for next time */
02206    rtp->txcore = t;
02207    return (unsigned int) ms;
02208 }

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

Get channel driver interface structure.

Definition at line 1480 of file rtp.c.

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

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

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

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

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

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

03179 {
03180    ast_channel_lock(chan);
03181 
03182    /* Remove the callback from the IO context */
03183    ast_io_remove(rtp->io, iod[0]);
03184 
03185    /* Restore file descriptors */
03186    chan->fds[0] = fds[0];
03187    ast_channel_unlock(chan);
03188 
03189    /* Restore callback mode if previously used */
03190    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03191       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03192 
03193    return 0;
03194 }

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

P2P RTP Callback.

Definition at line 3171 of file rtp.c.

Referenced by bridge_p2p_loop().

03172 {
03173    return 0;
03174 }

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

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

Referenced by bridge_p2p_loop().

03198 {
03199    ast_mutex_lock(&rtp0->bridge_lock);
03200    rtp0->bridged = rtp1;
03201    ast_mutex_unlock(&rtp0->bridge_lock);
03202 
03203    return;
03204 }

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

Definition at line 668 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Process RTP DTMF and events according to RFC 2833.

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

Parameters:
rtp 
data 
len 
seqno 
Returns:

Definition at line 707 of file rtp.c.

References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_null_frame, ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), ast_rtp::dtmfcount, f, FLAG_DTMF_COMPENSATE, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, ast_frame::samples, and send_dtmf().

Referenced by ast_rtp_read().

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

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

Process Comfort Noise RTP.

This is incomplete at the moment.

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

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

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

Definition at line 654 of file rtp.c.

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

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

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

Definition at line 3617 of file rtp.c.

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

03617                                                          {
03618    if (argc != 2) {
03619       if (argc != 4)
03620          return RESULT_SHOWUSAGE;
03621       return rtcp_do_debug_ip(fd, argc, argv);
03622    }
03623    rtcpdebug = 1;
03624    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03625    ast_cli(fd, "RTCP Debugging Enabled\n");
03626    return RESULT_SUCCESS;
03627 }

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

Definition at line 3605 of file rtp.c.

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

03605                                                                     {
03606    if (argc != 3) {
03607       if (argc != 5)
03608          return RESULT_SHOWUSAGE;
03609       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03610    }
03611    rtcpdebug = 1;
03612    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03613    ast_cli(fd, "RTCP Debugging Enabled\n");
03614    return RESULT_SUCCESS;
03615 }

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

Definition at line 3562 of file rtp.c.

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

Referenced by rtcp_do_debug().

03563 {
03564    struct hostent *hp;
03565    struct ast_hostent ahp;
03566    int port = 0;
03567    char *p, *arg;
03568    if (argc != 4)
03569       return RESULT_SHOWUSAGE;
03570 
03571    arg = argv[3];
03572    p = strstr(arg, ":");
03573    if (p) {
03574       *p = '\0';
03575       p++;
03576       port = atoi(p);
03577    }
03578    hp = ast_gethostbyname(arg, &ahp);
03579    if (hp == NULL)
03580       return RESULT_SHOWUSAGE;
03581    rtcpdebugaddr.sin_family = AF_INET;
03582    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03583    rtcpdebugaddr.sin_port = htons(port);
03584    if (port == 0)
03585       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03586    else
03587       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03588    rtcpdebug = 1;
03589    return RESULT_SUCCESS;
03590 }

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

Definition at line 3532 of file rtp.c.

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

Referenced by rtcp_do_debug_deprecated().

03533 {
03534    struct hostent *hp;
03535    struct ast_hostent ahp;
03536    int port = 0;
03537    char *p, *arg;
03538    if (argc != 5)
03539       return RESULT_SHOWUSAGE;
03540 
03541    arg = argv[4];
03542    p = strstr(arg, ":");
03543    if (p) {
03544       *p = '\0';
03545       p++;
03546       port = atoi(p);
03547    }
03548    hp = ast_gethostbyname(arg, &ahp);
03549    if (hp == NULL)
03550       return RESULT_SHOWUSAGE;
03551    rtcpdebugaddr.sin_family = AF_INET;
03552    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03553    rtcpdebugaddr.sin_port = htons(port);
03554    if (port == 0)
03555       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03556    else
03557       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03558    rtcpdebug = 1;
03559    return RESULT_SUCCESS;
03560 }

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

Definition at line 3638 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03638                                                          {
03639    if (argc != 2) {
03640       return RESULT_SHOWUSAGE;
03641    }
03642    rtcpstats = 1;
03643    ast_cli(fd, "RTCP Stats Enabled\n");
03644    return RESULT_SUCCESS;
03645 }

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

Definition at line 3629 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03629                                                                     {
03630    if (argc != 3) {
03631       return RESULT_SHOWUSAGE;
03632    }
03633    rtcpstats = 1;
03634    ast_cli(fd, "RTCP Stats Enabled\n");
03635    return RESULT_SUCCESS;
03636 }

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

Definition at line 3665 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03666 {
03667    if (argc != 3)
03668       return RESULT_SHOWUSAGE;
03669    rtcpdebug = 0;
03670    ast_cli(fd,"RTCP Debugging Disabled\n");
03671    return RESULT_SUCCESS;
03672 }

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

Definition at line 3656 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03657 {
03658    if (argc != 4)
03659       return RESULT_SHOWUSAGE;
03660    rtcpdebug = 0;
03661    ast_cli(fd,"RTCP Debugging Disabled\n");
03662    return RESULT_SUCCESS;
03663 }

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

Definition at line 3683 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03684 {
03685    if (argc != 3)
03686       return RESULT_SHOWUSAGE;
03687    rtcpstats = 0;
03688    ast_cli(fd,"RTCP Stats Disabled\n");
03689    return RESULT_SUCCESS;
03690 }

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

Definition at line 3674 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03675 {
03676    if (argc != 4)
03677       return RESULT_SHOWUSAGE;
03678    rtcpstats = 0;
03679    ast_cli(fd,"RTCP Stats Disabled\n");
03680    return RESULT_SUCCESS;
03681 }

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

Definition at line 641 of file rtp.c.

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

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

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

Definition at line 3592 of file rtp.c.

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

03593 {
03594    if (argc != 2) {
03595       if (argc != 4)
03596          return RESULT_SHOWUSAGE;
03597       return rtp_do_debug_ip(fd, argc, argv);
03598    }
03599    rtpdebug = 1;
03600    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03601    ast_cli(fd, "RTP Debugging Enabled\n");
03602    return RESULT_SUCCESS;
03603 }

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

Definition at line 3502 of file rtp.c.

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

Referenced by rtp_do_debug().

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

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

Definition at line 3647 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03648 {
03649    if (argc != 3)
03650       return RESULT_SHOWUSAGE;
03651    rtpdebug = 0;
03652    ast_cli(fd,"RTP Debugging Disabled\n");
03653    return RESULT_SUCCESS;
03654 }

static int rtp_socket ( void   )  [static]

Definition at line 1855 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

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

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

Definition at line 813 of file rtp.c.

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

Referenced by p2p_callback_disable().

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

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

Definition at line 615 of file rtp.c.

References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_test_flag, ast_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, 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 ast_rtp_read(), 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       return &ast_null_frame;
00623    }
00624    if (option_debug)
00625       ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
00626    if (rtp->resp == 'X') {
00627       rtp->f.frametype = AST_FRAME_CONTROL;
00628       rtp->f.subclass = AST_CONTROL_FLASH;
00629    } else {
00630       rtp->f.frametype = type;
00631       rtp->f.subclass = rtp->resp;
00632    }
00633    rtp->f.datalen = 0;
00634    rtp->f.samples = 0;
00635    rtp->f.mallocd = 0;
00636    rtp->f.src = "RTP";
00637    return &rtp->f;
00638    
00639 }

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

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03693 {
03694    if (argc != 2) {
03695       return RESULT_SHOWUSAGE;
03696    }
03697    stundebug = 1;
03698    ast_cli(fd, "STUN Debugging Enabled\n");
03699    return RESULT_SUCCESS;
03700 }

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

Definition at line 423 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Definition at line 280 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3702 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03703 {
03704    if (argc != 3)
03705       return RESULT_SHOWUSAGE;
03706    stundebug = 0;
03707    ast_cli(fd, "STUN Debugging Disabled\n");
03708    return RESULT_SUCCESS;
03709 }

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(), stun_trans_id::id, 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 3778 of file rtp.c.

Referenced by ast_rtp_init().

struct ast_cli_entry cli_rtp_no_debug_deprecated [static]

Initial value:

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

Definition at line 3743 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_debug_deprecated [static]

Initial value:

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

Definition at line 3753 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated [static]

Initial value:

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

Definition at line 3748 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated [static]

Initial value:

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

Definition at line 3758 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated [static]

Initial value:

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

Definition at line 3768 of file rtp.c.

struct ast_cli_entry cli_rtp_rtcp_stats_deprecated [static]

Initial value:

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

Definition at line 3763 of file rtp.c.

struct ast_cli_entry cli_stun_no_debug_deprecated [static]

Initial value:

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

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

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 78 of file rtp.c.

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

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

char no_debug_usage[] [static]

Initial value:

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

Definition at line 3715 of file rtp.c.

struct rtpPayloadType payloadType

Definition at line 1351 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 3727 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 3731 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 3739 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

Definition at line 3735 of file rtp.c.

int rtcpdebug [static]

Are we debugging RTCP?

Definition at line 83 of file rtp.c.

struct sockaddr_in rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 88 of file rtp.c.

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 85 of file rtp.c.

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 84 of file rtp.c.

int rtpdebug [static]

Are we debugging?

Definition at line 82 of file rtp.c.

struct sockaddr_in rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 87 of file rtp.c.

int rtpend [static]

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

Definition at line 81 of file rtp.c.

int rtpstart [static]

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

Definition at line 80 of file rtp.c.

struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static]

Definition at line 1386 of file rtp.c.

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

char stun_debug_usage[] [static]

Initial value:

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

Definition at line 3719 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3723 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1353 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1352 of file rtp.c.

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


Generated on Thu May 14 14:50:16 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7