Sat Aug 6 00:40:04 2011

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  frame_list
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.
void ast_rtp_change_source (struct ast_rtp *rtp)
 Indicate that we need to set the marker bit and change the ssrc.
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)
 Indicate that we need to set the marker bit.
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)
int ast_rtp_senddigit_end_with_duration (struct ast_rtp *rtp, char digit, unsigned int duration)
 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_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_framecreate_dtmf_frame (struct ast_rtp *rtp, enum ast_frame_type type)
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 void process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct frame_list *frames)
 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 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 191 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 198 of file rtp.c.

Referenced by p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 199 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

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

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

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

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 269 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 267 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 268 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 282 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 264 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 281 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 280 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 284 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 272 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 270 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 271 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 283 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

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

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Definition at line 359 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 535 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

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

01980 {
01981    struct ast_rtcp *rtcp;
01982 
01983    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01984       return NULL;
01985    rtcp->s = rtp_socket();
01986    if (option_debug > 3)
01987          ast_log(LOG_DEBUG, "socket RTPaux (RTCP) fd: %i\n", rtcp->s);
01988    rtcp->us.sin_family = AF_INET;
01989    rtcp->them.sin_family = AF_INET;
01990    rtcp->schedid = -1;
01991 
01992    if (rtcp->s < 0) {
01993       free(rtcp);
01994       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01995       return NULL;
01996    }
01997 
01998    return rtcp;
01999 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

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

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

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

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

02511 {
02512    struct ast_rtp *rtp = data;
02513    int res;
02514 
02515    rtp->rtcp->sendfur = 1;
02516    res = ast_rtcp_write(data);
02517    
02518    return res;
02519 }

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

02728 {
02729    struct ast_rtp *rtp = (struct ast_rtp *)data;
02730    int res;
02731    
02732    if (!rtp || !rtp->rtcp)
02733       return 0;
02734 
02735    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02736       res = ast_rtcp_write_sr(data);
02737    else
02738       res = ast_rtcp_write_rr(data);
02739    
02740    return res;
02741 }

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

02633 {
02634    struct ast_rtp *rtp = (struct ast_rtp *)data;
02635    int res;
02636    int len = 32;
02637    unsigned int lost;
02638    unsigned int extended;
02639    unsigned int expected;
02640    unsigned int expected_interval;
02641    unsigned int received_interval;
02642    int lost_interval;
02643    struct timeval now;
02644    unsigned int *rtcpheader;
02645    char bdata[1024];
02646    struct timeval dlsr;
02647    int fraction;
02648 
02649    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
02650       return 0;
02651      
02652    if (!rtp->rtcp->them.sin_addr.s_addr) {
02653       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
02654       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02655       return 0;
02656    }
02657 
02658    extended = rtp->cycles + rtp->lastrxseqno;
02659    expected = extended - rtp->seedrxseqno + 1;
02660    lost = expected - rtp->rxcount;
02661    expected_interval = expected - rtp->rtcp->expected_prior;
02662    rtp->rtcp->expected_prior = expected;
02663    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02664    rtp->rtcp->received_prior = rtp->rxcount;
02665    lost_interval = expected_interval - received_interval;
02666    if (expected_interval == 0 || lost_interval <= 0)
02667       fraction = 0;
02668    else
02669       fraction = (lost_interval << 8) / expected_interval;
02670    gettimeofday(&now, NULL);
02671    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02672    rtcpheader = (unsigned int *)bdata;
02673    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
02674    rtcpheader[1] = htonl(rtp->ssrc);
02675    rtcpheader[2] = htonl(rtp->themssrc);
02676    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02677    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02678    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02679    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
02680    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02681 
02682    if (rtp->rtcp->sendfur) {
02683       rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
02684       rtcpheader[9] = htonl(rtp->ssrc);               /* Our SSRC */
02685       len += 8;
02686       rtp->rtcp->sendfur = 0;
02687    }
02688 
02689    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
02690    it can change mid call, and SDES can't) */
02691    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02692    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02693    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
02694    len += 12;
02695    
02696    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02697 
02698    if (res < 0) {
02699       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
02700       /* Remove the scheduler */
02701       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02702       return 0;
02703    }
02704 
02705    rtp->rtcp->rr_count++;
02706 
02707    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02708       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
02709          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 
02710          "  IA jitter: %.4f\n" 
02711          "  Their last SR: %u\n" 
02712          "  DLSR: %4.4f (sec)\n\n",
02713          ast_inet_ntoa(rtp->rtcp->them.sin_addr),
02714          ntohs(rtp->rtcp->them.sin_port),
02715          rtp->ssrc, rtp->themssrc, fraction, lost,
02716          rtp->rxjitter,
02717          rtp->rtcp->themrxlsr,
02718          (double)(ntohl(rtcpheader[7])/65536.0));
02719    }
02720 
02721    return res;
02722 }

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

Send RTCP sender's report.

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

02523 {
02524    struct ast_rtp *rtp = (struct ast_rtp *)data;
02525    int res;
02526    int len = 0;
02527    struct timeval now;
02528    unsigned int now_lsw;
02529    unsigned int now_msw;
02530    unsigned int *rtcpheader;
02531    unsigned int lost;
02532    unsigned int extended;
02533    unsigned int expected;
02534    unsigned int expected_interval;
02535    unsigned int received_interval;
02536    int lost_interval;
02537    int fraction;
02538    struct timeval dlsr;
02539    char bdata[512];
02540 
02541    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
02542    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
02543       return 0;
02544    
02545    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
02546       ast_verbose("RTCP SR transmission error, rtcp halted\n");
02547       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02548       return 0;
02549    }
02550 
02551    gettimeofday(&now, NULL);
02552    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
02553    rtcpheader = (unsigned int *)bdata;
02554    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
02555    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
02556    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
02557    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
02558    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
02559    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
02560    len += 28;
02561    
02562    extended = rtp->cycles + rtp->lastrxseqno;
02563    expected = extended - rtp->seedrxseqno + 1;
02564    if (rtp->rxcount > expected) 
02565       expected += rtp->rxcount - expected;
02566    lost = expected - rtp->rxcount;
02567    expected_interval = expected - rtp->rtcp->expected_prior;
02568    rtp->rtcp->expected_prior = expected;
02569    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02570    rtp->rtcp->received_prior = rtp->rxcount;
02571    lost_interval = expected_interval - received_interval;
02572    if (expected_interval == 0 || lost_interval <= 0)
02573       fraction = 0;
02574    else
02575       fraction = (lost_interval << 8) / expected_interval;
02576    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02577    rtcpheader[7] = htonl(rtp->themssrc);
02578    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02579    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02580    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02581    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
02582    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02583    len += 24;
02584    
02585    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
02586 
02587    if (rtp->rtcp->sendfur) {
02588       rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
02589       rtcpheader[14] = htonl(rtp->ssrc);               /* Our SSRC */
02590       len += 8;
02591       rtp->rtcp->sendfur = 0;
02592    }
02593    
02594    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 
02595    /* it can change mid call, and SDES can't) */
02596    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02597    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02598    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
02599    len += 12;
02600    
02601    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02602    if (res < 0) {
02603       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));
02604       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02605       return 0;
02606    }
02607    
02608    /* FIXME Don't need to get a new one */
02609    gettimeofday(&rtp->rtcp->txlsr, NULL);
02610    rtp->rtcp->sr_count++;
02611 
02612    rtp->rtcp->lastsrtxcount = rtp->txcount;  
02613    
02614    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02615       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
02616       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
02617       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
02618       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
02619       ast_verbose("  Sent packets: %u\n", rtp->txcount);
02620       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
02621       ast_verbose("  Report block:\n");
02622       ast_verbose("  Fraction lost: %u\n", fraction);
02623       ast_verbose("  Cumulative loss: %u\n", lost);
02624       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
02625       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
02626       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
02627    }
02628    return res;
02629 }

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

Referenced by process_sdp().

00404 {
00405    return sizeof(struct ast_rtp);
00406 }

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

03487 {
03488    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03489    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03490    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03491    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03492    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03493    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03494    int codec0 = 0, codec1 = 0;
03495    void *pvt0 = NULL, *pvt1 = NULL;
03496 
03497    /* Lock channels */
03498    ast_channel_lock(c0);
03499    while(ast_channel_trylock(c1)) {
03500       ast_channel_unlock(c0);
03501       usleep(1);
03502       ast_channel_lock(c0);
03503    }
03504 
03505    /* Ensure neither channel got hungup during lock avoidance */
03506    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03507       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
03508       ast_channel_unlock(c0);
03509       ast_channel_unlock(c1);
03510       return AST_BRIDGE_FAILED;
03511    }
03512       
03513    /* Find channel driver interfaces */
03514    if (!(pr0 = get_proto(c0))) {
03515       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03516       ast_channel_unlock(c0);
03517       ast_channel_unlock(c1);
03518       return AST_BRIDGE_FAILED;
03519    }
03520    if (!(pr1 = get_proto(c1))) {
03521       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03522       ast_channel_unlock(c0);
03523       ast_channel_unlock(c1);
03524       return AST_BRIDGE_FAILED;
03525    }
03526 
03527    /* Get channel specific interface structures */
03528    pvt0 = c0->tech_pvt;
03529    pvt1 = c1->tech_pvt;
03530 
03531    /* Get audio and video interface (if native bridge is possible) */
03532    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03533    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03534    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03535    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03536 
03537    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03538    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03539       audio_p0_res = AST_RTP_GET_FAILED;
03540    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03541       audio_p1_res = AST_RTP_GET_FAILED;
03542 
03543    /* Check if a bridge is possible (partial/native) */
03544    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03545       /* Somebody doesn't want to play... */
03546       ast_channel_unlock(c0);
03547       ast_channel_unlock(c1);
03548       return AST_BRIDGE_FAILED_NOWARN;
03549    }
03550 
03551    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03552    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03553       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03554       audio_p0_res = AST_RTP_TRY_PARTIAL;
03555    }
03556 
03557    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03558       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03559       audio_p1_res = AST_RTP_TRY_PARTIAL;
03560    }
03561 
03562    /* If both sides are not using the same method of DTMF transmission 
03563     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03564     * --------------------------------------------------
03565     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03566     * |-----------|------------|-----------------------|
03567     * | Inband    | False      | True                  |
03568     * | RFC2833   | True       | True                  |
03569     * | SIP INFO  | False      | False                 |
03570     * --------------------------------------------------
03571     * However, if DTMF from both channels is being monitored by the core, then
03572     * we can still do packet-to-packet bridging, because passing through the 
03573     * core will handle DTMF mode translation.
03574     */
03575    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03576        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03577       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03578          ast_channel_unlock(c0);
03579          ast_channel_unlock(c1);
03580          return AST_BRIDGE_FAILED_NOWARN;
03581       }
03582       audio_p0_res = AST_RTP_TRY_PARTIAL;
03583       audio_p1_res = AST_RTP_TRY_PARTIAL;
03584    }
03585 
03586    /* If we need to feed frames into the core don't do a P2P bridge */
03587    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
03588        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
03589       ast_channel_unlock(c0);
03590       ast_channel_unlock(c1);
03591       return AST_BRIDGE_FAILED_NOWARN;
03592    }
03593 
03594    /* Get codecs from both sides */
03595    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03596    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03597    if (codec0 && codec1 && !(codec0 & codec1)) {
03598       /* Hey, we can't do native bridging if both parties speak different codecs */
03599       if (option_debug)
03600          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03601       ast_channel_unlock(c0);
03602       ast_channel_unlock(c1);
03603       return AST_BRIDGE_FAILED_NOWARN;
03604    }
03605 
03606    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03607    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03608       struct ast_format_list fmt0, fmt1;
03609 
03610       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03611       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03612          if (option_debug)
03613             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03614          ast_channel_unlock(c0);
03615          ast_channel_unlock(c1);
03616          return AST_BRIDGE_FAILED_NOWARN;
03617       }
03618       /* They must also be using the same packetization */
03619       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
03620       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
03621       if (fmt0.cur_ms != fmt1.cur_ms) {
03622          if (option_debug)
03623             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n");
03624          ast_channel_unlock(c0);
03625          ast_channel_unlock(c1);
03626          return AST_BRIDGE_FAILED_NOWARN;
03627       }
03628 
03629       if (option_verbose > 2)
03630          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03631       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03632    } else {
03633       if (option_verbose > 2) 
03634          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03635       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03636    }
03637 
03638    return res;
03639 }

void ast_rtp_change_source ( struct ast_rtp rtp  ) 

Indicate that we need to set the marker bit and change the ssrc.

Definition at line 2138 of file rtp.c.

References ast_log(), ast_random(), LOG_DEBUG, option_debug, ast_rtp::set_marker_bit, and ast_rtp::ssrc.

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

02139 {
02140    if (rtp) {
02141       unsigned int ssrc = ast_random();
02142 
02143       rtp->set_marker_bit = 1;
02144       if (option_debug > 2) {
02145          ast_log(LOG_DEBUG, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc);
02146       }
02147       rtp->ssrc = ssrc;
02148    }
02149 }

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2938 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp_a_audio().

02939 {
02940    if (pt < 0 || pt >= MAX_RTP_PT)
02941       return 0; /* bogus payload type */
02942 
02943    if (static_RTP_PT[pt].isAstFormat)
02944       return static_RTP_PT[pt].code;
02945    else
02946       return 0;
02947 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2933 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

02934 {
02935    return &rtp->pref;
02936 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

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

02887 {
02888    struct ast_format_list current_format_old, current_format_new;
02889 
02890    /* if no packets have been sent through this session yet, then
02891     *  changing preferences does not require any extra work
02892     */
02893    if (rtp->lasttxformat == 0) {
02894       rtp->pref = *prefs;
02895       return 0;
02896    }
02897 
02898    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
02899 
02900    rtp->pref = *prefs;
02901 
02902    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
02903 
02904    /* if the framing desired for the current format has changed, we may have to create
02905     * or adjust the smoother for this session
02906     */
02907    if ((current_format_new.inc_ms != 0) &&
02908        (current_format_new.cur_ms != current_format_old.cur_ms)) {
02909       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
02910 
02911       if (rtp->smoother) {
02912          ast_smoother_reconfigure(rtp->smoother, new_size);
02913          if (option_debug) {
02914             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
02915          }
02916       } else {
02917          if (!(rtp->smoother = ast_smoother_new(new_size))) {
02918             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
02919             return -1;
02920          }
02921          if (current_format_new.flags) {
02922             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
02923          }
02924          if (option_debug) {
02925             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
02926          }
02927       }
02928    }
02929 
02930    return 0;
02931 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

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

02281 {
02282    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02283       /*Print some info on the call here */
02284       ast_verbose("  RTP-stats\n");
02285       ast_verbose("* Our Receiver:\n");
02286       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02287       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02288       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
02289       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02290       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02291       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
02292       ast_verbose("* Our Sender:\n");
02293       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02294       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02295       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
02296       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
02297       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
02298       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
02299    }
02300 
02301    if (rtp->smoother)
02302       ast_smoother_free(rtp->smoother);
02303    if (rtp->ioid)
02304       ast_io_remove(rtp->io, rtp->ioid);
02305    if (rtp->s > -1)
02306       close(rtp->s);
02307    if (rtp->rtcp) {
02308       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02309       close(rtp->rtcp->s);
02310       free(rtp->rtcp);
02311       rtp->rtcp=NULL;
02312    }
02313 
02314    ast_mutex_destroy(&rtp->bridge_lock);
02315 
02316    free(rtp);
02317 }

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

01598 {
01599    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01600    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01601    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01602    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01603    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
01604    int srccodec, destcodec, nat_active = 0;
01605 
01606    /* Lock channels */
01607    ast_channel_lock(dest);
01608    if (src) {
01609       while(ast_channel_trylock(src)) {
01610          ast_channel_unlock(dest);
01611          usleep(1);
01612          ast_channel_lock(dest);
01613       }
01614    }
01615 
01616    /* Find channel driver interfaces */
01617    destpr = get_proto(dest);
01618    if (src)
01619       srcpr = get_proto(src);
01620    if (!destpr) {
01621       if (option_debug)
01622          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01623       ast_channel_unlock(dest);
01624       if (src)
01625          ast_channel_unlock(src);
01626       return 0;
01627    }
01628    if (!srcpr) {
01629       if (option_debug)
01630          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>");
01631       ast_channel_unlock(dest);
01632       if (src)
01633          ast_channel_unlock(src);
01634       return 0;
01635    }
01636 
01637    /* Get audio and video interface (if native bridge is possible) */
01638    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01639    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01640    if (srcpr) {
01641       audio_src_res = srcpr->get_rtp_info(src, &srcp);
01642       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01643    }
01644 
01645    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01646    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
01647       /* Somebody doesn't want to play... */
01648       ast_channel_unlock(dest);
01649       if (src)
01650          ast_channel_unlock(src);
01651       return 0;
01652    }
01653    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)
01654       srccodec = srcpr->get_codec(src);
01655    else
01656       srccodec = 0;
01657    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)
01658       destcodec = destpr->get_codec(dest);
01659    else
01660       destcodec = 0;
01661    /* Ensure we have at least one matching codec */
01662    if (srcp && !(srccodec & destcodec)) {
01663       ast_channel_unlock(dest);
01664       ast_channel_unlock(src);
01665       return 0;
01666    }
01667    /* Consider empty media as non-existant */
01668    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
01669       srcp = NULL;
01670    /* If the client has NAT stuff turned on then just safe NAT is active */
01671    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01672       nat_active = 1;
01673    /* Bridge media early */
01674    if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active))
01675       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>");
01676    ast_channel_unlock(dest);
01677    if (src)
01678       ast_channel_unlock(src);
01679    if (option_debug)
01680       ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>");
01681    return 1;
01682 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00519 {
00520    return rtp->s;
00521 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

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

02191 {
02192    struct ast_rtp *bridged = NULL;
02193 
02194    ast_mutex_lock(&rtp->bridge_lock);
02195    bridged = rtp->bridged;
02196    ast_mutex_unlock(&rtp->bridge_lock);
02197 
02198    return bridged;
02199 }

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

01820 {
01821    int pt;
01822    
01823    ast_mutex_lock(&rtp->bridge_lock);
01824    
01825    *astFormats = *nonAstFormats = 0;
01826    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01827       if (rtp->current_RTP_PT[pt].isAstFormat) {
01828          *astFormats |= rtp->current_RTP_PT[pt].code;
01829       } else {
01830          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01831       }
01832    }
01833    
01834    ast_mutex_unlock(&rtp->bridge_lock);
01835    
01836    return;
01837 }

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

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

02173 {
02174    if ((them->sin_family != AF_INET) ||
02175       (them->sin_port != rtp->them.sin_port) ||
02176       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02177       them->sin_family = AF_INET;
02178       them->sin_port = rtp->them.sin_port;
02179       them->sin_addr = rtp->them.sin_addr;
02180       return 1;
02181    }
02182    return 0;
02183 }

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

Return RTCP quality string.

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

02237 {
02238    /*
02239    *ssrc          our ssrc
02240    *themssrc      their ssrc
02241    *lp            lost packets
02242    *rxjitter      our calculated jitter(rx)
02243    *rxcount       no. received packets
02244    *txjitter      reported jitter of the other end
02245    *txcount       transmitted packets
02246    *rlp           remote lost packets
02247    *rtt           round trip time
02248    */
02249 
02250    if (qual && rtp) {
02251       qual->local_ssrc = rtp->ssrc;
02252       qual->local_jitter = rtp->rxjitter;
02253       qual->local_count = rtp->rxcount;
02254       qual->remote_ssrc = rtp->themssrc;
02255       qual->remote_count = rtp->txcount;
02256       if (rtp->rtcp) {
02257          qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02258          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02259          qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02260          qual->rtt = rtp->rtcp->rtt;
02261       }
02262    }
02263    if (rtp->rtcp) {
02264       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02265          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02266          rtp->ssrc,
02267          rtp->themssrc,
02268          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02269          rtp->rxjitter,
02270          rtp->rxcount,
02271          (double)rtp->rtcp->reported_jitter / 65536.0,
02272          rtp->txcount,
02273          rtp->rtcp->reported_lost,
02274          rtp->rtcp->rtt);
02275       return rtp->rtcp->quality;
02276    } else
02277       return "<Unknown> - RTP/RTCP has already been destroyed";
02278 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 578 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 586 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00587 {
00588    return rtp->rtpkeepalive;
00589 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 570 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

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

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

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

02186 {
02187    *us = rtp->us;
02188 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 606 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00607 {
00608    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00609 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4024 of file rtp.c.

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

Referenced by main().

04025 {
04026    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04027    ast_rtp_reload();
04028 }

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

01862 {
01863    int pt = 0;
01864 
01865    ast_mutex_lock(&rtp->bridge_lock);
01866 
01867    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
01868       code == rtp->rtp_lookup_code_cache_code) {
01869       /* Use our cached mapping, to avoid the overhead of the loop below */
01870       pt = rtp->rtp_lookup_code_cache_result;
01871       ast_mutex_unlock(&rtp->bridge_lock);
01872       return pt;
01873    }
01874 
01875    /* Check the dynamic list first */
01876    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01877       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
01878          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01879          rtp->rtp_lookup_code_cache_code = code;
01880          rtp->rtp_lookup_code_cache_result = pt;
01881          ast_mutex_unlock(&rtp->bridge_lock);
01882          return pt;
01883       }
01884    }
01885 
01886    /* Then the static list */
01887    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01888       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
01889          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01890          rtp->rtp_lookup_code_cache_code = code;
01891          rtp->rtp_lookup_code_cache_result = pt;
01892          ast_mutex_unlock(&rtp->bridge_lock);
01893          return pt;
01894       }
01895    }
01896 
01897    ast_mutex_unlock(&rtp->bridge_lock);
01898 
01899    return -1;
01900 }

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

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

Referenced by process_sdp().

01923 {
01924    int format;
01925    unsigned len;
01926    char *end = buf;
01927    char *start = buf;
01928 
01929    if (!buf || !size)
01930       return NULL;
01931 
01932    snprintf(end, size, "0x%x (", capability);
01933 
01934    len = strlen(end);
01935    end += len;
01936    size -= len;
01937    start = end;
01938 
01939    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01940       if (capability & format) {
01941          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01942 
01943          snprintf(end, size, "%s|", name);
01944          len = strlen(end);
01945          end += len;
01946          size -= len;
01947       }
01948    }
01949 
01950    if (start == end)
01951       snprintf(start, size, "nothing)"); 
01952    else if (size > 1)
01953       *(end -1) = ')';
01954    
01955    return buf;
01956 }

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

01904 {
01905    unsigned int i;
01906 
01907    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01908       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01909          if (isAstFormat &&
01910              (code == AST_FORMAT_G726_AAL2) &&
01911              (options & AST_RTP_OPT_G726_NONSTANDARD))
01912             return "G726-32";
01913          else
01914             return mimeTypes[i].subtype;
01915       }
01916    }
01917 
01918    return "";
01919 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

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

01840 {
01841    struct rtpPayloadType result;
01842 
01843    result.isAstFormat = result.code = 0;
01844 
01845    if (pt < 0 || pt >= MAX_RTP_PT) 
01846       return result; /* bogus payload type */
01847 
01848    /* Start with negotiated codecs */
01849    ast_mutex_lock(&rtp->bridge_lock);
01850    result = rtp->current_RTP_PT[pt];
01851    ast_mutex_unlock(&rtp->bridge_lock);
01852 
01853    /* If it doesn't exist, check our static RTP type list, just in case */
01854    if (!result.code) 
01855       result = static_RTP_PT[pt];
01856 
01857    return result;
01858 }

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

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

01685 {
01686    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01687    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01688    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01689    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01690    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 
01691    int srccodec, destcodec;
01692 
01693    /* Lock channels */
01694    ast_channel_lock(dest);
01695    while(ast_channel_trylock(src)) {
01696       ast_channel_unlock(dest);
01697       usleep(1);
01698       ast_channel_lock(dest);
01699    }
01700 
01701    /* Find channel driver interfaces */
01702    if (!(destpr = get_proto(dest))) {
01703       if (option_debug)
01704          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01705       ast_channel_unlock(dest);
01706       ast_channel_unlock(src);
01707       return 0;
01708    }
01709    if (!(srcpr = get_proto(src))) {
01710       if (option_debug)
01711          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
01712       ast_channel_unlock(dest);
01713       ast_channel_unlock(src);
01714       return 0;
01715    }
01716 
01717    /* Get audio and video interface (if native bridge is possible) */
01718    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01719    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01720    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01721    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01722 
01723    /* Ensure we have at least one matching codec */
01724    if (srcpr->get_codec)
01725       srccodec = srcpr->get_codec(src);
01726    else
01727       srccodec = 0;
01728    if (destpr->get_codec)
01729       destcodec = destpr->get_codec(dest);
01730    else
01731       destcodec = 0;
01732 
01733    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01734    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)) {
01735       /* Somebody doesn't want to play... */
01736       ast_channel_unlock(dest);
01737       ast_channel_unlock(src);
01738       return 0;
01739    }
01740    ast_rtp_pt_copy(destp, srcp);
01741    if (vdestp && vsrcp)
01742       ast_rtp_pt_copy(vdestp, vsrcp);
01743    if (media) {
01744       /* Bridge early */
01745       if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01746          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
01747    }
01748    ast_channel_unlock(dest);
01749    ast_channel_unlock(src);
01750    if (option_debug)
01751       ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
01752    return 1;
01753 }

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02112 {
02113    struct in_addr ia;
02114 
02115    memset(&ia, 0, sizeof(ia));
02116    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02117 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

02006 {
02007    ast_mutex_init(&rtp->bridge_lock);
02008 
02009    rtp->them.sin_family = AF_INET;
02010    rtp->us.sin_family = AF_INET;
02011    rtp->ssrc = ast_random();
02012    rtp->seqno = ast_random() & 0xffff;
02013    ast_set_flag(rtp, FLAG_HAS_DTMF);
02014 
02015    return;
02016 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Indicate that we need to set the marker bit.

Definition at line 2128 of file rtp.c.

References ast_log(), LOG_DEBUG, option_debug, and ast_rtp::set_marker_bit.

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

02129 {
02130    if (rtp) {
02131       rtp->set_marker_bit = 1;
02132       if (option_debug > 2) {
02133          ast_log(LOG_DEBUG, "Setting the marker bit due to a source update\n");
02134       }
02135    }
02136 }

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

02019 {
02020    struct ast_rtp *rtp;
02021    int x;
02022    int first;
02023    int startplace;
02024    
02025    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
02026       return NULL;
02027 
02028    ast_rtp_new_init(rtp);
02029 
02030    rtp->s = rtp_socket();
02031    if (option_debug > 2)
02032          ast_log(LOG_DEBUG, "socket RTP fd: %i\n", rtp->s); 
02033    if (rtp->s < 0) {
02034       free(rtp);
02035       ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
02036       return NULL;
02037    }
02038    if (sched && rtcpenable) {
02039       rtp->sched = sched;
02040       rtp->rtcp = ast_rtcp_new();
02041       if (option_debug > 2)
02042             ast_log(LOG_DEBUG, "socket RTCP fd: %i\n", rtp->rtcp->s);
02043    }
02044    
02045    /* Select a random port number in the range of possible RTP */
02046    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
02047    x = x & ~1;
02048    /* Save it for future references. */
02049    startplace = x;
02050    /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
02051    for (;;) {
02052       /* Must be an even port number by RTP spec */
02053       rtp->us.sin_port = htons(x);
02054       rtp->us.sin_addr = addr;
02055       /* If there's rtcp, initialize it as well. */
02056       if (rtp->rtcp) {
02057          rtp->rtcp->us.sin_port = htons(x + 1);
02058          rtp->rtcp->us.sin_addr = addr;
02059       }
02060       /* Try to bind it/them. */
02061       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
02062          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
02063          break;
02064       if (!first) {
02065          /* Primary bind succeeded! Gotta recreate it */
02066          close(rtp->s);
02067          rtp->s = rtp_socket();
02068          if (option_debug > 2)
02069                ast_log(LOG_DEBUG, "socket RTP2 fd: %i\n", rtp->s); 
02070       }
02071       if (errno != EADDRINUSE) {
02072          /* We got an error that wasn't expected, abort! */
02073          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02074          close(rtp->s);
02075          if (rtp->rtcp) {
02076             close(rtp->rtcp->s);
02077             free(rtp->rtcp);
02078          }
02079          free(rtp);
02080          return NULL;
02081       }
02082       /* The port was used, increment it (by two). */
02083       x += 2;
02084       /* Did we go over the limit ? */
02085       if (x > rtpend)
02086          /* then, start from the begingig. */
02087          x = (rtpstart + 1) & ~1;
02088       /* Check if we reached the place were we started. */
02089       if (x == startplace) {
02090          /* If so, there's no ports available. */
02091          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02092          close(rtp->s);
02093          if (rtp->rtcp) {
02094             close(rtp->rtcp->s);
02095             free(rtp->rtcp);
02096          }
02097          free(rtp);
02098          return NULL;
02099       }
02100    }
02101    rtp->sched = sched;
02102    rtp->io = io;
02103    if (callbackmode) {
02104       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02105       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02106    }
02107    ast_rtp_pt_default(rtp);
02108    return rtp;
02109 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

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

03041 {
03042    struct ast_rtp_protocol *cur;
03043 
03044    AST_LIST_LOCK(&protos);
03045    AST_LIST_TRAVERSE(&protos, cur, list) {   
03046       if (!strcmp(cur->type, proto->type)) {
03047          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03048          AST_LIST_UNLOCK(&protos);
03049          return -1;
03050       }
03051    }
03052    AST_LIST_INSERT_HEAD(&protos, proto, list);
03053    AST_LIST_UNLOCK(&protos);
03054    
03055    return 0;
03056 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 3032 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by load_module(), and unload_module().

03033 {
03034    AST_LIST_LOCK(&protos);
03035    AST_LIST_REMOVE(&protos, proto, list);
03036    AST_LIST_UNLOCK(&protos);
03037 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

01522 {
01523    int i;
01524 
01525    if (!rtp)
01526       return;
01527 
01528    ast_mutex_lock(&rtp->bridge_lock);
01529 
01530    for (i = 0; i < MAX_RTP_PT; ++i) {
01531       rtp->current_RTP_PT[i].isAstFormat = 0;
01532       rtp->current_RTP_PT[i].code = 0;
01533    }
01534 
01535    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01536    rtp->rtp_lookup_code_cache_code = 0;
01537    rtp->rtp_lookup_code_cache_result = 0;
01538 
01539    ast_mutex_unlock(&rtp->bridge_lock);
01540 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01562 {
01563    unsigned int i;
01564 
01565    ast_mutex_lock(&dest->bridge_lock);
01566    ast_mutex_lock(&src->bridge_lock);
01567 
01568    for (i=0; i < MAX_RTP_PT; ++i) {
01569       dest->current_RTP_PT[i].isAstFormat = 
01570          src->current_RTP_PT[i].isAstFormat;
01571       dest->current_RTP_PT[i].code = 
01572          src->current_RTP_PT[i].code; 
01573    }
01574    dest->rtp_lookup_code_cache_isAstFormat = 0;
01575    dest->rtp_lookup_code_cache_code = 0;
01576    dest->rtp_lookup_code_cache_result = 0;
01577 
01578    ast_mutex_unlock(&src->bridge_lock);
01579    ast_mutex_unlock(&dest->bridge_lock);
01580 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

01543 {
01544    int i;
01545 
01546    ast_mutex_lock(&rtp->bridge_lock);
01547 
01548    /* Initialize to default payload types */
01549    for (i = 0; i < MAX_RTP_PT; ++i) {
01550       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01551       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01552    }
01553 
01554    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01555    rtp->rtp_lookup_code_cache_code = 0;
01556    rtp->rtp_lookup_code_cache_result = 0;
01557 
01558    ast_mutex_unlock(&rtp->bridge_lock);
01559 }

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

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

02779 {
02780    unsigned char *rtpheader;
02781    int hdrlen = 12;
02782    int res;
02783    unsigned int ms;
02784    int pred;
02785    int mark = 0;
02786    int rate = rtp_get_rate(f->subclass) / 1000;
02787 
02788    if (f->subclass == AST_FORMAT_G722) {
02789       /* G722 is silllllllllllllllllly */
02790       f->samples /= 2;
02791    }
02792 
02793    if (rtp->sending_digit) {
02794       return 0;
02795    }
02796 
02797    ms = calc_txstamp(rtp, &f->delivery);
02798    /* Default prediction */
02799    if (f->frametype == AST_FRAME_VOICE) {
02800       pred = rtp->lastts + f->samples;
02801 
02802       /* Re-calculate last TS */
02803       rtp->lastts = rtp->lastts + ms * rate;
02804       if (ast_tvzero(f->delivery)) {
02805          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
02806             and if so, go with our prediction */
02807          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
02808             rtp->lastts = pred;
02809          else {
02810             if (option_debug > 2)
02811                ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
02812             mark = 1;
02813          }
02814       }
02815    } else if (f->frametype == AST_FRAME_VIDEO) {
02816       mark = f->subclass & 0x1;
02817       pred = rtp->lastovidtimestamp + f->samples;
02818       /* Re-calculate last TS */
02819       rtp->lastts = rtp->lastts + ms * 90;
02820       /* If it's close to our prediction, go for it */
02821       if (ast_tvzero(f->delivery)) {
02822          if (abs(rtp->lastts - pred) < 7200) {
02823             rtp->lastts = pred;
02824             rtp->lastovidtimestamp += f->samples;
02825          } else {
02826             if (option_debug > 2)
02827                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);
02828             rtp->lastovidtimestamp = rtp->lastts;
02829          }
02830       }
02831    }
02832 
02833    /* If we have been explicitly told to set the marker bit do so */
02834    if (rtp->set_marker_bit) {
02835       mark = 1;
02836       rtp->set_marker_bit = 0;
02837    }
02838 
02839    /* If the timestamp for non-digit packets has moved beyond the timestamp
02840       for digits, update the digit timestamp.
02841    */
02842    if (rtp->lastts > rtp->lastdigitts)
02843       rtp->lastdigitts = rtp->lastts;
02844 
02845    if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
02846       rtp->lastts = f->ts * rate;
02847 
02848    /* Get a pointer to the header */
02849    rtpheader = (unsigned char *)(f->data - hdrlen);
02850 
02851    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
02852    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
02853    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
02854 
02855    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02856       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02857       if (res <0) {
02858          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
02859             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));
02860          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
02861             /* Only give this error message once if we are not RTP debugging */
02862             if (option_debug || rtpdebug)
02863                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));
02864             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
02865          }
02866       } else {
02867          rtp->txcount++;
02868          rtp->txoctetcount +=(res - hdrlen);
02869          
02870          /* Do not schedule RR if RTCP isn't run */
02871          if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
02872              rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
02873          }
02874       }
02875             
02876       if (rtp_debug_test_addr(&rtp->them))
02877          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02878                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
02879    }
02880 
02881    rtp->seqno++;
02882 
02883    return 0;
02884 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1182 of file rtp.c.

References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, 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, create_dtmf_frame(), 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, frames, 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, 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().

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

int ast_rtp_reload ( void   ) 

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

03960 {
03961    struct ast_config *cfg;
03962    const char *s;
03963 
03964    rtpstart = 5000;
03965    rtpend = 31000;
03966    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03967    cfg = ast_config_load("rtp.conf");
03968    if (cfg) {
03969       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03970          rtpstart = atoi(s);
03971          if (rtpstart < 1024)
03972             rtpstart = 1024;
03973          if (rtpstart > 65535)
03974             rtpstart = 65535;
03975       }
03976       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03977          rtpend = atoi(s);
03978          if (rtpend < 1024)
03979             rtpend = 1024;
03980          if (rtpend > 65535)
03981             rtpend = 65535;
03982       }
03983       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03984          rtcpinterval = atoi(s);
03985          if (rtcpinterval == 0)
03986             rtcpinterval = 0; /* Just so we're clear... it's zero */
03987          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03988             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03989          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03990             rtcpinterval = RTCP_MAX_INTERVALMS;
03991       }
03992       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03993 #ifdef SO_NO_CHECK
03994          if (ast_false(s))
03995             nochecksums = 1;
03996          else
03997             nochecksums = 0;
03998 #else
03999          if (ast_false(s))
04000             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
04001 #endif
04002       }
04003       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
04004          dtmftimeout = atoi(s);
04005          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
04006             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
04007                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
04008             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04009          };
04010       }
04011       ast_config_destroy(cfg);
04012    }
04013    if (rtpstart >= rtpend) {
04014       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
04015       rtpstart = 5000;
04016       rtpend = 31000;
04017    }
04018    if (option_verbose > 1)
04019       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
04020    return 0;
04021 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

02218 {
02219    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02220    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02221    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02222    rtp->lastts = 0;
02223    rtp->lastdigitts = 0;
02224    rtp->lastrxts = 0;
02225    rtp->lastividtimestamp = 0;
02226    rtp->lastovidtimestamp = 0;
02227    rtp->lasteventseqn = 0;
02228    rtp->lastevent = 0;
02229    rtp->lasttxformat = 0;
02230    rtp->lastrxformat = 0;
02231    rtp->dtmf_timeout = 0;
02232    rtp->seqno = 0;
02233    rtp->rxseqno = 0;
02234 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

02745 {
02746    unsigned int *rtpheader;
02747    int hdrlen = 12;
02748    int res;
02749    int payload;
02750    char data[256];
02751    level = 127 - (level & 0x7f);
02752    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
02753 
02754    /* If we have no peer, return immediately */ 
02755    if (!rtp->them.sin_addr.s_addr)
02756       return 0;
02757 
02758    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02759 
02760    /* Get a pointer to the header */
02761    rtpheader = (unsigned int *)data;
02762    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02763    rtpheader[1] = htonl(rtp->lastts);
02764    rtpheader[2] = htonl(rtp->ssrc); 
02765    data[12] = level;
02766    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02767       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02768       if (res <0) 
02769          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));
02770       if (rtp_debug_test_addr(&rtp->them))
02771          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
02772                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
02773          
02774    }
02775    return 0;
02776 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

02340 {
02341    unsigned int *rtpheader;
02342    int hdrlen = 12, res = 0, i = 0, payload = 0;
02343    char data[256];
02344 
02345    if ((digit <= '9') && (digit >= '0'))
02346       digit -= '0';
02347    else if (digit == '*')
02348       digit = 10;
02349    else if (digit == '#')
02350       digit = 11;
02351    else if ((digit >= 'A') && (digit <= 'D'))
02352       digit = digit - 'A' + 12;
02353    else if ((digit >= 'a') && (digit <= 'd'))
02354       digit = digit - 'a' + 12;
02355    else {
02356       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02357       return 0;
02358    }
02359 
02360    /* If we have no peer, return immediately */ 
02361    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02362       return 0;
02363 
02364    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02365 
02366    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02367    rtp->send_duration = 160;
02368    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
02369    
02370    /* Get a pointer to the header */
02371    rtpheader = (unsigned int *)data;
02372    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02373    rtpheader[1] = htonl(rtp->lastdigitts);
02374    rtpheader[2] = htonl(rtp->ssrc); 
02375 
02376    for (i = 0; i < 2; i++) {
02377       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02378       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02379       if (res < 0) 
02380          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02381             ast_inet_ntoa(rtp->them.sin_addr),
02382             ntohs(rtp->them.sin_port), strerror(errno));
02383       if (rtp_debug_test_addr(&rtp->them))
02384          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02385                 ast_inet_ntoa(rtp->them.sin_addr),
02386                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02387       /* Increment sequence number */
02388       rtp->seqno++;
02389       /* Increment duration */
02390       rtp->send_duration += 160;
02391       /* Clear marker bit and set seqno */
02392       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02393    }
02394 
02395    /* Since we received a begin, we can safely store the digit and disable any compensation */
02396    rtp->sending_digit = 1;
02397    rtp->send_digit = digit;
02398    rtp->send_payload = payload;
02399 
02400    return 0;
02401 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

02405 {
02406    unsigned int *rtpheader;
02407    int hdrlen = 12, res = 0;
02408    char data[256];
02409 
02410    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02411       return 0;
02412 
02413    /* Setup packet to send */
02414    rtpheader = (unsigned int *)data;
02415         rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02416         rtpheader[1] = htonl(rtp->lastdigitts);
02417         rtpheader[2] = htonl(rtp->ssrc);
02418         rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
02419    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02420    
02421    /* Transmit */
02422    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02423    if (res < 0)
02424       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02425          ast_inet_ntoa(rtp->them.sin_addr),
02426          ntohs(rtp->them.sin_port), strerror(errno));
02427    if (rtp_debug_test_addr(&rtp->them))
02428       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02429              ast_inet_ntoa(rtp->them.sin_addr),
02430              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02431 
02432    /* Increment sequence number */
02433    rtp->seqno++;
02434    /* Increment duration */
02435    rtp->send_duration += 160;
02436 
02437    return 0;
02438 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Definition at line 2440 of file rtp.c.

References ast_rtp_senddigit_end_with_duration().

Referenced by mgcp_senddigit_end(), and oh323_digit_end().

02441 {
02442    return ast_rtp_senddigit_end_with_duration(rtp, digit, 0);
02443 }

int ast_rtp_senddigit_end_with_duration ( struct ast_rtp rtp,
char  digit,
unsigned int  duration 
)

Send end packets for DTMF.

Definition at line 2446 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::f, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_DEBUG, LOG_ERROR, LOG_WARNING, option_debug, rtp_debug_test_addr(), rtp_get_rate(), 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, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_senddigit_end(), and sip_senddigit_end().

02447 {
02448    unsigned int *rtpheader;
02449    int hdrlen = 12, res = 0, i = 0;
02450    char data[256];
02451    unsigned int measured_samples;
02452    
02453    /* If no address, then bail out */
02454    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02455       return 0;
02456    
02457    if ((digit <= '9') && (digit >= '0'))
02458       digit -= '0';
02459    else if (digit == '*')
02460       digit = 10;
02461    else if (digit == '#')
02462       digit = 11;
02463    else if ((digit >= 'A') && (digit <= 'D'))
02464       digit = digit - 'A' + 12;
02465    else if ((digit >= 'a') && (digit <= 'd'))
02466       digit = digit - 'a' + 12;
02467    else {
02468       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02469       return 0;
02470    }
02471 
02472    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02473 
02474    if (duration > 0 && (measured_samples = duration * rtp_get_rate(rtp->f.subclass) / 1000) > rtp->send_duration) {
02475       if (option_debug > 1) {
02476          ast_log(LOG_DEBUG, "Adjusting final end duration from %u to %u\n", rtp->send_duration, measured_samples);
02477       }
02478       rtp->send_duration = measured_samples;
02479    }
02480 
02481    rtpheader = (unsigned int *)data;
02482    rtpheader[1] = htonl(rtp->lastdigitts);
02483    rtpheader[2] = htonl(rtp->ssrc);
02484    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02485    /* Set end bit */
02486    rtpheader[3] |= htonl((1 << 23));
02487 
02488    /* Send 3 termination packets */
02489    for (i = 0; i < 3; i++) {
02490       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02491       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02492       rtp->seqno++;
02493       if (res < 0)
02494          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02495             ast_inet_ntoa(rtp->them.sin_addr),
02496             ntohs(rtp->them.sin_port), strerror(errno));
02497       if (rtp_debug_test_addr(&rtp->them))
02498          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02499                 ast_inet_ntoa(rtp->them.sin_addr),
02500                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02501    }
02502    rtp->lastts += rtp->send_duration;
02503    rtp->sending_digit = 0;
02504    rtp->send_digit = 0;
02505 
02506    return res;
02507 }

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

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

Referenced by handle_request_invite().

02163 {
02164    rtp->altthem.sin_port = alt->sin_port;
02165    rtp->altthem.sin_addr = alt->sin_addr;
02166    if (rtp->rtcp) {
02167       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02168       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02169    }
02170 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 596 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00597 {
00598    rtp->callback = callback;
00599 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 591 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

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

01760 {
01761    if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01762       return; /* bogus payload type */
01763 
01764    ast_mutex_lock(&rtp->bridge_lock);
01765    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01766    ast_mutex_unlock(&rtp->bridge_lock);
01767 } 

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

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

02152 {
02153    rtp->them.sin_port = them->sin_port;
02154    rtp->them.sin_addr = them->sin_addr;
02155    if (rtp->rtcp) {
02156       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02157       rtp->rtcp->them.sin_addr = them->sin_addr;
02158    }
02159    rtp->rxseqno = 0;
02160 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 558 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00559 {
00560    rtp->rtpholdtimeout = timeout;
00561 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 564 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00565 {
00566    rtp->rtpkeepalive = period;
00567 }

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

01789 {
01790    unsigned int i;
01791    int found = 0;
01792 
01793    if (pt < 0 || pt >= MAX_RTP_PT) 
01794       return -1; /* bogus payload type */
01795    
01796    ast_mutex_lock(&rtp->bridge_lock);
01797 
01798    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01799       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01800           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01801          found = 1;
01802          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01803          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01804              mimeTypes[i].payloadType.isAstFormat &&
01805              (options & AST_RTP_OPT_G726_NONSTANDARD))
01806             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01807          break;
01808       }
01809    }
01810 
01811    ast_mutex_unlock(&rtp->bridge_lock);
01812 
01813    return (found ? 0 : -1);
01814 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 552 of file rtp.c.

References ast_rtp::rtptimeout.

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

00553 {
00554    rtp->rtptimeout = timeout;
00555 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 545 of file rtp.c.

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

Referenced by handle_response_invite().

00546 {
00547    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00548    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00549 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00612 {
00613    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00614 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00617 {
00618    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00619 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 601 of file rtp.c.

References ast_rtp::nat.

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

00602 {
00603    rtp->nat = nat;
00604 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 621 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00622 {
00623    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00624 }

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 2119 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

02120 {
02121    int res;
02122 
02123    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
02124       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
02125    return res;
02126 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

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

02202 {
02203    if (rtp->rtcp) {
02204       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02205    }
02206 
02207    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02208    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02209    if (rtp->rtcp) {
02210       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02211       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02212    }
02213    
02214    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02215 }

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

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

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

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

01772 {
01773    if (pt < 0 || pt >= MAX_RTP_PT)
01774       return; /* bogus payload type */
01775 
01776    ast_mutex_lock(&rtp->bridge_lock);
01777    rtp->current_RTP_PT[pt].isAstFormat = 0;
01778    rtp->current_RTP_PT[pt].code = 0;
01779    ast_mutex_unlock(&rtp->bridge_lock);
01780 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

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

02950 {
02951    struct ast_frame *f;
02952    int codec;
02953    int hdrlen = 12;
02954    int subclass;
02955    
02956 
02957    /* If we have no peer, return immediately */ 
02958    if (!rtp->them.sin_addr.s_addr)
02959       return 0;
02960 
02961    /* If there is no data length, return immediately */
02962    if (!_f->datalen) 
02963       return 0;
02964    
02965    /* Make sure we have enough space for RTP header */
02966    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02967       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02968       return -1;
02969    }
02970 
02971    subclass = _f->subclass;
02972    if (_f->frametype == AST_FRAME_VIDEO)
02973       subclass &= ~0x1;
02974 
02975    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02976    if (codec < 0) {
02977       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02978       return -1;
02979    }
02980 
02981    if (rtp->lasttxformat != subclass) {
02982       /* New format, reset the smoother */
02983       if (option_debug)
02984          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02985       rtp->lasttxformat = subclass;
02986       if (rtp->smoother)
02987          ast_smoother_free(rtp->smoother);
02988       rtp->smoother = NULL;
02989    }
02990 
02991    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
02992       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02993       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02994          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02995             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));
02996             return -1;
02997          }
02998          if (fmt.flags)
02999             ast_smoother_set_flags(rtp->smoother, fmt.flags);
03000          if (option_debug)
03001             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));
03002       }
03003    }
03004    if (rtp->smoother) {
03005       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03006          ast_smoother_feed_be(rtp->smoother, _f);
03007       } else {
03008          ast_smoother_feed(rtp->smoother, _f);
03009       }
03010 
03011       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
03012          ast_rtp_raw_write(rtp, f, codec);
03013       }
03014    } else {
03015       /* Don't buffer outgoing frames; send them one-per-packet: */
03016       if (_f->offset < hdrlen) {
03017          f = ast_frdup(_f);
03018       } else {
03019          f = _f;
03020       }
03021       if (f->data) {
03022          ast_rtp_raw_write(rtp, f, codec);
03023       }
03024       if (f != _f)
03025          ast_frfree(f);
03026    }
03027       
03028    return 0;
03029 }

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

03060 {
03061    struct ast_frame *fr = NULL;
03062    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03063    int oldcodec0 = codec0, oldcodec1 = codec1;
03064    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
03065    struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
03066    
03067    /* Set it up so audio goes directly between the two endpoints */
03068 
03069    /* Test the first channel */
03070    if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
03071       ast_rtp_get_peer(p1, &ac1);
03072       if (vp1)
03073          ast_rtp_get_peer(vp1, &vac1);
03074    } else
03075       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
03076    
03077    /* Test the second channel */
03078    if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
03079       ast_rtp_get_peer(p0, &ac0);
03080       if (vp0)
03081          ast_rtp_get_peer(vp0, &vac0);
03082    } else
03083       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
03084 
03085    /* Now we can unlock and move into our loop */
03086    ast_channel_unlock(c0);
03087    ast_channel_unlock(c1);
03088 
03089    /* Throw our channels into the structure and enter the loop */
03090    cs[0] = c0;
03091    cs[1] = c1;
03092    cs[2] = NULL;
03093    for (;;) {
03094       /* Check if anything changed */
03095       if ((c0->tech_pvt != pvt0) ||
03096           (c1->tech_pvt != pvt1) ||
03097           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03098           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03099          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03100          if (c0->tech_pvt == pvt0)
03101             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03102                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03103          if (c1->tech_pvt == pvt1)
03104             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03105                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03106          return AST_BRIDGE_RETRY;
03107       }
03108 
03109       /* Check if they have changed their address */
03110       ast_rtp_get_peer(p1, &t1);
03111       if (vp1)
03112          ast_rtp_get_peer(vp1, &vt1);
03113       if (pr1->get_codec)
03114          codec1 = pr1->get_codec(c1);
03115       ast_rtp_get_peer(p0, &t0);
03116       if (vp0)
03117          ast_rtp_get_peer(vp0, &vt0);
03118       if (pr0->get_codec)
03119          codec0 = pr0->get_codec(c0);
03120       if ((inaddrcmp(&t1, &ac1)) ||
03121           (vp1 && inaddrcmp(&vt1, &vac1)) ||
03122           (codec1 != oldcodec1)) {
03123          if (option_debug > 1) {
03124             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03125                c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
03126             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
03127                c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
03128             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
03129                c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
03130             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
03131                c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
03132          }
03133          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)))
03134             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
03135          memcpy(&ac1, &t1, sizeof(ac1));
03136          memcpy(&vac1, &vt1, sizeof(vac1));
03137          oldcodec1 = codec1;
03138       }
03139       if ((inaddrcmp(&t0, &ac0)) ||
03140           (vp0 && inaddrcmp(&vt0, &vac0)) ||
03141           (codec0 != oldcodec0)) {
03142          if (option_debug > 1) {
03143             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03144                c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
03145             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
03146                c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
03147          }
03148          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)))
03149             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
03150          memcpy(&ac0, &t0, sizeof(ac0));
03151          memcpy(&vac0, &vt0, sizeof(vac0));
03152          oldcodec0 = codec0;
03153       }
03154 
03155       /* Wait for frame to come in on the channels */
03156       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03157          if (!timeoutms) {
03158             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03159                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03160             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03161                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03162             return AST_BRIDGE_RETRY;
03163          }
03164          if (option_debug)
03165             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03166          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03167             break;
03168          continue;
03169       }
03170       fr = ast_read(who);
03171       other = (who == c0) ? c1 : c0;
03172       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03173              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
03174               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
03175          /* Break out of bridge */
03176          *fo = fr;
03177          *rc = who;
03178          if (option_debug)
03179             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03180          if (c0->tech_pvt == pvt0)
03181             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03182                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03183          if (c1->tech_pvt == pvt1)
03184             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03185                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03186          return AST_BRIDGE_COMPLETE;
03187       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03188          if ((fr->subclass == AST_CONTROL_HOLD) ||
03189              (fr->subclass == AST_CONTROL_UNHOLD) ||
03190              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03191              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03192             if (fr->subclass == AST_CONTROL_HOLD) {
03193                /* If we someone went on hold we want the other side to reinvite back to us */
03194                if (who == c0)
03195                   pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
03196                else
03197                   pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
03198             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03199                /* If they went off hold they should go back to being direct */
03200                if (who == c0)
03201                   pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
03202                else
03203                   pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
03204             }
03205             /* Update local address information */
03206             ast_rtp_get_peer(p0, &t0);
03207             memcpy(&ac0, &t0, sizeof(ac0));
03208             ast_rtp_get_peer(p1, &t1);
03209             memcpy(&ac1, &t1, sizeof(ac1));
03210             /* Update codec information */
03211             if (pr0->get_codec && c0->tech_pvt)
03212                oldcodec0 = codec0 = pr0->get_codec(c0);
03213             if (pr1->get_codec && c1->tech_pvt)
03214                oldcodec1 = codec1 = pr1->get_codec(c1);
03215             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03216             ast_frfree(fr);
03217          } else {
03218             *fo = fr;
03219             *rc = who;
03220             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03221             return AST_BRIDGE_COMPLETE;
03222          }
03223       } else {
03224          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03225              (fr->frametype == AST_FRAME_DTMF_END) ||
03226              (fr->frametype == AST_FRAME_VOICE) ||
03227              (fr->frametype == AST_FRAME_VIDEO) ||
03228              (fr->frametype == AST_FRAME_IMAGE) ||
03229              (fr->frametype == AST_FRAME_HTML) ||
03230              (fr->frametype == AST_FRAME_MODEM) ||
03231              (fr->frametype == AST_FRAME_TEXT)) {
03232             ast_write(other, fr);
03233          }
03234          ast_frfree(fr);
03235       }
03236       /* Swap priority */
03237       cs[2] = cs[0];
03238       cs[0] = cs[1];
03239       cs[1] = cs[2];
03240    }
03241 
03242    if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03243       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03244    if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03245       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03246 
03247    return AST_BRIDGE_FAILED;
03248 }

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

03347 {
03348    struct ast_frame *fr = NULL;
03349    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03350    int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
03351    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03352    int p0_callback = 0, p1_callback = 0;
03353    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03354 
03355    /* Okay, setup each RTP structure to do P2P forwarding */
03356    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03357    p2p_set_bridge(p0, p1);
03358    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03359    p2p_set_bridge(p1, p0);
03360 
03361    /* Activate callback modes if possible */
03362    p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03363    p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03364 
03365    /* Now let go of the channel locks and be on our way */
03366    ast_channel_unlock(c0);
03367    ast_channel_unlock(c1);
03368 
03369    /* Go into a loop forwarding frames until we don't need to anymore */
03370    cs[0] = c0;
03371    cs[1] = c1;
03372    cs[2] = NULL;
03373    for (;;) {
03374       /* If the underlying formats have changed force this bridge to break */
03375       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
03376          ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n");
03377          res = AST_BRIDGE_FAILED_NOWARN;
03378          break;
03379       }
03380       /* Check if anything changed */
03381       if ((c0->tech_pvt != pvt0) ||
03382           (c1->tech_pvt != pvt1) ||
03383           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03384           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03385          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03386          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03387             ast_frfree(fr);
03388          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03389             ast_frfree(fr);
03390          res = AST_BRIDGE_RETRY;
03391          break;
03392       }
03393       /* Wait on a channel to feed us a frame */
03394       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03395          if (!timeoutms) {
03396             res = AST_BRIDGE_RETRY;
03397             break;
03398          }
03399          if (option_debug)
03400             ast_log(LOG_NOTICE, "Ooh, empty read...\n");
03401          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03402             break;
03403          continue;
03404       }
03405       /* Read in frame from channel */
03406       fr = ast_read(who);
03407       other = (who == c0) ? c1 : c0;
03408       /* Dependong on the frame we may need to break out of our bridge */
03409       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03410              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03411              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03412          /* Record received frame and who */
03413          *fo = fr;
03414          *rc = who;
03415          if (option_debug)
03416             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03417          res = AST_BRIDGE_COMPLETE;
03418          break;
03419       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03420          if ((fr->subclass == AST_CONTROL_HOLD) ||
03421              (fr->subclass == AST_CONTROL_UNHOLD) ||
03422              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03423              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03424             /* If we are going on hold, then break callback mode and P2P bridging */
03425             if (fr->subclass == AST_CONTROL_HOLD) {
03426                if (p0_callback)
03427                   p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03428                if (p1_callback)
03429                   p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03430                p2p_set_bridge(p0, NULL);
03431                p2p_set_bridge(p1, NULL);
03432             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03433                /* If we are off hold, then go back to callback mode and P2P bridging */
03434                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03435                p2p_set_bridge(p0, p1);
03436                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03437                p2p_set_bridge(p1, p0);
03438                p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03439                p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03440             }
03441             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03442             ast_frfree(fr);
03443          } else {
03444             *fo = fr;
03445             *rc = who;
03446             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03447             res = AST_BRIDGE_COMPLETE;
03448             break;
03449          }
03450       } else {
03451          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03452              (fr->frametype == AST_FRAME_DTMF_END) ||
03453              (fr->frametype == AST_FRAME_VOICE) ||
03454              (fr->frametype == AST_FRAME_VIDEO) ||
03455              (fr->frametype == AST_FRAME_IMAGE) ||
03456              (fr->frametype == AST_FRAME_HTML) ||
03457              (fr->frametype == AST_FRAME_MODEM) ||
03458              (fr->frametype == AST_FRAME_TEXT)) {
03459             ast_write(other, fr);
03460          }
03461 
03462          ast_frfree(fr);
03463       }
03464       /* Swap priority */
03465       cs[2] = cs[0];
03466       cs[0] = cs[1];
03467       cs[1] = cs[2];
03468    }
03469 
03470    /* If we are totally avoiding the core, then restore our link to it */
03471    if (p0_callback)
03472       p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03473    if (p1_callback)
03474       p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03475 
03476    /* Break out of the direct bridge */
03477    p2p_set_bridge(p0, NULL);
03478    p2p_set_bridge(p1, NULL);
03479 
03480    return res;
03481 }

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

01129 {
01130    int res = 0, payload = 0, bridged_payload = 0, mark;
01131    struct rtpPayloadType rtpPT;
01132    int reconstruct = ntohl(rtpheader[0]);
01133 
01134    /* Get fields from packet */
01135    payload = (reconstruct & 0x7f0000) >> 16;
01136    mark = (((reconstruct & 0x800000) >> 23) != 0);
01137 
01138    /* Check what the payload value should be */
01139    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01140 
01141    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01142    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01143       return -1;
01144 
01145    /* Otherwise adjust bridged payload to match */
01146    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01147 
01148    /* 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 */
01149    if (!bridged->current_RTP_PT[bridged_payload].code)
01150       return -1;
01151 
01152 
01153    /* If the mark bit has not been sent yet... do it now */
01154    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01155       mark = 1;
01156       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01157    }
01158 
01159    /* Reconstruct part of the packet */
01160    reconstruct &= 0xFF80FFFF;
01161    reconstruct |= (bridged_payload << 16);
01162    reconstruct |= (mark << 23);
01163    rtpheader[0] = htonl(reconstruct);
01164 
01165    /* Send the packet back out */
01166    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01167    if (res < 0) {
01168       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01169          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));
01170       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01171          if (option_debug || rtpdebug)
01172             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));
01173          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01174       }
01175       return 0;
01176    } else if (rtp_debug_test_addr(&bridged->them))
01177          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);
01178 
01179    return 0;
01180 }

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

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

01086 {
01087    struct timeval now;
01088    double transit;
01089    double current_time;
01090    double d;
01091    double dtv;
01092    double prog;
01093    int rate = rtp_get_rate(rtp->f.subclass);
01094 
01095    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01096       gettimeofday(&rtp->rxcore, NULL);
01097       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01098       /* map timestamp to a real time */
01099       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01100       rtp->rxcore.tv_sec -= timestamp / rate;
01101       rtp->rxcore.tv_usec -= (timestamp % rate) * 125;
01102       /* Round to 0.1ms for nice, pretty timestamps */
01103       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01104       sanitize_tv(&rtp->rxcore);
01105    }
01106 
01107    gettimeofday(&now,NULL);
01108    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01109    tv->tv_sec = rtp->rxcore.tv_sec + timestamp / rate;
01110    tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % rate) * 125;
01111    sanitize_tv(tv);
01112    prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
01113    dtv = (double)rtp->drxcore + (double)(prog);
01114    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01115    transit = current_time - dtv;
01116    d = transit - rtp->rxtransit;
01117    rtp->rxtransit = transit;
01118    if (d<0)
01119       d=-d;
01120    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01121    if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
01122       rtp->rtcp->maxrxjitter = rtp->rxjitter;
01123    if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01124       rtp->rtcp->minrxjitter = rtp->rxjitter;
01125 }

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

Definition at line 2319 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

02320 {
02321    struct timeval t;
02322    long ms;
02323    if (ast_tvzero(rtp->txcore)) {
02324       rtp->txcore = ast_tvnow();
02325       /* Round to 20ms for nice, pretty timestamps */
02326       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02327    }
02328    /* Use previous txcore if available */
02329    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02330    ms = ast_tvdiff_ms(t, rtp->txcore);
02331    if (ms < 0)
02332       ms = 0;
02333    /* Use what we just got for next time */
02334    rtp->txcore = t;
02335    return (unsigned int) ms;
02336 }

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

Definition at line 626 of file rtp.c.

References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), AST_LIST_NEXT, 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().

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

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

Get channel driver interface structure.

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

01584 {
01585    struct ast_rtp_protocol *cur = NULL;
01586 
01587    AST_LIST_LOCK(&protos);
01588    AST_LIST_TRAVERSE(&protos, cur, list) {
01589       if (cur->type == chan->tech->type)
01590          break;
01591    }
01592    AST_LIST_UNLOCK(&protos);
01593 
01594    return cur;
01595 }

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

03318 {
03319    ast_channel_lock(chan);
03320 
03321    /* Remove the callback from the IO context */
03322    ast_io_remove(rtp->io, iod[0]);
03323 
03324    /* Restore file descriptors */
03325    chan->fds[0] = fds[0];
03326    ast_channel_unlock(chan);
03327 
03328    /* Restore callback mode if previously used */
03329    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03330       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03331 
03332    return 0;
03333 }

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

P2P RTP Callback.

Definition at line 3310 of file rtp.c.

Referenced by bridge_p2p_loop().

03311 {
03312    return 0;
03313 }

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

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

Referenced by bridge_p2p_loop().

03337 {
03338    ast_mutex_lock(&rtp0->bridge_lock);
03339    rtp0->bridged = rtp1;
03340    ast_mutex_unlock(&rtp0->bridge_lock);
03341 
03342    return;
03343 }

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

Definition at line 680 of file rtp.c.

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

Referenced by ast_rtp_read().

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

static void process_rfc2833 ( struct ast_rtp rtp,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
struct frame_list frames 
) [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 
frames 
Returns:

Definition at line 720 of file rtp.c.

References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup(), AST_LIST_INSERT_TAIL, ast_log(), ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), create_dtmf_frame(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, f, FLAG_DTMF_COMPENSATE, frames, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_get_rate(), and ast_frame::samples.

Referenced by ast_rtp_read().

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

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

00840 {
00841    struct ast_frame *f = NULL;
00842    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
00843       totally help us out becuase we don't have an engine to keep it going and we are not
00844       guaranteed to have it every 20ms or anything */
00845    if (rtpdebug)
00846       ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
00847 
00848    if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
00849       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
00850          ast_inet_ntoa(rtp->them.sin_addr));
00851       ast_set_flag(rtp, FLAG_3389_WARNING);
00852    }
00853 
00854    /* Must have at least one byte */
00855    if (!len)
00856       return NULL;
00857    if (len < 24) {
00858       rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
00859       rtp->f.datalen = len - 1;
00860       rtp->f.offset = AST_FRIENDLY_OFFSET;
00861       memcpy(rtp->f.data, data + 1, len - 1);
00862    } else {
00863       rtp->f.data = NULL;
00864       rtp->f.offset = 0;
00865       rtp->f.datalen = 0;
00866    }
00867    rtp->f.frametype = AST_FRAME_CNG;
00868    rtp->f.subclass = data[0] & 0x7f;
00869    rtp->f.samples = 0;
00870    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
00871    f = &rtp->f;
00872    return f;
00873 }

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

Definition at line 666 of file rtp.c.

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

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

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

Definition at line 3756 of file rtp.c.

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

03756                                                          {
03757    if (argc != 2) {
03758       if (argc != 4)
03759          return RESULT_SHOWUSAGE;
03760       return rtcp_do_debug_ip(fd, argc, argv);
03761    }
03762    rtcpdebug = 1;
03763    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03764    ast_cli(fd, "RTCP Debugging Enabled\n");
03765    return RESULT_SUCCESS;
03766 }

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

Definition at line 3744 of file rtp.c.

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

03744                                                                     {
03745    if (argc != 3) {
03746       if (argc != 5)
03747          return RESULT_SHOWUSAGE;
03748       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03749    }
03750    rtcpdebug = 1;
03751    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03752    ast_cli(fd, "RTCP Debugging Enabled\n");
03753    return RESULT_SUCCESS;
03754 }

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

Definition at line 3701 of file rtp.c.

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

Referenced by rtcp_do_debug().

03702 {
03703    struct hostent *hp;
03704    struct ast_hostent ahp;
03705    int port = 0;
03706    char *p, *arg;
03707    if (argc != 4)
03708       return RESULT_SHOWUSAGE;
03709 
03710    arg = argv[3];
03711    p = strstr(arg, ":");
03712    if (p) {
03713       *p = '\0';
03714       p++;
03715       port = atoi(p);
03716    }
03717    hp = ast_gethostbyname(arg, &ahp);
03718    if (hp == NULL)
03719       return RESULT_SHOWUSAGE;
03720    rtcpdebugaddr.sin_family = AF_INET;
03721    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03722    rtcpdebugaddr.sin_port = htons(port);
03723    if (port == 0)
03724       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03725    else
03726       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03727    rtcpdebug = 1;
03728    return RESULT_SUCCESS;
03729 }

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

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

03672 {
03673    struct hostent *hp;
03674    struct ast_hostent ahp;
03675    int port = 0;
03676    char *p, *arg;
03677    if (argc != 5)
03678       return RESULT_SHOWUSAGE;
03679 
03680    arg = argv[4];
03681    p = strstr(arg, ":");
03682    if (p) {
03683       *p = '\0';
03684       p++;
03685       port = atoi(p);
03686    }
03687    hp = ast_gethostbyname(arg, &ahp);
03688    if (hp == NULL)
03689       return RESULT_SHOWUSAGE;
03690    rtcpdebugaddr.sin_family = AF_INET;
03691    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03692    rtcpdebugaddr.sin_port = htons(port);
03693    if (port == 0)
03694       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03695    else
03696       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03697    rtcpdebug = 1;
03698    return RESULT_SUCCESS;
03699 }

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

Definition at line 3777 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03777                                                          {
03778    if (argc != 2) {
03779       return RESULT_SHOWUSAGE;
03780    }
03781    rtcpstats = 1;
03782    ast_cli(fd, "RTCP Stats Enabled\n");
03783    return RESULT_SUCCESS;
03784 }

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

Definition at line 3768 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03768                                                                     {
03769    if (argc != 3) {
03770       return RESULT_SHOWUSAGE;
03771    }
03772    rtcpstats = 1;
03773    ast_cli(fd, "RTCP Stats Enabled\n");
03774    return RESULT_SUCCESS;
03775 }

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

Definition at line 3804 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03805 {
03806    if (argc != 3)
03807       return RESULT_SHOWUSAGE;
03808    rtcpdebug = 0;
03809    ast_cli(fd,"RTCP Debugging Disabled\n");
03810    return RESULT_SUCCESS;
03811 }

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

Definition at line 3795 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03796 {
03797    if (argc != 4)
03798       return RESULT_SHOWUSAGE;
03799    rtcpdebug = 0;
03800    ast_cli(fd,"RTCP Debugging Disabled\n");
03801    return RESULT_SUCCESS;
03802 }

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

Definition at line 3822 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03823 {
03824    if (argc != 3)
03825       return RESULT_SHOWUSAGE;
03826    rtcpstats = 0;
03827    ast_cli(fd,"RTCP Stats Disabled\n");
03828    return RESULT_SUCCESS;
03829 }

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

Definition at line 3813 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03814 {
03815    if (argc != 4)
03816       return RESULT_SHOWUSAGE;
03817    rtcpstats = 0;
03818    ast_cli(fd,"RTCP Stats Disabled\n");
03819    return RESULT_SUCCESS;
03820 }

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

Definition at line 653 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_with_duration(), and bridge_p2p_rtp_write().

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

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

Definition at line 3731 of file rtp.c.

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

03732 {
03733    if (argc != 2) {
03734       if (argc != 4)
03735          return RESULT_SHOWUSAGE;
03736       return rtp_do_debug_ip(fd, argc, argv);
03737    }
03738    rtpdebug = 1;
03739    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03740    ast_cli(fd, "RTP Debugging Enabled\n");
03741    return RESULT_SUCCESS;
03742 }

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

Definition at line 3641 of file rtp.c.

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

Referenced by rtp_do_debug().

03642 {
03643    struct hostent *hp;
03644    struct ast_hostent ahp;
03645    int port = 0;
03646    char *p, *arg;
03647 
03648    if (argc != 4)
03649       return RESULT_SHOWUSAGE;
03650    arg = argv[3];
03651    p = strstr(arg, ":");
03652    if (p) {
03653       *p = '\0';
03654       p++;
03655       port = atoi(p);
03656    }
03657    hp = ast_gethostbyname(arg, &ahp);
03658    if (hp == NULL)
03659       return RESULT_SHOWUSAGE;
03660    rtpdebugaddr.sin_family = AF_INET;
03661    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
03662    rtpdebugaddr.sin_port = htons(port);
03663    if (port == 0)
03664       ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
03665    else
03666       ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
03667    rtpdebug = 1;
03668    return RESULT_SUCCESS;
03669 }

static int rtp_get_rate ( int  subclass  )  [static]

Definition at line 530 of file rtp.c.

References AST_FORMAT_G722, and ast_format_rate().

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

00531 {
00532    return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
00533 }

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

Definition at line 3786 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03787 {
03788    if (argc != 3)
03789       return RESULT_SHOWUSAGE;
03790    rtpdebug = 0;
03791    ast_cli(fd,"RTP Debugging Disabled\n");
03792    return RESULT_SUCCESS;
03793 }

static int rtp_socket ( void   )  [static]

Definition at line 1958 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01959 {
01960    int s;
01961    long flags;
01962    s = socket(AF_INET, SOCK_DGRAM, 0);
01963    if (s > -1) {
01964       flags = fcntl(s, F_GETFL);
01965       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01966 #ifdef SO_NO_CHECK
01967       if (nochecksums)
01968          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01969 #endif
01970    }
01971    return s;
01972 }

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

Definition at line 875 of file rtp.c.

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

Referenced by p2p_callback_disable().

00876 {
00877    struct ast_rtp *rtp = cbdata;
00878    struct ast_frame *f;
00879    f = ast_rtp_read(rtp);
00880    if (f) {
00881       if (rtp->callback)
00882          rtp->callback(rtp, f, rtp->data);
00883    }
00884    return 1;
00885 }

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

Definition at line 1073 of file rtp.c.

Referenced by calc_rxstamp().

01074 {
01075    while (tv->tv_usec < 0) {
01076       tv->tv_usec += 1000000;
01077       tv->tv_sec -= 1;
01078    }
01079    while (tv->tv_usec >= 1000000) {
01080       tv->tv_usec -= 1000000;
01081       tv->tv_sec += 1;
01082    }
01083 }

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

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

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

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

Definition at line 3831 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03832 {
03833    if (argc != 2) {
03834       return RESULT_SHOWUSAGE;
03835    }
03836    stundebug = 1;
03837    ast_cli(fd, "STUN Debugging Enabled\n");
03838    return RESULT_SUCCESS;
03839 }

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

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

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

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

Definition at line 286 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3841 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03842 {
03843    if (argc != 3)
03844       return RESULT_SHOWUSAGE;
03845    stundebug = 0;
03846    ast_cli(fd, "STUN Debugging Disabled\n");
03847    return RESULT_SUCCESS;
03848 }

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

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

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

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 396 of file rtp.c.

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

Referenced by ast_rtp_stun_request().

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

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

Definition at line 390 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Definition at line 508 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3917 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 3882 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 3892 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 3887 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 3897 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 3907 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 3902 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 3912 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 3850 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 3854 of file rtp.c.

struct rtpPayloadType payloadType

Definition at line 1454 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 3866 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 3870 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 3878 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

Definition at line 3874 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 1489 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 3858 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3862 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1456 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1455 of file rtp.c.

Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), ast_call_forward(), ast_format_str_reduce(), 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 Sat Aug 6 00:40:04 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7