Thu Oct 8 00:59:50 2009

Asterisk developer's documentation


rtp.c File Reference

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

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"

Go to the source code of this file.

Data Structures

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

Defines

#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))
#define FLAG_3389_WARNING   (1 << 0)
#define FLAG_CALLBACK_MODE   (1 << 6)
#define FLAG_DTMF_COMPENSATE   (1 << 7)
#define FLAG_HAS_DTMF   (1 << 3)
#define FLAG_HAS_STUN   (1 << 8)
#define FLAG_NAT_ACTIVE   (3 << 1)
#define FLAG_NAT_INACTIVE   (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
#define FLAG_P2P_NEED_DTMF   (1 << 5)
#define FLAG_P2P_SENT_MARK   (1 << 4)
#define MAX_TIMESTAMP_SKEW   640
#define RTCP_DEFAULT_INTERVALMS   5000
#define RTCP_MAX_INTERVALMS   60000
#define RTCP_MIN_INTERVALMS   500
#define RTCP_PT_APP   204
#define RTCP_PT_BYE   203
#define RTCP_PT_FUR   192
#define RTCP_PT_RR   201
#define RTCP_PT_SDES   202
#define RTCP_PT_SR   200
#define RTP_MTU   1200
#define RTP_SEQ_MOD   (1<<16)
#define STUN_ACCEPT   (1)
#define STUN_BINDERR   0x0111
#define STUN_BINDREQ   0x0001
#define STUN_BINDRESP   0x0101
#define STUN_CHANGE_REQUEST   0x0003
#define STUN_CHANGED_ADDRESS   0x0005
#define STUN_ERROR_CODE   0x0009
#define STUN_IGNORE   (0)
#define STUN_MAPPED_ADDRESS   0x0001
#define STUN_MESSAGE_INTEGRITY   0x0008
#define STUN_PASSWORD   0x0007
#define STUN_REFLECTED_FROM   0x000b
#define STUN_RESPONSE_ADDRESS   0x0002
#define STUN_SECERR   0x0112
#define STUN_SECREQ   0x0002
#define STUN_SECRESP   0x0102
#define STUN_SOURCE_ADDRESS   0x0004
#define STUN_UNKNOWN_ATTRIBUTES   0x000a
#define STUN_USERNAME   0x0006

Functions

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

Variables

static struct ast_cli_entry cli_rtp []
static struct ast_cli_entry cli_rtp_no_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated
static struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated
static struct ast_cli_entry cli_rtp_rtcp_stats_deprecated
static struct ast_cli_entry cli_stun_no_debug_deprecated
static char debug_usage []
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
struct {
   rtpPayloadType   payloadType
   char *   subtype
   char *   type
mimeTypes []
static char no_debug_usage []
static char rtcp_debug_usage []
static char rtcp_no_debug_usage []
static char rtcp_no_stats_usage []
static char rtcp_stats_usage []
static int rtcpdebug
static struct sockaddr_in rtcpdebugaddr
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static int rtcpstats
static int rtpdebug
static struct sockaddr_in rtpdebugaddr
static int rtpend
static int rtpstart
static struct rtpPayloadType static_RTP_PT [MAX_RTP_PT]
static char stun_debug_usage []
static char stun_no_debug_usage []
static int stundebug


Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))

samples

Definition at line 76 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 188 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 195 of file rtp.c.

Referenced by p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 196 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

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

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

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

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 264 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 265 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 273 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 279 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 261 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 281 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 269 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 267 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 268 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 280 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

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

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Definition at line 356 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 532 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

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

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

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 869 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_rtcp::altthem, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, f, ast_rtp::f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().

Referenced by oh323_read(), sip_rtp_read(), and skinny_rtp_read().

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

int ast_rtcp_send_h261fur ( void *  data  ) 

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

Definition at line 2426 of file rtp.c.

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

02427 {
02428    struct ast_rtp *rtp = data;
02429    int res;
02430 
02431    rtp->rtcp->sendfur = 1;
02432    res = ast_rtcp_write(data);
02433    
02434    return res;
02435 }

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

02644 {
02645    struct ast_rtp *rtp = (struct ast_rtp *)data;
02646    int res;
02647    
02648    if (!rtp || !rtp->rtcp)
02649       return 0;
02650 
02651    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02652       res = ast_rtcp_write_sr(data);
02653    else
02654       res = ast_rtcp_write_rr(data);
02655    
02656    return res;
02657 }

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

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

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

Send RTCP sender's report.

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

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

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

Referenced by process_sdp().

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

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

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

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2854 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

02855 {
02856    if (pt < 0 || pt > MAX_RTP_PT)
02857       return 0; /* bogus payload type */
02858 
02859    if (static_RTP_PT[pt].isAstFormat)
02860       return static_RTP_PT[pt].code;
02861    else
02862       return 0;
02863 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2849 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02850 {
02851    return &rtp->pref;
02852 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2802 of file rtp.c.

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

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

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

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

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

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

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

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00516 {
00517    return rtp->s;
00518 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

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

02120 {
02121    struct ast_rtp *bridged = NULL;
02122 
02123    ast_mutex_lock(&rtp->bridge_lock);
02124    bridged = rtp->bridged;
02125    ast_mutex_unlock(&rtp->bridge_lock);
02126 
02127    return bridged;
02128 }

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

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

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

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

02102 {
02103    if ((them->sin_family != AF_INET) ||
02104       (them->sin_port != rtp->them.sin_port) ||
02105       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02106       them->sin_family = AF_INET;
02107       them->sin_port = rtp->them.sin_port;
02108       them->sin_addr = rtp->them.sin_addr;
02109       return 1;
02110    }
02111    return 0;
02112 }

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

Return RTCP quality string.

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

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

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 575 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 583 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00584 {
00585    return rtp->rtpkeepalive;
00586 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 567 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

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

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

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

02115 {
02116    *us = rtp->us;
02117 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 603 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3940 of file rtp.c.

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

Referenced by main().

03941 {
03942    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03943    ast_rtp_reload();
03944 }

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

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

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

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

Referenced by process_sdp().

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

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

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

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

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

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

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

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

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

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02056 {
02057    struct in_addr ia;
02058 
02059    memset(&ia, 0, sizeof(ia));
02060    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02061 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

01950 {
01951    ast_mutex_init(&rtp->bridge_lock);
01952 
01953    rtp->them.sin_family = AF_INET;
01954    rtp->us.sin_family = AF_INET;
01955    rtp->ssrc = ast_random();
01956    rtp->seqno = ast_random() & 0xffff;
01957    ast_set_flag(rtp, FLAG_HAS_DTMF);
01958 
01959    return;
01960 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2072 of file rtp.c.

References ast_rtp::set_marker_bit.

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

02073 {
02074    if (rtp) {
02075       rtp->set_marker_bit = 1;
02076    }
02077    return;
02078 }

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

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

02957 {
02958    struct ast_rtp_protocol *cur;
02959 
02960    AST_LIST_LOCK(&protos);
02961    AST_LIST_TRAVERSE(&protos, cur, list) {   
02962       if (!strcmp(cur->type, proto->type)) {
02963          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02964          AST_LIST_UNLOCK(&protos);
02965          return -1;
02966       }
02967    }
02968    AST_LIST_INSERT_HEAD(&protos, proto, list);
02969    AST_LIST_UNLOCK(&protos);
02970    
02971    return 0;
02972 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2948 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by load_module(), and unload_module().

02949 {
02950    AST_LIST_LOCK(&protos);
02951    AST_LIST_REMOVE(&protos, proto, list);
02952    AST_LIST_UNLOCK(&protos);
02953 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

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

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

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

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

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

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

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

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

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1155 of file rtp.c.

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

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

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

int ast_rtp_reload ( void   ) 

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

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

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

02147 {
02148    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02149    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02150    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02151    rtp->lastts = 0;
02152    rtp->lastdigitts = 0;
02153    rtp->lastrxts = 0;
02154    rtp->lastividtimestamp = 0;
02155    rtp->lastovidtimestamp = 0;
02156    rtp->lasteventseqn = 0;
02157    rtp->lastevent = 0;
02158    rtp->lasttxformat = 0;
02159    rtp->lastrxformat = 0;
02160    rtp->dtmf_timeout = 0;
02161    rtp->seqno = 0;
02162    rtp->rxseqno = 0;
02163 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2370 of file rtp.c.

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

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

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

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

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

Referenced by handle_request_invite().

02092 {
02093    rtp->altthem.sin_port = alt->sin_port;
02094    rtp->altthem.sin_addr = alt->sin_addr;
02095    if (rtp->rtcp) {
02096       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02097       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02098    }
02099 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 593 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 588 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

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

01704 {
01705    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01706       return; /* bogus payload type */
01707 
01708    ast_mutex_lock(&rtp->bridge_lock);
01709    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01710    ast_mutex_unlock(&rtp->bridge_lock);
01711 } 

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

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

02081 {
02082    rtp->them.sin_port = them->sin_port;
02083    rtp->them.sin_addr = them->sin_addr;
02084    if (rtp->rtcp) {
02085       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02086       rtp->rtcp->them.sin_addr = them->sin_addr;
02087    }
02088    rtp->rxseqno = 0;
02089 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 555 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

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

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 561 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

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

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

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

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

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

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 549 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 542 of file rtp.c.

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

Referenced by handle_response_invite().

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

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

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

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

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

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 598 of file rtp.c.

References ast_rtp::nat.

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

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

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 618 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 2063 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

02064 {
02065    int res;
02066 
02067    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
02068       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
02069    return res;
02070 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

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

02131 {
02132    if (rtp->rtcp) {
02133       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02134    }
02135 
02136    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02137    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02138    if (rtp->rtcp) {
02139       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02140       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02141    }
02142    
02143    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02144 }

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

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

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

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

01716 {
01717    if (pt < 0 || pt > MAX_RTP_PT)
01718       return; /* bogus payload type */
01719 
01720    ast_mutex_lock(&rtp->bridge_lock);
01721    rtp->current_RTP_PT[pt].isAstFormat = 0;
01722    rtp->current_RTP_PT[pt].code = 0;
01723    ast_mutex_unlock(&rtp->bridge_lock);
01724 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

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

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

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

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

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

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

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

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

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

Definition at line 1051 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, ast_rtp::seedrxts, and ast_frame::subclass.

Referenced by ast_rtp_read(), and schedule_delivery().

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

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

Definition at line 2248 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

02249 {
02250    struct timeval t;
02251    long ms;
02252    if (ast_tvzero(rtp->txcore)) {
02253       rtp->txcore = ast_tvnow();
02254       /* Round to 20ms for nice, pretty timestamps */
02255       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02256    }
02257    /* Use previous txcore if available */
02258    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02259    ms = ast_tvdiff_ms(t, rtp->txcore);
02260    if (ms < 0)
02261       ms = 0;
02262    /* Use what we just got for next time */
02263    rtp->txcore = t;
02264    return (unsigned int) ms;
02265 }

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

Get channel driver interface structure.

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

01528 {
01529    struct ast_rtp_protocol *cur = NULL;
01530 
01531    AST_LIST_LOCK(&protos);
01532    AST_LIST_TRAVERSE(&protos, cur, list) {
01533       if (cur->type == chan->tech->type)
01534          break;
01535    }
01536    AST_LIST_UNLOCK(&protos);
01537 
01538    return cur;
01539 }

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

03234 {
03235    ast_channel_lock(chan);
03236 
03237    /* Remove the callback from the IO context */
03238    ast_io_remove(rtp->io, iod[0]);
03239 
03240    /* Restore file descriptors */
03241    chan->fds[0] = fds[0];
03242    ast_channel_unlock(chan);
03243 
03244    /* Restore callback mode if previously used */
03245    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03246       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03247 
03248    return 0;
03249 }

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

P2P RTP Callback.

Definition at line 3226 of file rtp.c.

Referenced by bridge_p2p_loop().

03227 {
03228    return 0;
03229 }

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

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

Referenced by bridge_p2p_loop().

03253 {
03254    ast_mutex_lock(&rtp0->bridge_lock);
03255    rtp0->bridged = rtp1;
03256    ast_mutex_unlock(&rtp0->bridge_lock);
03257 
03258    return;
03259 }

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

Definition at line 676 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Process RTP DTMF and events according to RFC 2833.

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

Parameters:
rtp 
data 
len 
seqno 
Returns:

Definition at line 715 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

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

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

Definition at line 662 of file rtp.c.

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

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

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

Definition at line 3672 of file rtp.c.

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

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

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

Definition at line 3660 of file rtp.c.

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

03660                                                                     {
03661    if (argc != 3) {
03662       if (argc != 5)
03663          return RESULT_SHOWUSAGE;
03664       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03665    }
03666    rtcpdebug = 1;
03667    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03668    ast_cli(fd, "RTCP Debugging Enabled\n");
03669    return RESULT_SUCCESS;
03670 }

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

Definition at line 3617 of file rtp.c.

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

Referenced by rtcp_do_debug().

03618 {
03619    struct hostent *hp;
03620    struct ast_hostent ahp;
03621    int port = 0;
03622    char *p, *arg;
03623    if (argc != 4)
03624       return RESULT_SHOWUSAGE;
03625 
03626    arg = argv[3];
03627    p = strstr(arg, ":");
03628    if (p) {
03629       *p = '\0';
03630       p++;
03631       port = atoi(p);
03632    }
03633    hp = ast_gethostbyname(arg, &ahp);
03634    if (hp == NULL)
03635       return RESULT_SHOWUSAGE;
03636    rtcpdebugaddr.sin_family = AF_INET;
03637    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03638    rtcpdebugaddr.sin_port = htons(port);
03639    if (port == 0)
03640       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03641    else
03642       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03643    rtcpdebug = 1;
03644    return RESULT_SUCCESS;
03645 }

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

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

03588 {
03589    struct hostent *hp;
03590    struct ast_hostent ahp;
03591    int port = 0;
03592    char *p, *arg;
03593    if (argc != 5)
03594       return RESULT_SHOWUSAGE;
03595 
03596    arg = argv[4];
03597    p = strstr(arg, ":");
03598    if (p) {
03599       *p = '\0';
03600       p++;
03601       port = atoi(p);
03602    }
03603    hp = ast_gethostbyname(arg, &ahp);
03604    if (hp == NULL)
03605       return RESULT_SHOWUSAGE;
03606    rtcpdebugaddr.sin_family = AF_INET;
03607    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03608    rtcpdebugaddr.sin_port = htons(port);
03609    if (port == 0)
03610       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03611    else
03612       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03613    rtcpdebug = 1;
03614    return RESULT_SUCCESS;
03615 }

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

Definition at line 3693 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 3684 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 3720 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03721 {
03722    if (argc != 3)
03723       return RESULT_SHOWUSAGE;
03724    rtcpdebug = 0;
03725    ast_cli(fd,"RTCP Debugging Disabled\n");
03726    return RESULT_SUCCESS;
03727 }

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

Definition at line 3711 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03712 {
03713    if (argc != 4)
03714       return RESULT_SHOWUSAGE;
03715    rtcpdebug = 0;
03716    ast_cli(fd,"RTCP Debugging Disabled\n");
03717    return RESULT_SUCCESS;
03718 }

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

Definition at line 3738 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03739 {
03740    if (argc != 3)
03741       return RESULT_SHOWUSAGE;
03742    rtcpstats = 0;
03743    ast_cli(fd,"RTCP Stats Disabled\n");
03744    return RESULT_SUCCESS;
03745 }

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

Definition at line 3729 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03730 {
03731    if (argc != 4)
03732       return RESULT_SHOWUSAGE;
03733    rtcpstats = 0;
03734    ast_cli(fd,"RTCP Stats Disabled\n");
03735    return RESULT_SUCCESS;
03736 }

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

Definition at line 649 of file rtp.c.

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

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

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

Definition at line 3647 of file rtp.c.

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

03648 {
03649    if (argc != 2) {
03650       if (argc != 4)
03651          return RESULT_SHOWUSAGE;
03652       return rtp_do_debug_ip(fd, argc, argv);
03653    }
03654    rtpdebug = 1;
03655    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03656    ast_cli(fd, "RTP Debugging Enabled\n");
03657    return RESULT_SUCCESS;
03658 }

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

Definition at line 3557 of file rtp.c.

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

Referenced by rtp_do_debug().

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

static int rtp_get_rate ( int  subclass  )  [static]

Definition at line 527 of file rtp.c.

References AST_FORMAT_G722, and ast_format_rate().

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

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

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

Definition at line 3702 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

static int rtp_socket ( void   )  [static]

Definition at line 1902 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

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

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

Definition at line 857 of file rtp.c.

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

Referenced by p2p_callback_disable().

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

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

Definition at line 623 of file rtp.c.

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

Referenced by ast_rtp_read(), process_cisco_dtmf(), and process_rfc2833().

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

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

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

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

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

Definition at line 3747 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03748 {
03749    if (argc != 2) {
03750       return RESULT_SHOWUSAGE;
03751    }
03752    stundebug = 1;
03753    ast_cli(fd, "STUN Debugging Enabled\n");
03754    return RESULT_SUCCESS;
03755 }

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

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

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

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

Definition at line 283 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3757 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03758 {
03759    if (argc != 3)
03760       return RESULT_SHOWUSAGE;
03761    stundebug = 0;
03762    ast_cli(fd, "STUN Debugging Disabled\n");
03763    return RESULT_SUCCESS;
03764 }

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

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

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

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 393 of file rtp.c.

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

Referenced by ast_rtp_stun_request().

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

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

Definition at line 387 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Definition at line 505 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3833 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 3798 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 3808 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 3803 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 3813 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 3823 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 3818 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 3828 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 3766 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 3770 of file rtp.c.

struct rtpPayloadType payloadType

Definition at line 1398 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 3782 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 3786 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 3794 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

Definition at line 3790 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 1433 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 3774 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3778 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1400 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1399 of file rtp.c.

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


Generated on Thu Oct 8 00:59:50 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7