Thu Dec 17 15:36:12 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   (150 * (8000 / 1000))
#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_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt)
 set potential alternate source for RTP media
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_constantssrc (struct ast_rtp *rtp)
 When changing sources, don't generate a new SSRC.
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_get_rate (int subclass)
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 void sanitize_tv (struct timeval *tv)
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   (150 * (8000 / 1000))

samples

Definition at line 76 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 189 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 196 of file rtp.c.

Referenced by p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 197 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

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

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

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

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 267 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 265 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 266 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 280 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 262 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 279 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 282 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 273 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 270 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 268 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 269 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 281 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

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

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Definition at line 357 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 533 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00534 {
00535    unsigned int interval;
00536    /*! \todo XXX Do a more reasonable calculation on this one
00537    * Look in RFC 3550 Section A.7 for an example*/
00538    interval = rtcpinterval;
00539    return interval;
00540 }

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

00522 {
00523    if (rtp->rtcp)
00524       return rtp->rtcp->s;
00525    return -1;
00526 }

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

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

01929 {
01930    struct ast_rtcp *rtcp;
01931 
01932    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01933       return NULL;
01934    rtcp->s = rtp_socket();
01935    if (option_debug > 3)
01936          ast_log(LOG_DEBUG, "socket RTPaux (RTCP) fd: %i\n", rtcp->s);
01937    rtcp->us.sin_family = AF_INET;
01938    rtcp->them.sin_family = AF_INET;
01939    rtcp->schedid = -1;
01940 
01941    if (rtcp->s < 0) {
01942       free(rtcp);
01943       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01944       return NULL;
01945    }
01946 
01947    return rtcp;
01948 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 869 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_rtcp::altthem, 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().

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

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

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

02439 {
02440    struct ast_rtp *rtp = data;
02441    int res;
02442 
02443    rtp->rtcp->sendfur = 1;
02444    res = ast_rtcp_write(data);
02445    
02446    return res;
02447 }

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

02656 {
02657    struct ast_rtp *rtp = (struct ast_rtp *)data;
02658    int res;
02659    
02660    if (!rtp || !rtp->rtcp)
02661       return 0;
02662 
02663    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02664       res = ast_rtcp_write_sr(data);
02665    else
02666       res = ast_rtcp_write_rr(data);
02667    
02668    return res;
02669 }

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

02561 {
02562    struct ast_rtp *rtp = (struct ast_rtp *)data;
02563    int res;
02564    int len = 32;
02565    unsigned int lost;
02566    unsigned int extended;
02567    unsigned int expected;
02568    unsigned int expected_interval;
02569    unsigned int received_interval;
02570    int lost_interval;
02571    struct timeval now;
02572    unsigned int *rtcpheader;
02573    char bdata[1024];
02574    struct timeval dlsr;
02575    int fraction;
02576 
02577    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
02578       return 0;
02579      
02580    if (!rtp->rtcp->them.sin_addr.s_addr) {
02581       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
02582       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02583       return 0;
02584    }
02585 
02586    extended = rtp->cycles + rtp->lastrxseqno;
02587    expected = extended - rtp->seedrxseqno + 1;
02588    lost = expected - rtp->rxcount;
02589    expected_interval = expected - rtp->rtcp->expected_prior;
02590    rtp->rtcp->expected_prior = expected;
02591    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02592    rtp->rtcp->received_prior = rtp->rxcount;
02593    lost_interval = expected_interval - received_interval;
02594    if (expected_interval == 0 || lost_interval <= 0)
02595       fraction = 0;
02596    else
02597       fraction = (lost_interval << 8) / expected_interval;
02598    gettimeofday(&now, NULL);
02599    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02600    rtcpheader = (unsigned int *)bdata;
02601    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
02602    rtcpheader[1] = htonl(rtp->ssrc);
02603    rtcpheader[2] = htonl(rtp->themssrc);
02604    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02605    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02606    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02607    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
02608    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02609 
02610    if (rtp->rtcp->sendfur) {
02611       rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
02612       rtcpheader[9] = htonl(rtp->ssrc);               /* Our SSRC */
02613       len += 8;
02614       rtp->rtcp->sendfur = 0;
02615    }
02616 
02617    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
02618    it can change mid call, and SDES can't) */
02619    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02620    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02621    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
02622    len += 12;
02623    
02624    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02625 
02626    if (res < 0) {
02627       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
02628       /* Remove the scheduler */
02629       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02630       return 0;
02631    }
02632 
02633    rtp->rtcp->rr_count++;
02634 
02635    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02636       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
02637          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 
02638          "  IA jitter: %.4f\n" 
02639          "  Their last SR: %u\n" 
02640          "  DLSR: %4.4f (sec)\n\n",
02641          ast_inet_ntoa(rtp->rtcp->them.sin_addr),
02642          ntohs(rtp->rtcp->them.sin_port),
02643          rtp->ssrc, rtp->themssrc, fraction, lost,
02644          rtp->rxjitter,
02645          rtp->rtcp->themrxlsr,
02646          (double)(ntohl(rtcpheader[7])/65536.0));
02647    }
02648 
02649    return res;
02650 }

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

Send RTCP sender's report.

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

02451 {
02452    struct ast_rtp *rtp = (struct ast_rtp *)data;
02453    int res;
02454    int len = 0;
02455    struct timeval now;
02456    unsigned int now_lsw;
02457    unsigned int now_msw;
02458    unsigned int *rtcpheader;
02459    unsigned int lost;
02460    unsigned int extended;
02461    unsigned int expected;
02462    unsigned int expected_interval;
02463    unsigned int received_interval;
02464    int lost_interval;
02465    int fraction;
02466    struct timeval dlsr;
02467    char bdata[512];
02468 
02469    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
02470    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
02471       return 0;
02472    
02473    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
02474       ast_verbose("RTCP SR transmission error, rtcp halted\n");
02475       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02476       return 0;
02477    }
02478 
02479    gettimeofday(&now, NULL);
02480    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
02481    rtcpheader = (unsigned int *)bdata;
02482    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
02483    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
02484    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
02485    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
02486    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
02487    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
02488    len += 28;
02489    
02490    extended = rtp->cycles + rtp->lastrxseqno;
02491    expected = extended - rtp->seedrxseqno + 1;
02492    if (rtp->rxcount > expected) 
02493       expected += rtp->rxcount - expected;
02494    lost = expected - rtp->rxcount;
02495    expected_interval = expected - rtp->rtcp->expected_prior;
02496    rtp->rtcp->expected_prior = expected;
02497    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02498    rtp->rtcp->received_prior = rtp->rxcount;
02499    lost_interval = expected_interval - received_interval;
02500    if (expected_interval == 0 || lost_interval <= 0)
02501       fraction = 0;
02502    else
02503       fraction = (lost_interval << 8) / expected_interval;
02504    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02505    rtcpheader[7] = htonl(rtp->themssrc);
02506    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02507    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02508    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02509    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
02510    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02511    len += 24;
02512    
02513    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
02514 
02515    if (rtp->rtcp->sendfur) {
02516       rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
02517       rtcpheader[14] = htonl(rtp->ssrc);               /* Our SSRC */
02518       len += 8;
02519       rtp->rtcp->sendfur = 0;
02520    }
02521    
02522    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 
02523    /* it can change mid call, and SDES can't) */
02524    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02525    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02526    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
02527    len += 12;
02528    
02529    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02530    if (res < 0) {
02531       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));
02532       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02533       return 0;
02534    }
02535    
02536    /* FIXME Don't need to get a new one */
02537    gettimeofday(&rtp->rtcp->txlsr, NULL);
02538    rtp->rtcp->sr_count++;
02539 
02540    rtp->rtcp->lastsrtxcount = rtp->txcount;  
02541    
02542    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02543       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
02544       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
02545       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
02546       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
02547       ast_verbose("  Sent packets: %u\n", rtp->txcount);
02548       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
02549       ast_verbose("  Report block:\n");
02550       ast_verbose("  Fraction lost: %u\n", fraction);
02551       ast_verbose("  Cumulative loss: %u\n", lost);
02552       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
02553       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
02554       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
02555    }
02556    return res;
02557 }

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

Referenced by process_sdp().

00402 {
00403    return sizeof(struct ast_rtp);
00404 }

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

03415 {
03416    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03417    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03418    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03419    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03420    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03421    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03422    int codec0 = 0, codec1 = 0;
03423    void *pvt0 = NULL, *pvt1 = NULL;
03424 
03425    /* Lock channels */
03426    ast_channel_lock(c0);
03427    while(ast_channel_trylock(c1)) {
03428       ast_channel_unlock(c0);
03429       usleep(1);
03430       ast_channel_lock(c0);
03431    }
03432 
03433    /* Ensure neither channel got hungup during lock avoidance */
03434    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03435       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
03436       ast_channel_unlock(c0);
03437       ast_channel_unlock(c1);
03438       return AST_BRIDGE_FAILED;
03439    }
03440       
03441    /* Find channel driver interfaces */
03442    if (!(pr0 = get_proto(c0))) {
03443       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03444       ast_channel_unlock(c0);
03445       ast_channel_unlock(c1);
03446       return AST_BRIDGE_FAILED;
03447    }
03448    if (!(pr1 = get_proto(c1))) {
03449       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03450       ast_channel_unlock(c0);
03451       ast_channel_unlock(c1);
03452       return AST_BRIDGE_FAILED;
03453    }
03454 
03455    /* Get channel specific interface structures */
03456    pvt0 = c0->tech_pvt;
03457    pvt1 = c1->tech_pvt;
03458 
03459    /* Get audio and video interface (if native bridge is possible) */
03460    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03461    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03462    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03463    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03464 
03465    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03466    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03467       audio_p0_res = AST_RTP_GET_FAILED;
03468    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03469       audio_p1_res = AST_RTP_GET_FAILED;
03470 
03471    /* Check if a bridge is possible (partial/native) */
03472    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03473       /* Somebody doesn't want to play... */
03474       ast_channel_unlock(c0);
03475       ast_channel_unlock(c1);
03476       return AST_BRIDGE_FAILED_NOWARN;
03477    }
03478 
03479    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03480    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03481       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03482       audio_p0_res = AST_RTP_TRY_PARTIAL;
03483    }
03484 
03485    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03486       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03487       audio_p1_res = AST_RTP_TRY_PARTIAL;
03488    }
03489 
03490    /* If both sides are not using the same method of DTMF transmission 
03491     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03492     * --------------------------------------------------
03493     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03494     * |-----------|------------|-----------------------|
03495     * | Inband    | False      | True                  |
03496     * | RFC2833   | True       | True                  |
03497     * | SIP INFO  | False      | False                 |
03498     * --------------------------------------------------
03499     * However, if DTMF from both channels is being monitored by the core, then
03500     * we can still do packet-to-packet bridging, because passing through the 
03501     * core will handle DTMF mode translation.
03502     */
03503    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03504        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03505       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03506          ast_channel_unlock(c0);
03507          ast_channel_unlock(c1);
03508          return AST_BRIDGE_FAILED_NOWARN;
03509       }
03510       audio_p0_res = AST_RTP_TRY_PARTIAL;
03511       audio_p1_res = AST_RTP_TRY_PARTIAL;
03512    }
03513 
03514    /* If we need to feed frames into the core don't do a P2P bridge */
03515    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
03516        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
03517       ast_channel_unlock(c0);
03518       ast_channel_unlock(c1);
03519       return AST_BRIDGE_FAILED_NOWARN;
03520    }
03521 
03522    /* Get codecs from both sides */
03523    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03524    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03525    if (codec0 && codec1 && !(codec0 & codec1)) {
03526       /* Hey, we can't do native bridging if both parties speak different codecs */
03527       if (option_debug)
03528          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03529       ast_channel_unlock(c0);
03530       ast_channel_unlock(c1);
03531       return AST_BRIDGE_FAILED_NOWARN;
03532    }
03533 
03534    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03535    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03536       struct ast_format_list fmt0, fmt1;
03537 
03538       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03539       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03540          if (option_debug)
03541             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03542          ast_channel_unlock(c0);
03543          ast_channel_unlock(c1);
03544          return AST_BRIDGE_FAILED_NOWARN;
03545       }
03546       /* They must also be using the same packetization */
03547       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
03548       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
03549       if (fmt0.cur_ms != fmt1.cur_ms) {
03550          if (option_debug)
03551             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n");
03552          ast_channel_unlock(c0);
03553          ast_channel_unlock(c1);
03554          return AST_BRIDGE_FAILED_NOWARN;
03555       }
03556 
03557       if (option_verbose > 2)
03558          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03559       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03560    } else {
03561       if (option_verbose > 2) 
03562          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03563       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03564    }
03565 
03566    return res;
03567 }

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2866 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp_a_audio().

02867 {
02868    if (pt < 0 || pt >= MAX_RTP_PT)
02869       return 0; /* bogus payload type */
02870 
02871    if (static_RTP_PT[pt].isAstFormat)
02872       return static_RTP_PT[pt].code;
02873    else
02874       return 0;
02875 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2861 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

02862 {
02863    return &rtp->pref;
02864 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2814 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_a_audio(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

02815 {
02816    struct ast_format_list current_format_old, current_format_new;
02817 
02818    /* if no packets have been sent through this session yet, then
02819     *  changing preferences does not require any extra work
02820     */
02821    if (rtp->lasttxformat == 0) {
02822       rtp->pref = *prefs;
02823       return 0;
02824    }
02825 
02826    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
02827 
02828    rtp->pref = *prefs;
02829 
02830    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
02831 
02832    /* if the framing desired for the current format has changed, we may have to create
02833     * or adjust the smoother for this session
02834     */
02835    if ((current_format_new.inc_ms != 0) &&
02836        (current_format_new.cur_ms != current_format_old.cur_ms)) {
02837       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
02838 
02839       if (rtp->smoother) {
02840          ast_smoother_reconfigure(rtp->smoother, new_size);
02841          if (option_debug) {
02842             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
02843          }
02844       } else {
02845          if (!(rtp->smoother = ast_smoother_new(new_size))) {
02846             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
02847             return -1;
02848          }
02849          if (current_format_new.flags) {
02850             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
02851          }
02852          if (option_debug) {
02853             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
02854          }
02855       }
02856    }
02857 
02858    return 0;
02859 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 2221 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(), sip_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().

02222 {
02223    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02224       /*Print some info on the call here */
02225       ast_verbose("  RTP-stats\n");
02226       ast_verbose("* Our Receiver:\n");
02227       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02228       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02229       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
02230       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02231       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02232       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
02233       ast_verbose("* Our Sender:\n");
02234       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02235       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02236       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
02237       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
02238       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
02239       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
02240    }
02241 
02242    if (rtp->smoother)
02243       ast_smoother_free(rtp->smoother);
02244    if (rtp->ioid)
02245       ast_io_remove(rtp->io, rtp->ioid);
02246    if (rtp->s > -1)
02247       close(rtp->s);
02248    if (rtp->rtcp) {
02249       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02250       close(rtp->rtcp->s);
02251       free(rtp->rtcp);
02252       rtp->rtcp=NULL;
02253    }
02254 
02255    ast_mutex_destroy(&rtp->bridge_lock);
02256 
02257    free(rtp);
02258 }

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

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00517 {
00518    return rtp->s;
00519 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

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

02132 {
02133    struct ast_rtp *bridged = NULL;
02134 
02135    ast_mutex_lock(&rtp->bridge_lock);
02136    bridged = rtp->bridged;
02137    ast_mutex_unlock(&rtp->bridge_lock);
02138 
02139    return bridged;
02140 }

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

01769 {
01770    int pt;
01771    
01772    ast_mutex_lock(&rtp->bridge_lock);
01773    
01774    *astFormats = *nonAstFormats = 0;
01775    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01776       if (rtp->current_RTP_PT[pt].isAstFormat) {
01777          *astFormats |= rtp->current_RTP_PT[pt].code;
01778       } else {
01779          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01780       }
01781    }
01782    
01783    ast_mutex_unlock(&rtp->bridge_lock);
01784    
01785    return;
01786 }

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

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

02114 {
02115    if ((them->sin_family != AF_INET) ||
02116       (them->sin_port != rtp->them.sin_port) ||
02117       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02118       them->sin_family = AF_INET;
02119       them->sin_port = rtp->them.sin_port;
02120       them->sin_addr = rtp->them.sin_addr;
02121       return 1;
02122    }
02123    return 0;
02124 }

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

Return RTCP quality string.

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

02178 {
02179    /*
02180    *ssrc          our ssrc
02181    *themssrc      their ssrc
02182    *lp            lost packets
02183    *rxjitter      our calculated jitter(rx)
02184    *rxcount       no. received packets
02185    *txjitter      reported jitter of the other end
02186    *txcount       transmitted packets
02187    *rlp           remote lost packets
02188    *rtt           round trip time
02189    */
02190 
02191    if (qual && rtp) {
02192       qual->local_ssrc = rtp->ssrc;
02193       qual->local_jitter = rtp->rxjitter;
02194       qual->local_count = rtp->rxcount;
02195       qual->remote_ssrc = rtp->themssrc;
02196       qual->remote_count = rtp->txcount;
02197       if (rtp->rtcp) {
02198          qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02199          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02200          qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02201          qual->rtt = rtp->rtcp->rtt;
02202       }
02203    }
02204    if (rtp->rtcp) {
02205       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02206          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02207          rtp->ssrc,
02208          rtp->themssrc,
02209          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02210          rtp->rxjitter,
02211          rtp->rxcount,
02212          (double)rtp->rtcp->reported_jitter / 65536.0,
02213          rtp->txcount,
02214          rtp->rtcp->reported_lost,
02215          rtp->rtcp->rtt);
02216       return rtp->rtcp->quality;
02217    } else
02218       return "<Unknown> - RTP/RTCP has already been destroyed";
02219 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 576 of file rtp.c.

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

Referenced by do_monitor().

00577 {
00578    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00579       return 0;
00580    return rtp->rtpholdtimeout;
00581 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 584 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00585 {
00586    return rtp->rtpkeepalive;
00587 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 568 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

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

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

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

02127 {
02128    *us = rtp->us;
02129 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 604 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00605 {
00606    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00607 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3952 of file rtp.c.

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

Referenced by main().

03953 {
03954    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03955    ast_rtp_reload();
03956 }

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

01811 {
01812    int pt = 0;
01813 
01814    ast_mutex_lock(&rtp->bridge_lock);
01815 
01816    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
01817       code == rtp->rtp_lookup_code_cache_code) {
01818       /* Use our cached mapping, to avoid the overhead of the loop below */
01819       pt = rtp->rtp_lookup_code_cache_result;
01820       ast_mutex_unlock(&rtp->bridge_lock);
01821       return pt;
01822    }
01823 
01824    /* Check the dynamic list first */
01825    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01826       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
01827          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01828          rtp->rtp_lookup_code_cache_code = code;
01829          rtp->rtp_lookup_code_cache_result = pt;
01830          ast_mutex_unlock(&rtp->bridge_lock);
01831          return pt;
01832       }
01833    }
01834 
01835    /* Then the static list */
01836    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01837       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
01838          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01839          rtp->rtp_lookup_code_cache_code = code;
01840          rtp->rtp_lookup_code_cache_result = pt;
01841          ast_mutex_unlock(&rtp->bridge_lock);
01842          return pt;
01843       }
01844    }
01845 
01846    ast_mutex_unlock(&rtp->bridge_lock);
01847 
01848    return -1;
01849 }

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

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

Referenced by process_sdp().

01872 {
01873    int format;
01874    unsigned len;
01875    char *end = buf;
01876    char *start = buf;
01877 
01878    if (!buf || !size)
01879       return NULL;
01880 
01881    snprintf(end, size, "0x%x (", capability);
01882 
01883    len = strlen(end);
01884    end += len;
01885    size -= len;
01886    start = end;
01887 
01888    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01889       if (capability & format) {
01890          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01891 
01892          snprintf(end, size, "%s|", name);
01893          len = strlen(end);
01894          end += len;
01895          size -= len;
01896       }
01897    }
01898 
01899    if (start == end)
01900       snprintf(start, size, "nothing)"); 
01901    else if (size > 1)
01902       *(end -1) = ')';
01903    
01904    return buf;
01905 }

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

01853 {
01854    unsigned int i;
01855 
01856    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01857       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01858          if (isAstFormat &&
01859              (code == AST_FORMAT_G726_AAL2) &&
01860              (options & AST_RTP_OPT_G726_NONSTANDARD))
01861             return "G726-32";
01862          else
01863             return mimeTypes[i].subtype;
01864       }
01865    }
01866 
01867    return "";
01868 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

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

01789 {
01790    struct rtpPayloadType result;
01791 
01792    result.isAstFormat = result.code = 0;
01793 
01794    if (pt < 0 || pt >= MAX_RTP_PT) 
01795       return result; /* bogus payload type */
01796 
01797    /* Start with negotiated codecs */
01798    ast_mutex_lock(&rtp->bridge_lock);
01799    result = rtp->current_RTP_PT[pt];
01800    ast_mutex_unlock(&rtp->bridge_lock);
01801 
01802    /* If it doesn't exist, check our static RTP type list, just in case */
01803    if (!result.code) 
01804       result = static_RTP_PT[pt];
01805 
01806    return result;
01807 }

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

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

01634 {
01635    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01636    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01637    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01638    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01639    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 
01640    int srccodec, destcodec;
01641 
01642    /* Lock channels */
01643    ast_channel_lock(dest);
01644    while(ast_channel_trylock(src)) {
01645       ast_channel_unlock(dest);
01646       usleep(1);
01647       ast_channel_lock(dest);
01648    }
01649 
01650    /* Find channel driver interfaces */
01651    if (!(destpr = get_proto(dest))) {
01652       if (option_debug)
01653          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01654       ast_channel_unlock(dest);
01655       ast_channel_unlock(src);
01656       return 0;
01657    }
01658    if (!(srcpr = get_proto(src))) {
01659       if (option_debug)
01660          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
01661       ast_channel_unlock(dest);
01662       ast_channel_unlock(src);
01663       return 0;
01664    }
01665 
01666    /* Get audio and video interface (if native bridge is possible) */
01667    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01668    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01669    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01670    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01671 
01672    /* Ensure we have at least one matching codec */
01673    if (srcpr->get_codec)
01674       srccodec = srcpr->get_codec(src);
01675    else
01676       srccodec = 0;
01677    if (destpr->get_codec)
01678       destcodec = destpr->get_codec(dest);
01679    else
01680       destcodec = 0;
01681 
01682    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01683    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)) {
01684       /* Somebody doesn't want to play... */
01685       ast_channel_unlock(dest);
01686       ast_channel_unlock(src);
01687       return 0;
01688    }
01689    ast_rtp_pt_copy(destp, srcp);
01690    if (vdestp && vsrcp)
01691       ast_rtp_pt_copy(vdestp, vsrcp);
01692    if (media) {
01693       /* Bridge early */
01694       if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01695          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
01696    }
01697    ast_channel_unlock(dest);
01698    ast_channel_unlock(src);
01699    if (option_debug)
01700       ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
01701    return 1;
01702 }

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02061 {
02062    struct in_addr ia;
02063 
02064    memset(&ia, 0, sizeof(ia));
02065    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02066 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

01955 {
01956    ast_mutex_init(&rtp->bridge_lock);
01957 
01958    rtp->them.sin_family = AF_INET;
01959    rtp->us.sin_family = AF_INET;
01960    rtp->ssrc = ast_random();
01961    rtp->seqno = ast_random() & 0xffff;
01962    ast_set_flag(rtp, FLAG_HAS_DTMF);
01963 
01964    return;
01965 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2082 of file rtp.c.

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

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

02083 {
02084    if (rtp) {
02085       rtp->set_marker_bit = 1;
02086       if (!rtp->constantssrc) {
02087          rtp->ssrc = ast_random();
02088       }
02089    }
02090 }

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

01968 {
01969    struct ast_rtp *rtp;
01970    int x;
01971    int first;
01972    int startplace;
01973    
01974    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
01975       return NULL;
01976 
01977    ast_rtp_new_init(rtp);
01978 
01979    rtp->s = rtp_socket();
01980    if (option_debug > 2)
01981          ast_log(LOG_DEBUG, "socket RTP fd: %i\n", rtp->s); 
01982    if (rtp->s < 0) {
01983       free(rtp);
01984       ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
01985       return NULL;
01986    }
01987    if (sched && rtcpenable) {
01988       rtp->sched = sched;
01989       rtp->rtcp = ast_rtcp_new();
01990       if (option_debug > 2)
01991             ast_log(LOG_DEBUG, "socket RTCP fd: %i\n", rtp->rtcp->s);
01992    }
01993    
01994    /* Select a random port number in the range of possible RTP */
01995    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
01996    x = x & ~1;
01997    /* Save it for future references. */
01998    startplace = x;
01999    /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
02000    for (;;) {
02001       /* Must be an even port number by RTP spec */
02002       rtp->us.sin_port = htons(x);
02003       rtp->us.sin_addr = addr;
02004       /* If there's rtcp, initialize it as well. */
02005       if (rtp->rtcp) {
02006          rtp->rtcp->us.sin_port = htons(x + 1);
02007          rtp->rtcp->us.sin_addr = addr;
02008       }
02009       /* Try to bind it/them. */
02010       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
02011          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
02012          break;
02013       if (!first) {
02014          /* Primary bind succeeded! Gotta recreate it */
02015          close(rtp->s);
02016          rtp->s = rtp_socket();
02017          if (option_debug > 2)
02018                ast_log(LOG_DEBUG, "socket RTP2 fd: %i\n", rtp->s); 
02019       }
02020       if (errno != EADDRINUSE) {
02021          /* We got an error that wasn't expected, abort! */
02022          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02023          close(rtp->s);
02024          if (rtp->rtcp) {
02025             close(rtp->rtcp->s);
02026             free(rtp->rtcp);
02027          }
02028          free(rtp);
02029          return NULL;
02030       }
02031       /* The port was used, increment it (by two). */
02032       x += 2;
02033       /* Did we go over the limit ? */
02034       if (x > rtpend)
02035          /* then, start from the begingig. */
02036          x = (rtpstart + 1) & ~1;
02037       /* Check if we reached the place were we started. */
02038       if (x == startplace) {
02039          /* If so, there's no ports available. */
02040          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02041          close(rtp->s);
02042          if (rtp->rtcp) {
02043             close(rtp->rtcp->s);
02044             free(rtp->rtcp);
02045          }
02046          free(rtp);
02047          return NULL;
02048       }
02049    }
02050    rtp->sched = sched;
02051    rtp->io = io;
02052    if (callbackmode) {
02053       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02054       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02055    }
02056    ast_rtp_pt_default(rtp);
02057    return rtp;
02058 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

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

02969 {
02970    struct ast_rtp_protocol *cur;
02971 
02972    AST_LIST_LOCK(&protos);
02973    AST_LIST_TRAVERSE(&protos, cur, list) {   
02974       if (!strcmp(cur->type, proto->type)) {
02975          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02976          AST_LIST_UNLOCK(&protos);
02977          return -1;
02978       }
02979    }
02980    AST_LIST_INSERT_HEAD(&protos, proto, list);
02981    AST_LIST_UNLOCK(&protos);
02982    
02983    return 0;
02984 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2960 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by load_module(), and unload_module().

02961 {
02962    AST_LIST_LOCK(&protos);
02963    AST_LIST_REMOVE(&protos, proto, list);
02964    AST_LIST_UNLOCK(&protos);
02965 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

01471 {
01472    int i;
01473 
01474    if (!rtp)
01475       return;
01476 
01477    ast_mutex_lock(&rtp->bridge_lock);
01478 
01479    for (i = 0; i < MAX_RTP_PT; ++i) {
01480       rtp->current_RTP_PT[i].isAstFormat = 0;
01481       rtp->current_RTP_PT[i].code = 0;
01482    }
01483 
01484    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01485    rtp->rtp_lookup_code_cache_code = 0;
01486    rtp->rtp_lookup_code_cache_result = 0;
01487 
01488    ast_mutex_unlock(&rtp->bridge_lock);
01489 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01511 {
01512    unsigned int i;
01513 
01514    ast_mutex_lock(&dest->bridge_lock);
01515    ast_mutex_lock(&src->bridge_lock);
01516 
01517    for (i=0; i < MAX_RTP_PT; ++i) {
01518       dest->current_RTP_PT[i].isAstFormat = 
01519          src->current_RTP_PT[i].isAstFormat;
01520       dest->current_RTP_PT[i].code = 
01521          src->current_RTP_PT[i].code; 
01522    }
01523    dest->rtp_lookup_code_cache_isAstFormat = 0;
01524    dest->rtp_lookup_code_cache_code = 0;
01525    dest->rtp_lookup_code_cache_result = 0;
01526 
01527    ast_mutex_unlock(&src->bridge_lock);
01528    ast_mutex_unlock(&dest->bridge_lock);
01529 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

01492 {
01493    int i;
01494 
01495    ast_mutex_lock(&rtp->bridge_lock);
01496 
01497    /* Initialize to default payload types */
01498    for (i = 0; i < MAX_RTP_PT; ++i) {
01499       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01500       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01501    }
01502 
01503    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01504    rtp->rtp_lookup_code_cache_code = 0;
01505    rtp->rtp_lookup_code_cache_result = 0;
01506 
01507    ast_mutex_unlock(&rtp->bridge_lock);
01508 }

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

Definition at line 2706 of file rtp.c.

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

02707 {
02708    unsigned char *rtpheader;
02709    int hdrlen = 12;
02710    int res;
02711    unsigned int ms;
02712    int pred;
02713    int mark = 0;
02714    int rate = rtp_get_rate(f->subclass) / 1000;
02715 
02716    if (f->subclass == AST_FORMAT_G722) {
02717       /* G722 is silllllllllllllllllly */
02718       f->samples /= 2;
02719    }
02720 
02721    if (rtp->sending_digit) {
02722       return 0;
02723    }
02724 
02725    ms = calc_txstamp(rtp, &f->delivery);
02726    /* Default prediction */
02727    if (f->frametype == AST_FRAME_VOICE) {
02728       pred = rtp->lastts + f->samples;
02729 
02730       /* Re-calculate last TS */
02731       rtp->lastts = rtp->lastts + ms * rate;
02732       if (ast_tvzero(f->delivery)) {
02733          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
02734             and if so, go with our prediction */
02735          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
02736             rtp->lastts = pred;
02737          else {
02738             if (option_debug > 2)
02739                ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
02740             mark = 1;
02741          }
02742       }
02743    } else if (f->frametype == AST_FRAME_VIDEO) {
02744       mark = f->subclass & 0x1;
02745       pred = rtp->lastovidtimestamp + f->samples;
02746       /* Re-calculate last TS */
02747       rtp->lastts = rtp->lastts + ms * 90;
02748       /* If it's close to our prediction, go for it */
02749       if (ast_tvzero(f->delivery)) {
02750          if (abs(rtp->lastts - pred) < 7200) {
02751             rtp->lastts = pred;
02752             rtp->lastovidtimestamp += f->samples;
02753          } else {
02754             if (option_debug > 2)
02755                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);
02756             rtp->lastovidtimestamp = rtp->lastts;
02757          }
02758       }
02759    }
02760 
02761    /* If we have been explicitly told to set the marker bit do so */
02762    if (rtp->set_marker_bit) {
02763       mark = 1;
02764       rtp->set_marker_bit = 0;
02765    }
02766 
02767    /* If the timestamp for non-digit packets has moved beyond the timestamp
02768       for digits, update the digit timestamp.
02769    */
02770    if (rtp->lastts > rtp->lastdigitts)
02771       rtp->lastdigitts = rtp->lastts;
02772 
02773    if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
02774       rtp->lastts = f->ts * rate;
02775 
02776    /* Get a pointer to the header */
02777    rtpheader = (unsigned char *)(f->data - hdrlen);
02778 
02779    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
02780    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
02781    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
02782 
02783    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02784       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02785       if (res <0) {
02786          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
02787             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));
02788          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
02789             /* Only give this error message once if we are not RTP debugging */
02790             if (option_debug || rtpdebug)
02791                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));
02792             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
02793          }
02794       } else {
02795          rtp->txcount++;
02796          rtp->txoctetcount +=(res - hdrlen);
02797          
02798          /* Do not schedule RR if RTCP isn't run */
02799          if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
02800              rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
02801          }
02802       }
02803             
02804       if (rtp_debug_test_addr(&rtp->them))
02805          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02806                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
02807    }
02808 
02809    rtp->seqno++;
02810 
02811    return 0;
02812 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1160 of file rtp.c.

References ast_rtp::altthem, 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_samp2tv(), ast_sched_add(), ast_set_flag, ast_tv(), ast_tvdiff_ms(), 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::dtmf_duration, ast_rtp::dtmf_timeout, 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_get_rate(), 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().

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

int ast_rtp_reload ( void   ) 

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

03888 {
03889    struct ast_config *cfg;
03890    const char *s;
03891 
03892    rtpstart = 5000;
03893    rtpend = 31000;
03894    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03895    cfg = ast_config_load("rtp.conf");
03896    if (cfg) {
03897       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03898          rtpstart = atoi(s);
03899          if (rtpstart < 1024)
03900             rtpstart = 1024;
03901          if (rtpstart > 65535)
03902             rtpstart = 65535;
03903       }
03904       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03905          rtpend = atoi(s);
03906          if (rtpend < 1024)
03907             rtpend = 1024;
03908          if (rtpend > 65535)
03909             rtpend = 65535;
03910       }
03911       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03912          rtcpinterval = atoi(s);
03913          if (rtcpinterval == 0)
03914             rtcpinterval = 0; /* Just so we're clear... it's zero */
03915          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03916             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03917          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03918             rtcpinterval = RTCP_MAX_INTERVALMS;
03919       }
03920       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03921 #ifdef SO_NO_CHECK
03922          if (ast_false(s))
03923             nochecksums = 1;
03924          else
03925             nochecksums = 0;
03926 #else
03927          if (ast_false(s))
03928             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03929 #endif
03930       }
03931       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03932          dtmftimeout = atoi(s);
03933          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
03934             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03935                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03936             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03937          };
03938       }
03939       ast_config_destroy(cfg);
03940    }
03941    if (rtpstart >= rtpend) {
03942       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03943       rtpstart = 5000;
03944       rtpend = 31000;
03945    }
03946    if (option_verbose > 1)
03947       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03948    return 0;
03949 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2158 of file rtp.c.

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

02159 {
02160    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02161    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02162    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02163    rtp->lastts = 0;
02164    rtp->lastdigitts = 0;
02165    rtp->lastrxts = 0;
02166    rtp->lastividtimestamp = 0;
02167    rtp->lastovidtimestamp = 0;
02168    rtp->lasteventseqn = 0;
02169    rtp->lastevent = 0;
02170    rtp->lasttxformat = 0;
02171    rtp->lastrxformat = 0;
02172    rtp->dtmf_timeout = 0;
02173    rtp->seqno = 0;
02174    rtp->rxseqno = 0;
02175 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

02673 {
02674    unsigned int *rtpheader;
02675    int hdrlen = 12;
02676    int res;
02677    int payload;
02678    char data[256];
02679    level = 127 - (level & 0x7f);
02680    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
02681 
02682    /* If we have no peer, return immediately */ 
02683    if (!rtp->them.sin_addr.s_addr)
02684       return 0;
02685 
02686    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02687 
02688    /* Get a pointer to the header */
02689    rtpheader = (unsigned int *)data;
02690    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02691    rtpheader[1] = htonl(rtp->lastts);
02692    rtpheader[2] = htonl(rtp->ssrc); 
02693    data[12] = level;
02694    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02695       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02696       if (res <0) 
02697          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));
02698       if (rtp_debug_test_addr(&rtp->them))
02699          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
02700                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
02701          
02702    }
02703    return 0;
02704 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

02281 {
02282    unsigned int *rtpheader;
02283    int hdrlen = 12, res = 0, i = 0, payload = 0;
02284    char data[256];
02285 
02286    if ((digit <= '9') && (digit >= '0'))
02287       digit -= '0';
02288    else if (digit == '*')
02289       digit = 10;
02290    else if (digit == '#')
02291       digit = 11;
02292    else if ((digit >= 'A') && (digit <= 'D'))
02293       digit = digit - 'A' + 12;
02294    else if ((digit >= 'a') && (digit <= 'd'))
02295       digit = digit - 'a' + 12;
02296    else {
02297       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02298       return 0;
02299    }
02300 
02301    /* If we have no peer, return immediately */ 
02302    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02303       return 0;
02304 
02305    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02306 
02307    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02308    rtp->send_duration = 160;
02309    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
02310    
02311    /* Get a pointer to the header */
02312    rtpheader = (unsigned int *)data;
02313    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02314    rtpheader[1] = htonl(rtp->lastdigitts);
02315    rtpheader[2] = htonl(rtp->ssrc); 
02316 
02317    for (i = 0; i < 2; i++) {
02318       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02319       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02320       if (res < 0) 
02321          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02322             ast_inet_ntoa(rtp->them.sin_addr),
02323             ntohs(rtp->them.sin_port), strerror(errno));
02324       if (rtp_debug_test_addr(&rtp->them))
02325          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02326                 ast_inet_ntoa(rtp->them.sin_addr),
02327                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02328       /* Increment sequence number */
02329       rtp->seqno++;
02330       /* Increment duration */
02331       rtp->send_duration += 160;
02332       /* Clear marker bit and set seqno */
02333       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02334    }
02335 
02336    /* Since we received a begin, we can safely store the digit and disable any compensation */
02337    rtp->sending_digit = 1;
02338    rtp->send_digit = digit;
02339    rtp->send_payload = payload;
02340 
02341    return 0;
02342 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

02346 {
02347    unsigned int *rtpheader;
02348    int hdrlen = 12, res = 0;
02349    char data[256];
02350 
02351    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02352       return 0;
02353 
02354    /* Setup packet to send */
02355    rtpheader = (unsigned int *)data;
02356         rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02357         rtpheader[1] = htonl(rtp->lastdigitts);
02358         rtpheader[2] = htonl(rtp->ssrc);
02359         rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
02360    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02361    
02362    /* Transmit */
02363    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02364    if (res < 0)
02365       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02366          ast_inet_ntoa(rtp->them.sin_addr),
02367          ntohs(rtp->them.sin_port), strerror(errno));
02368    if (rtp_debug_test_addr(&rtp->them))
02369       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02370              ast_inet_ntoa(rtp->them.sin_addr),
02371              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02372 
02373    /* Increment sequence number */
02374    rtp->seqno++;
02375    /* Increment duration */
02376    rtp->send_duration += 160;
02377 
02378    return 0;
02379 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

02383 {
02384    unsigned int *rtpheader;
02385    int hdrlen = 12, res = 0, i = 0;
02386    char data[256];
02387    
02388    /* If no address, then bail out */
02389    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02390       return 0;
02391    
02392    if ((digit <= '9') && (digit >= '0'))
02393       digit -= '0';
02394    else if (digit == '*')
02395       digit = 10;
02396    else if (digit == '#')
02397       digit = 11;
02398    else if ((digit >= 'A') && (digit <= 'D'))
02399       digit = digit - 'A' + 12;
02400    else if ((digit >= 'a') && (digit <= 'd'))
02401       digit = digit - 'a' + 12;
02402    else {
02403       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02404       return 0;
02405    }
02406 
02407    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02408 
02409    rtpheader = (unsigned int *)data;
02410    rtpheader[1] = htonl(rtp->lastdigitts);
02411    rtpheader[2] = htonl(rtp->ssrc);
02412    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02413    /* Set end bit */
02414    rtpheader[3] |= htonl((1 << 23));
02415 
02416    /* Send 3 termination packets */
02417    for (i = 0; i < 3; i++) {
02418       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02419       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02420       rtp->seqno++;
02421       if (res < 0)
02422          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02423             ast_inet_ntoa(rtp->them.sin_addr),
02424             ntohs(rtp->them.sin_port), strerror(errno));
02425       if (rtp_debug_test_addr(&rtp->them))
02426          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02427                 ast_inet_ntoa(rtp->them.sin_addr),
02428                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02429    }
02430    rtp->lastts += rtp->send_duration;
02431    rtp->sending_digit = 0;
02432    rtp->send_digit = 0;
02433 
02434    return res;
02435 }

void ast_rtp_set_alt_peer ( struct ast_rtp rtp,
struct sockaddr_in *  alt 
)

set potential alternate source for RTP media

Since:
1.4.26
This function may be used to give the RTP stack a hint that there is a potential second source of media. One case where this is used is when the SIP stack receives a REINVITE to which it will be replying with a 491. In such a scenario, the IP and port information in the SDP of that REINVITE lets us know that we may receive media from that source/those sources even though the SIP transaction was unable to be completed successfully

Parameters:
rtp The RTP structure we wish to set up an alternate host/port on
alt The address information for the alternate media source
Return values:
void 

Definition at line 2103 of file rtp.c.

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

Referenced by handle_request_invite().

02104 {
02105    rtp->altthem.sin_port = alt->sin_port;
02106    rtp->altthem.sin_addr = alt->sin_addr;
02107    if (rtp->rtcp) {
02108       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02109       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02110    }
02111 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 594 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00595 {
00596    rtp->callback = callback;
00597 }

void ast_rtp_set_constantssrc ( struct ast_rtp rtp  ) 

When changing sources, don't generate a new SSRC.

Definition at line 2077 of file rtp.c.

References ast_rtp::constantssrc.

Referenced by create_addr_from_peer(), and handle_request_invite().

02078 {
02079    rtp->constantssrc = 1;
02080 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 589 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00590 {
00591    rtp->data = data;
00592 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

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

01709 {
01710    if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01711       return; /* bogus payload type */
01712 
01713    ast_mutex_lock(&rtp->bridge_lock);
01714    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01715    ast_mutex_unlock(&rtp->bridge_lock);
01716 } 

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

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

02093 {
02094    rtp->them.sin_port = them->sin_port;
02095    rtp->them.sin_addr = them->sin_addr;
02096    if (rtp->rtcp) {
02097       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02098       rtp->rtcp->them.sin_addr = them->sin_addr;
02099    }
02100    rtp->rxseqno = 0;
02101 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 556 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00557 {
00558    rtp->rtpholdtimeout = timeout;
00559 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 562 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00563 {
00564    rtp->rtpkeepalive = period;
00565 }

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 1735 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(), process_sdp_a_audio(), process_sdp_a_video(), and set_dtmf_payload().

01738 {
01739    unsigned int i;
01740    int found = 0;
01741 
01742    if (pt < 0 || pt >= MAX_RTP_PT) 
01743       return -1; /* bogus payload type */
01744    
01745    ast_mutex_lock(&rtp->bridge_lock);
01746 
01747    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01748       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01749           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01750          found = 1;
01751          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01752          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01753              mimeTypes[i].payloadType.isAstFormat &&
01754              (options & AST_RTP_OPT_G726_NONSTANDARD))
01755             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01756          break;
01757       }
01758    }
01759 
01760    ast_mutex_unlock(&rtp->bridge_lock);
01761 
01762    return (found ? 0 : -1);
01763 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 550 of file rtp.c.

References ast_rtp::rtptimeout.

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

00551 {
00552    rtp->rtptimeout = timeout;
00553 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 543 of file rtp.c.

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

Referenced by handle_response_invite().

00544 {
00545    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00546    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00547 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00610 {
00611    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00612 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00615 {
00616    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00617 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 599 of file rtp.c.

References ast_rtp::nat.

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

00600 {
00601    rtp->nat = nat;
00602 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 619 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00620 {
00621    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00622 }

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 2068 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

02069 {
02070    int res;
02071 
02072    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
02073       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
02074    return res;
02075 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

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

02143 {
02144    if (rtp->rtcp) {
02145       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02146    }
02147 
02148    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02149    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02150    if (rtp->rtcp) {
02151       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02152       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02153    }
02154    
02155    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02156 }

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

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

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

Definition at line 1720 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_a_audio(), and process_sdp_a_video().

01721 {
01722    if (pt < 0 || pt >= MAX_RTP_PT)
01723       return; /* bogus payload type */
01724 
01725    ast_mutex_lock(&rtp->bridge_lock);
01726    rtp->current_RTP_PT[pt].isAstFormat = 0;
01727    rtp->current_RTP_PT[pt].code = 0;
01728    ast_mutex_unlock(&rtp->bridge_lock);
01729 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2877 of file rtp.c.

References ast_codec_pref_getsize(), AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::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().

02878 {
02879    struct ast_frame *f;
02880    int codec;
02881    int hdrlen = 12;
02882    int subclass;
02883    
02884 
02885    /* If we have no peer, return immediately */ 
02886    if (!rtp->them.sin_addr.s_addr)
02887       return 0;
02888 
02889    /* If there is no data length, return immediately */
02890    if (!_f->datalen) 
02891       return 0;
02892    
02893    /* Make sure we have enough space for RTP header */
02894    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02895       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02896       return -1;
02897    }
02898 
02899    subclass = _f->subclass;
02900    if (_f->frametype == AST_FRAME_VIDEO)
02901       subclass &= ~0x1;
02902 
02903    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02904    if (codec < 0) {
02905       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02906       return -1;
02907    }
02908 
02909    if (rtp->lasttxformat != subclass) {
02910       /* New format, reset the smoother */
02911       if (option_debug)
02912          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02913       rtp->lasttxformat = subclass;
02914       if (rtp->smoother)
02915          ast_smoother_free(rtp->smoother);
02916       rtp->smoother = NULL;
02917    }
02918 
02919    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
02920       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02921       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02922          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02923             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));
02924             return -1;
02925          }
02926          if (fmt.flags)
02927             ast_smoother_set_flags(rtp->smoother, fmt.flags);
02928          if (option_debug)
02929             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));
02930       }
02931    }
02932    if (rtp->smoother) {
02933       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
02934          ast_smoother_feed_be(rtp->smoother, _f);
02935       } else {
02936          ast_smoother_feed(rtp->smoother, _f);
02937       }
02938 
02939       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
02940          ast_rtp_raw_write(rtp, f, codec);
02941       }
02942    } else {
02943       /* Don't buffer outgoing frames; send them one-per-packet: */
02944       if (_f->offset < hdrlen) {
02945          f = ast_frdup(_f);
02946       } else {
02947          f = _f;
02948       }
02949       if (f->data) {
02950          ast_rtp_raw_write(rtp, f, codec);
02951       }
02952       if (f != _f)
02953          ast_frfree(f);
02954    }
02955       
02956    return 0;
02957 }

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

02988 {
02989    struct ast_frame *fr = NULL;
02990    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
02991    int oldcodec0 = codec0, oldcodec1 = codec1;
02992    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
02993    struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
02994    
02995    /* Set it up so audio goes directly between the two endpoints */
02996 
02997    /* Test the first channel */
02998    if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
02999       ast_rtp_get_peer(p1, &ac1);
03000       if (vp1)
03001          ast_rtp_get_peer(vp1, &vac1);
03002    } else
03003       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
03004    
03005    /* Test the second channel */
03006    if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
03007       ast_rtp_get_peer(p0, &ac0);
03008       if (vp0)
03009          ast_rtp_get_peer(vp0, &vac0);
03010    } else
03011       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
03012 
03013    /* Now we can unlock and move into our loop */
03014    ast_channel_unlock(c0);
03015    ast_channel_unlock(c1);
03016 
03017    /* Throw our channels into the structure and enter the loop */
03018    cs[0] = c0;
03019    cs[1] = c1;
03020    cs[2] = NULL;
03021    for (;;) {
03022       /* Check if anything changed */
03023       if ((c0->tech_pvt != pvt0) ||
03024           (c1->tech_pvt != pvt1) ||
03025           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03026           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03027          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03028          if (c0->tech_pvt == pvt0)
03029             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03030                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03031          if (c1->tech_pvt == pvt1)
03032             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03033                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03034          return AST_BRIDGE_RETRY;
03035       }
03036 
03037       /* Check if they have changed their address */
03038       ast_rtp_get_peer(p1, &t1);
03039       if (vp1)
03040          ast_rtp_get_peer(vp1, &vt1);
03041       if (pr1->get_codec)
03042          codec1 = pr1->get_codec(c1);
03043       ast_rtp_get_peer(p0, &t0);
03044       if (vp0)
03045          ast_rtp_get_peer(vp0, &vt0);
03046       if (pr0->get_codec)
03047          codec0 = pr0->get_codec(c0);
03048       if ((inaddrcmp(&t1, &ac1)) ||
03049           (vp1 && inaddrcmp(&vt1, &vac1)) ||
03050           (codec1 != oldcodec1)) {
03051          if (option_debug > 1) {
03052             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03053                c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
03054             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
03055                c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
03056             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
03057                c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
03058             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
03059                c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
03060          }
03061          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)))
03062             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
03063          memcpy(&ac1, &t1, sizeof(ac1));
03064          memcpy(&vac1, &vt1, sizeof(vac1));
03065          oldcodec1 = codec1;
03066       }
03067       if ((inaddrcmp(&t0, &ac0)) ||
03068           (vp0 && inaddrcmp(&vt0, &vac0)) ||
03069           (codec0 != oldcodec0)) {
03070          if (option_debug > 1) {
03071             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03072                c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
03073             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
03074                c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
03075          }
03076          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)))
03077             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
03078          memcpy(&ac0, &t0, sizeof(ac0));
03079          memcpy(&vac0, &vt0, sizeof(vac0));
03080          oldcodec0 = codec0;
03081       }
03082 
03083       /* Wait for frame to come in on the channels */
03084       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03085          if (!timeoutms) {
03086             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03087                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03088             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03089                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03090             return AST_BRIDGE_RETRY;
03091          }
03092          if (option_debug)
03093             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03094          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03095             break;
03096          continue;
03097       }
03098       fr = ast_read(who);
03099       other = (who == c0) ? c1 : c0;
03100       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03101              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
03102               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
03103          /* Break out of bridge */
03104          *fo = fr;
03105          *rc = who;
03106          if (option_debug)
03107             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03108          if (c0->tech_pvt == pvt0)
03109             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03110                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03111          if (c1->tech_pvt == pvt1)
03112             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03113                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03114          return AST_BRIDGE_COMPLETE;
03115       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03116          if ((fr->subclass == AST_CONTROL_HOLD) ||
03117              (fr->subclass == AST_CONTROL_UNHOLD) ||
03118              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03119              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03120             if (fr->subclass == AST_CONTROL_HOLD) {
03121                /* If we someone went on hold we want the other side to reinvite back to us */
03122                if (who == c0)
03123                   pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
03124                else
03125                   pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
03126             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03127                /* If they went off hold they should go back to being direct */
03128                if (who == c0)
03129                   pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
03130                else
03131                   pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
03132             }
03133             /* Update local address information */
03134             ast_rtp_get_peer(p0, &t0);
03135             memcpy(&ac0, &t0, sizeof(ac0));
03136             ast_rtp_get_peer(p1, &t1);
03137             memcpy(&ac1, &t1, sizeof(ac1));
03138             /* Update codec information */
03139             if (pr0->get_codec && c0->tech_pvt)
03140                oldcodec0 = codec0 = pr0->get_codec(c0);
03141             if (pr1->get_codec && c1->tech_pvt)
03142                oldcodec1 = codec1 = pr1->get_codec(c1);
03143             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03144             ast_frfree(fr);
03145          } else {
03146             *fo = fr;
03147             *rc = who;
03148             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03149             return AST_BRIDGE_COMPLETE;
03150          }
03151       } else {
03152          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03153              (fr->frametype == AST_FRAME_DTMF_END) ||
03154              (fr->frametype == AST_FRAME_VOICE) ||
03155              (fr->frametype == AST_FRAME_VIDEO) ||
03156              (fr->frametype == AST_FRAME_IMAGE) ||
03157              (fr->frametype == AST_FRAME_HTML) ||
03158              (fr->frametype == AST_FRAME_MODEM) ||
03159              (fr->frametype == AST_FRAME_TEXT)) {
03160             ast_write(other, fr);
03161          }
03162          ast_frfree(fr);
03163       }
03164       /* Swap priority */
03165       cs[2] = cs[0];
03166       cs[0] = cs[1];
03167       cs[1] = cs[2];
03168    }
03169 
03170    if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03171       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03172    if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03173       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03174 
03175    return AST_BRIDGE_FAILED;
03176 }

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

03275 {
03276    struct ast_frame *fr = NULL;
03277    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03278    int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
03279    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03280    int p0_callback = 0, p1_callback = 0;
03281    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03282 
03283    /* Okay, setup each RTP structure to do P2P forwarding */
03284    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03285    p2p_set_bridge(p0, p1);
03286    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03287    p2p_set_bridge(p1, p0);
03288 
03289    /* Activate callback modes if possible */
03290    p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03291    p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03292 
03293    /* Now let go of the channel locks and be on our way */
03294    ast_channel_unlock(c0);
03295    ast_channel_unlock(c1);
03296 
03297    /* Go into a loop forwarding frames until we don't need to anymore */
03298    cs[0] = c0;
03299    cs[1] = c1;
03300    cs[2] = NULL;
03301    for (;;) {
03302       /* If the underlying formats have changed force this bridge to break */
03303       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
03304          ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n");
03305          res = AST_BRIDGE_FAILED_NOWARN;
03306          break;
03307       }
03308       /* Check if anything changed */
03309       if ((c0->tech_pvt != pvt0) ||
03310           (c1->tech_pvt != pvt1) ||
03311           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03312           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03313          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03314          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03315             ast_frfree(fr);
03316          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03317             ast_frfree(fr);
03318          res = AST_BRIDGE_RETRY;
03319          break;
03320       }
03321       /* Wait on a channel to feed us a frame */
03322       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03323          if (!timeoutms) {
03324             res = AST_BRIDGE_RETRY;
03325             break;
03326          }
03327          if (option_debug)
03328             ast_log(LOG_NOTICE, "Ooh, empty read...\n");
03329          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03330             break;
03331          continue;
03332       }
03333       /* Read in frame from channel */
03334       fr = ast_read(who);
03335       other = (who == c0) ? c1 : c0;
03336       /* Dependong on the frame we may need to break out of our bridge */
03337       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03338              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03339              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03340          /* Record received frame and who */
03341          *fo = fr;
03342          *rc = who;
03343          if (option_debug)
03344             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03345          res = AST_BRIDGE_COMPLETE;
03346          break;
03347       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03348          if ((fr->subclass == AST_CONTROL_HOLD) ||
03349              (fr->subclass == AST_CONTROL_UNHOLD) ||
03350              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03351              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03352             /* If we are going on hold, then break callback mode and P2P bridging */
03353             if (fr->subclass == AST_CONTROL_HOLD) {
03354                if (p0_callback)
03355                   p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03356                if (p1_callback)
03357                   p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03358                p2p_set_bridge(p0, NULL);
03359                p2p_set_bridge(p1, NULL);
03360             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03361                /* If we are off hold, then go back to callback mode and P2P bridging */
03362                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03363                p2p_set_bridge(p0, p1);
03364                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03365                p2p_set_bridge(p1, p0);
03366                p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03367                p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03368             }
03369             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03370             ast_frfree(fr);
03371          } else {
03372             *fo = fr;
03373             *rc = who;
03374             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03375             res = AST_BRIDGE_COMPLETE;
03376             break;
03377          }
03378       } else {
03379          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03380              (fr->frametype == AST_FRAME_DTMF_END) ||
03381              (fr->frametype == AST_FRAME_VOICE) ||
03382              (fr->frametype == AST_FRAME_VIDEO) ||
03383              (fr->frametype == AST_FRAME_IMAGE) ||
03384              (fr->frametype == AST_FRAME_HTML) ||
03385              (fr->frametype == AST_FRAME_MODEM) ||
03386              (fr->frametype == AST_FRAME_TEXT)) {
03387             ast_write(other, fr);
03388          }
03389 
03390          ast_frfree(fr);
03391       }
03392       /* Swap priority */
03393       cs[2] = cs[0];
03394       cs[0] = cs[1];
03395       cs[1] = cs[2];
03396    }
03397 
03398    /* If we are totally avoiding the core, then restore our link to it */
03399    if (p0_callback)
03400       p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03401    if (p1_callback)
03402       p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03403 
03404    /* Break out of the direct bridge */
03405    p2p_set_bridge(p0, NULL);
03406    p2p_set_bridge(p1, NULL);
03407 
03408    return res;
03409 }

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

01107 {
01108    int res = 0, payload = 0, bridged_payload = 0, mark;
01109    struct rtpPayloadType rtpPT;
01110    int reconstruct = ntohl(rtpheader[0]);
01111 
01112    /* Get fields from packet */
01113    payload = (reconstruct & 0x7f0000) >> 16;
01114    mark = (((reconstruct & 0x800000) >> 23) != 0);
01115 
01116    /* Check what the payload value should be */
01117    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01118 
01119    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01120    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01121       return -1;
01122 
01123    /* Otherwise adjust bridged payload to match */
01124    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01125 
01126    /* 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 */
01127    if (!bridged->current_RTP_PT[bridged_payload].code)
01128       return -1;
01129 
01130 
01131    /* If the mark bit has not been sent yet... do it now */
01132    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01133       mark = 1;
01134       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01135    }
01136 
01137    /* Reconstruct part of the packet */
01138    reconstruct &= 0xFF80FFFF;
01139    reconstruct |= (bridged_payload << 16);
01140    reconstruct |= (mark << 23);
01141    rtpheader[0] = htonl(reconstruct);
01142 
01143    /* Send the packet back out */
01144    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01145    if (res < 0) {
01146       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01147          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));
01148       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01149          if (option_debug || rtpdebug)
01150             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));
01151          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01152       }
01153       return 0;
01154    } else if (rtp_debug_test_addr(&bridged->them))
01155          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);
01156 
01157    return 0;
01158 }

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

Definition at line 1063 of file rtp.c.

References ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtp::rxtransit, sanitize_tv(), ast_rtp::seedrxts, and ast_frame::subclass.

Referenced by ast_rtp_read(), and schedule_delivery().

01064 {
01065    struct timeval now;
01066    double transit;
01067    double current_time;
01068    double d;
01069    double dtv;
01070    double prog;
01071    int rate = rtp_get_rate(rtp->f.subclass);
01072 
01073    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01074       gettimeofday(&rtp->rxcore, NULL);
01075       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01076       /* map timestamp to a real time */
01077       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01078       rtp->rxcore.tv_sec -= timestamp / rate;
01079       rtp->rxcore.tv_usec -= (timestamp % rate) * 125;
01080       /* Round to 0.1ms for nice, pretty timestamps */
01081       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01082       sanitize_tv(&rtp->rxcore);
01083    }
01084 
01085    gettimeofday(&now,NULL);
01086    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01087    tv->tv_sec = rtp->rxcore.tv_sec + timestamp / rate;
01088    tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % rate) * 125;
01089    sanitize_tv(tv);
01090    prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
01091    dtv = (double)rtp->drxcore + (double)(prog);
01092    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01093    transit = current_time - dtv;
01094    d = transit - rtp->rxtransit;
01095    rtp->rxtransit = transit;
01096    if (d<0)
01097       d=-d;
01098    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01099    if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
01100       rtp->rtcp->maxrxjitter = rtp->rxjitter;
01101    if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01102       rtp->rtcp->minrxjitter = rtp->rxjitter;
01103 }

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

Definition at line 2260 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

02261 {
02262    struct timeval t;
02263    long ms;
02264    if (ast_tvzero(rtp->txcore)) {
02265       rtp->txcore = ast_tvnow();
02266       /* Round to 20ms for nice, pretty timestamps */
02267       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02268    }
02269    /* Use previous txcore if available */
02270    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02271    ms = ast_tvdiff_ms(t, rtp->txcore);
02272    if (ms < 0)
02273       ms = 0;
02274    /* Use what we just got for next time */
02275    rtp->txcore = t;
02276    return (unsigned int) ms;
02277 }

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

Get channel driver interface structure.

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

01533 {
01534    struct ast_rtp_protocol *cur = NULL;
01535 
01536    AST_LIST_LOCK(&protos);
01537    AST_LIST_TRAVERSE(&protos, cur, list) {
01538       if (cur->type == chan->tech->type)
01539          break;
01540    }
01541    AST_LIST_UNLOCK(&protos);
01542 
01543    return cur;
01544 }

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

03246 {
03247    ast_channel_lock(chan);
03248 
03249    /* Remove the callback from the IO context */
03250    ast_io_remove(rtp->io, iod[0]);
03251 
03252    /* Restore file descriptors */
03253    chan->fds[0] = fds[0];
03254    ast_channel_unlock(chan);
03255 
03256    /* Restore callback mode if previously used */
03257    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03258       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03259 
03260    return 0;
03261 }

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

P2P RTP Callback.

Definition at line 3238 of file rtp.c.

Referenced by bridge_p2p_loop().

03239 {
03240    return 0;
03241 }

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

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

Referenced by bridge_p2p_loop().

03265 {
03266    ast_mutex_lock(&rtp0->bridge_lock);
03267    rtp0->bridged = rtp1;
03268    ast_mutex_unlock(&rtp0->bridge_lock);
03269 
03270    return;
03271 }

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

Definition at line 677 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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 716 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::dtmf_duration, ast_rtp::dtmf_timeout, f, FLAG_DTMF_COMPENSATE, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_get_rate(), ast_frame::samples, and send_dtmf().

Referenced by ast_rtp_read().

00717 {
00718    unsigned int event;
00719    unsigned int event_end;
00720    unsigned int samples;
00721    char resp = 0;
00722    struct ast_frame *f = NULL;
00723 
00724    /* Figure out event, event end, and samples */
00725    event = ntohl(*((unsigned int *)(data)));
00726    event >>= 24;
00727    event_end = ntohl(*((unsigned int *)(data)));
00728    event_end <<= 8;
00729    event_end >>= 24;
00730    samples = ntohl(*((unsigned int *)(data)));
00731    samples &= 0xFFFF;
00732 
00733    /* Print out debug if turned on */
00734    if (rtpdebug || option_debug > 2)
00735       ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
00736 
00737    /* Figure out what digit was pressed */
00738    if (event < 10) {
00739       resp = '0' + event;
00740    } else if (event < 11) {
00741       resp = '*';
00742    } else if (event < 12) {
00743       resp = '#';
00744    } else if (event < 16) {
00745       resp = 'A' + (event - 12);
00746    } else if (event < 17) {   /* Event 16: Hook flash */
00747       resp = 'X'; 
00748    } else {
00749       /* Not a supported event */
00750       ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
00751       return &ast_null_frame;
00752    }
00753 
00754    if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
00755       if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
00756          rtp->resp = resp;
00757          rtp->dtmf_timeout = 0;
00758          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00759          f->len = 0;
00760          rtp->lastevent = timestamp;
00761       }
00762    } else {
00763       /*  The duration parameter measures the complete
00764           duration of the event (from the beginning) - RFC2833.
00765           Account for the fact that duration is only 16 bits long
00766           (about 8 seconds at 8000 Hz) and can wrap if digit
00767           is held for too long. */
00768       unsigned int new_duration = rtp->dtmf_duration;
00769       unsigned int last_duration = new_duration & 0xFFFF;
00770 
00771       if (last_duration > 64000 && samples < last_duration)
00772          new_duration += 0xFFFF + 1;
00773       new_duration = (new_duration & ~0xFFFF) | samples;
00774 
00775       if (event_end & 0x80) {
00776          /* End event */
00777          if ((rtp->lastevent != seqno) && rtp->resp) {
00778             rtp->dtmf_duration = new_duration;
00779             f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00780             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
00781             rtp->resp = 0;
00782             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
00783          }
00784       } else {
00785          /* Begin/continuation */
00786 
00787          if (rtp->resp && rtp->resp != resp) {
00788             /* Another digit already began. End it */
00789             f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00790             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
00791             rtp->resp = 0;
00792             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
00793          }
00794 
00795 
00796          if (rtp->resp) {
00797             /* Digit continues */
00798             rtp->dtmf_duration = new_duration;
00799          } else {
00800             /* New digit began */
00801             rtp->resp = resp;
00802             f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
00803             rtp->dtmf_duration = samples;
00804          }
00805 
00806          rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
00807       }
00808 
00809       rtp->lastevent = seqno;
00810    }
00811 
00812    return f;
00813 }

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

00822 {
00823    struct ast_frame *f = NULL;
00824    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
00825       totally help us out becuase we don't have an engine to keep it going and we are not
00826       guaranteed to have it every 20ms or anything */
00827    if (rtpdebug)
00828       ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
00829 
00830    if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
00831       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
00832          ast_inet_ntoa(rtp->them.sin_addr));
00833       ast_set_flag(rtp, FLAG_3389_WARNING);
00834    }
00835 
00836    /* Must have at least one byte */
00837    if (!len)
00838       return NULL;
00839    if (len < 24) {
00840       rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
00841       rtp->f.datalen = len - 1;
00842       rtp->f.offset = AST_FRIENDLY_OFFSET;
00843       memcpy(rtp->f.data, data + 1, len - 1);
00844    } else {
00845       rtp->f.data = NULL;
00846       rtp->f.offset = 0;
00847       rtp->f.datalen = 0;
00848    }
00849    rtp->f.frametype = AST_FRAME_CNG;
00850    rtp->f.subclass = data[0] & 0x7f;
00851    rtp->f.samples = 0;
00852    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
00853    f = &rtp->f;
00854    return f;
00855 }

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

Definition at line 663 of file rtp.c.

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

00664 {
00665    if (rtcpdebug == 0)
00666       return 0;
00667    if (rtcpdebugaddr.sin_addr.s_addr) {
00668       if (((ntohs(rtcpdebugaddr.sin_port) != 0)
00669          && (rtcpdebugaddr.sin_port != addr->sin_port))
00670          || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00671       return 0;
00672    }
00673    return 1;
00674 }

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

Definition at line 3684 of file rtp.c.

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

03684                                                          {
03685    if (argc != 2) {
03686       if (argc != 4)
03687          return RESULT_SHOWUSAGE;
03688       return rtcp_do_debug_ip(fd, argc, argv);
03689    }
03690    rtcpdebug = 1;
03691    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03692    ast_cli(fd, "RTCP Debugging Enabled\n");
03693    return RESULT_SUCCESS;
03694 }

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

Definition at line 3672 of file rtp.c.

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

03672                                                                     {
03673    if (argc != 3) {
03674       if (argc != 5)
03675          return RESULT_SHOWUSAGE;
03676       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03677    }
03678    rtcpdebug = 1;
03679    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03680    ast_cli(fd, "RTCP Debugging Enabled\n");
03681    return RESULT_SUCCESS;
03682 }

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

Definition at line 3629 of file rtp.c.

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

Referenced by rtcp_do_debug().

03630 {
03631    struct hostent *hp;
03632    struct ast_hostent ahp;
03633    int port = 0;
03634    char *p, *arg;
03635    if (argc != 4)
03636       return RESULT_SHOWUSAGE;
03637 
03638    arg = argv[3];
03639    p = strstr(arg, ":");
03640    if (p) {
03641       *p = '\0';
03642       p++;
03643       port = atoi(p);
03644    }
03645    hp = ast_gethostbyname(arg, &ahp);
03646    if (hp == NULL)
03647       return RESULT_SHOWUSAGE;
03648    rtcpdebugaddr.sin_family = AF_INET;
03649    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03650    rtcpdebugaddr.sin_port = htons(port);
03651    if (port == 0)
03652       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03653    else
03654       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03655    rtcpdebug = 1;
03656    return RESULT_SUCCESS;
03657 }

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

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

03600 {
03601    struct hostent *hp;
03602    struct ast_hostent ahp;
03603    int port = 0;
03604    char *p, *arg;
03605    if (argc != 5)
03606       return RESULT_SHOWUSAGE;
03607 
03608    arg = argv[4];
03609    p = strstr(arg, ":");
03610    if (p) {
03611       *p = '\0';
03612       p++;
03613       port = atoi(p);
03614    }
03615    hp = ast_gethostbyname(arg, &ahp);
03616    if (hp == NULL)
03617       return RESULT_SHOWUSAGE;
03618    rtcpdebugaddr.sin_family = AF_INET;
03619    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03620    rtcpdebugaddr.sin_port = htons(port);
03621    if (port == 0)
03622       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03623    else
03624       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03625    rtcpdebug = 1;
03626    return RESULT_SUCCESS;
03627 }

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

Definition at line 3705 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03705                                                          {
03706    if (argc != 2) {
03707       return RESULT_SHOWUSAGE;
03708    }
03709    rtcpstats = 1;
03710    ast_cli(fd, "RTCP Stats Enabled\n");
03711    return RESULT_SUCCESS;
03712 }

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

Definition at line 3696 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03696                                                                     {
03697    if (argc != 3) {
03698       return RESULT_SHOWUSAGE;
03699    }
03700    rtcpstats = 1;
03701    ast_cli(fd, "RTCP Stats Enabled\n");
03702    return RESULT_SUCCESS;
03703 }

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

Definition at line 3732 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03733 {
03734    if (argc != 3)
03735       return RESULT_SHOWUSAGE;
03736    rtcpdebug = 0;
03737    ast_cli(fd,"RTCP Debugging Disabled\n");
03738    return RESULT_SUCCESS;
03739 }

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

Definition at line 3723 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03724 {
03725    if (argc != 4)
03726       return RESULT_SHOWUSAGE;
03727    rtcpdebug = 0;
03728    ast_cli(fd,"RTCP Debugging Disabled\n");
03729    return RESULT_SUCCESS;
03730 }

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

Definition at line 3750 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03751 {
03752    if (argc != 3)
03753       return RESULT_SHOWUSAGE;
03754    rtcpstats = 0;
03755    ast_cli(fd,"RTCP Stats Disabled\n");
03756    return RESULT_SUCCESS;
03757 }

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

Definition at line 3741 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03742 {
03743    if (argc != 4)
03744       return RESULT_SHOWUSAGE;
03745    rtcpstats = 0;
03746    ast_cli(fd,"RTCP Stats Disabled\n");
03747    return RESULT_SUCCESS;
03748 }

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

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

00651 {
00652    if (rtpdebug == 0)
00653       return 0;
00654    if (rtpdebugaddr.sin_addr.s_addr) {
00655       if (((ntohs(rtpdebugaddr.sin_port) != 0)
00656          && (rtpdebugaddr.sin_port != addr->sin_port))
00657          || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00658       return 0;
00659    }
00660    return 1;
00661 }

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

Definition at line 3659 of file rtp.c.

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

03660 {
03661    if (argc != 2) {
03662       if (argc != 4)
03663          return RESULT_SHOWUSAGE;
03664       return rtp_do_debug_ip(fd, argc, argv);
03665    }
03666    rtpdebug = 1;
03667    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03668    ast_cli(fd, "RTP Debugging Enabled\n");
03669    return RESULT_SUCCESS;
03670 }

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

Definition at line 3569 of file rtp.c.

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

Referenced by rtp_do_debug().

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

static int rtp_get_rate ( int  subclass  )  [static]

Definition at line 528 of file rtp.c.

References AST_FORMAT_G722, and ast_format_rate().

Referenced by ast_rtp_raw_write(), ast_rtp_read(), calc_rxstamp(), and process_rfc2833().

00529 {
00530    return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
00531 }

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

Definition at line 3714 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03715 {
03716    if (argc != 3)
03717       return RESULT_SHOWUSAGE;
03718    rtpdebug = 0;
03719    ast_cli(fd,"RTP Debugging Disabled\n");
03720    return RESULT_SUCCESS;
03721 }

static int rtp_socket ( void   )  [static]

Definition at line 1907 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01908 {
01909    int s;
01910    long flags;
01911    s = socket(AF_INET, SOCK_DGRAM, 0);
01912    if (s > -1) {
01913       flags = fcntl(s, F_GETFL);
01914       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01915 #ifdef SO_NO_CHECK
01916       if (nochecksums)
01917          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01918 #endif
01919    }
01920    return s;
01921 }

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

Definition at line 857 of file rtp.c.

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

Referenced by p2p_callback_disable().

00858 {
00859    struct ast_rtp *rtp = cbdata;
00860    struct ast_frame *f;
00861    f = ast_rtp_read(rtp);
00862    if (f) {
00863       if (rtp->callback)
00864          rtp->callback(rtp, f, rtp->data);
00865    }
00866    return 1;
00867 }

static void sanitize_tv ( struct timeval *  tv  )  [static]

Definition at line 1051 of file rtp.c.

Referenced by calc_rxstamp().

01052 {
01053    while (tv->tv_usec < 0) {
01054       tv->tv_usec += 1000000;
01055       tv->tv_sec -= 1;
01056    }
01057    while (tv->tv_usec >= 1000000) {
01058       tv->tv_usec -= 1000000;
01059       tv->tv_sec += 1;
01060    }
01061 }

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

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

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

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

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

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

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

Definition at line 3759 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03760 {
03761    if (argc != 2) {
03762       return RESULT_SHOWUSAGE;
03763    }
03764    stundebug = 1;
03765    ast_cli(fd, "STUN Debugging Enabled\n");
03766    return RESULT_SUCCESS;
03767 }

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

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

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

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

Definition at line 284 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3769 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03770 {
03771    if (argc != 3)
03772       return RESULT_SHOWUSAGE;
03773    stundebug = 0;
03774    ast_cli(fd, "STUN Debugging Disabled\n");
03775    return RESULT_SUCCESS;
03776 }

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

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

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

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 394 of file rtp.c.

References ast_random(), stun_trans_id::id, and stun_header::id.

Referenced by ast_rtp_stun_request().

00395 {
00396    int x;
00397    for (x=0;x<4;x++)
00398       req->id.id[x] = ast_random();
00399 }

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

Definition at line 388 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

00389 {
00390    return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00391       (struct sockaddr *)dst, sizeof(*dst));
00392 }

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

Definition at line 506 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3845 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 3810 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 3820 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 3815 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 3825 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 3835 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 3830 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 3840 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 3778 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 3782 of file rtp.c.

struct rtpPayloadType payloadType

Definition at line 1403 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 3794 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 3798 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 3806 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

Definition at line 3802 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 1438 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 3786 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3790 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1405 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1404 of file rtp.c.

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


Generated on Thu Dec 17 15:36:12 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7