Mon May 14 04:50:58 2007

Asterisk developer's documentation


rtp.c File Reference

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

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

Include dependency graph for rtp.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

static void append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
static void append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
static AST_LIST_HEAD_STATIC (protos, ast_rtp_protocol)
 List of current sessions.
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
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 (void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (void *data)
 Send RTCP recipient's report.
static int ast_rtcp_write_sr (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.
ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
 Initializate a RTP session using an in_addr structure.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register interface to channel driver.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister interface to channel driver.
void ast_rtp_pt_clear (struct ast_rtp *rtp)
 Setting RTP payload types from lines in a SDP description:.
void ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src)
 Copy payload types between RTP structures.
void ast_rtp_pt_default (struct ast_rtp *rtp)
 Set payload types to defaults.
static int ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec)
ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
static int ast_rtp_senddigit_continuation (struct ast_rtp *rtp)
 Send continuation frame for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
void ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
static enum ast_bridge_result bridge_native_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for true native bridge (reinvite).
static enum ast_bridge_result bridge_p2p_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for partial native bridge (packet2packet).
static int bridge_p2p_rtp_write (struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen)
 Perform a Packet2Packet RTP write.
static void calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
static struct ast_rtp_protocolget_proto (struct ast_channel *chan)
 Get channel driver interface structure.
static int p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
 Helper function to switch a channel and RTP stream out of callback mode.
static int p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
 P2P RTP Callback.
static void p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1)
 Helper function that sets what an RTP structure is bridged to.
static struct ast_frameprocess_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len)
static struct ast_frameprocess_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp)
 Process RTP DTMF and events according to RFC 2833.
static struct ast_frameprocess_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len)
 Process Comfort Noise RTP.
static int rtcp_debug_test_addr (struct sockaddr_in *addr)
static int rtcp_do_debug (int fd, int argc, char *argv[])
static int rtcp_do_debug_deprecated (int fd, int argc, char *argv[])
static int rtcp_do_debug_ip (int fd, int argc, char *argv[])
static int rtcp_do_debug_ip_deprecated (int fd, int argc, char *argv[])
static int rtcp_do_stats (int fd, int argc, char *argv[])
static int rtcp_do_stats_deprecated (int fd, int argc, char *argv[])
static int rtcp_no_debug (int fd, int argc, char *argv[])
static int rtcp_no_debug_deprecated (int fd, int argc, char *argv[])
static int rtcp_no_stats (int fd, int argc, char *argv[])
static int rtcp_no_stats_deprecated (int fd, int argc, char *argv[])
static int rtp_debug_test_addr (struct sockaddr_in *addr)
static int rtp_do_debug (int fd, int argc, char *argv[])
static int rtp_do_debug_ip (int fd, int argc, char *argv[])
static int rtp_no_debug (int fd, int argc, char *argv[])
static int rtp_socket (void)
static int rtpread (int *id, int fd, short events, void *cbdata)
static struct ast_framesend_dtmf (struct ast_rtp *rtp, enum ast_frame_type type)
static const char * stun_attr2str (int msg)
static int stun_do_debug (int fd, int argc, char *argv[])
static int stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len)
static const char * stun_msg2str (int msg)
static int stun_no_debug (int fd, int argc, char *argv[])
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
static void stun_req_id (struct stun_header *req)
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)

Variables

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


Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

#define DEFAULT_DTMF_TIMEOUT   3000

samples

Definition at line 76 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 186 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 193 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 194 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

Definition at line 190 of file rtp.c.

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

#define FLAG_HAS_STUN   (1 << 8)

Definition at line 195 of file rtp.c.

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 187 of file rtp.c.

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

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 188 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 189 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_P2P_NEED_DTMF   (1 << 5)

Definition at line 192 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 191 of file rtp.c.

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

#define MAX_TIMESTAMP_SKEW   640

Definition at line 60 of file rtp.c.

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

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 63 of file rtp.c.

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 65 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 64 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 72 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 71 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

Definition at line 67 of file rtp.c.

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

#define RTCP_PT_RR   201

Definition at line 69 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

Definition at line 70 of file rtp.c.

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

#define RTCP_PT_SR   200

Definition at line 68 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 74 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 62 of file rtp.c.

Referenced by ast_rtp_read().

#define STUN_ACCEPT   (1)

Definition at line 259 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 263 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 261 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 262 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 258 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 268 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 269 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 264 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 273 of file rtp.c.

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


Function Documentation

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

Definition at line 366 of file rtp.c.

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Definition at line 353 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

static AST_LIST_HEAD_STATIC ( protos  ,
ast_rtp_protocol   
) [static]

List of current sessions.

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 524 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 517 of file rtp.c.

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

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1826 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

01827 {
01828    struct ast_rtcp *rtcp;
01829 
01830    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01831       return NULL;
01832    rtcp->s = rtp_socket();
01833    rtcp->us.sin_family = AF_INET;
01834    rtcp->them.sin_family = AF_INET;
01835 
01836    if (rtcp->s < 0) {
01837       free(rtcp);
01838       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01839       return NULL;
01840    }
01841 
01842    return rtcp;
01843 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 822 of file rtp.c.

References ast_rtcp::accumulated_transit, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), CRASH, ast_frame::datalen, 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_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().

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

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

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

02292 {
02293    struct ast_rtp *rtp = data;
02294    int res;
02295 
02296    rtp->rtcp->sendfur = 1;
02297    res = ast_rtcp_write(data);
02298    
02299    return res;
02300 }

static int ast_rtcp_write ( 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 2516 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().

02517 {
02518    struct ast_rtp *rtp = data;
02519    int res;
02520    
02521    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02522       res = ast_rtcp_write_sr(data);
02523    else
02524       res = ast_rtcp_write_rr(data);
02525    
02526    return res;
02527 }

static int ast_rtcp_write_rr ( void *  data  )  [static]

Send RTCP recipient'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 2417 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, 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().

02418 {
02419    struct ast_rtp *rtp = data;
02420    int res;
02421    int len = 32;
02422    unsigned int lost;
02423    unsigned int extended;
02424    unsigned int expected;
02425    unsigned int expected_interval;
02426    unsigned int received_interval;
02427    int lost_interval;
02428    struct timeval now;
02429    unsigned int *rtcpheader;
02430    char bdata[1024];
02431    struct timeval dlsr;
02432    int fraction;
02433 
02434    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
02435       return 0;
02436      
02437    if (!rtp->rtcp->them.sin_addr.s_addr) {
02438       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
02439       if (rtp->rtcp->schedid > 0)
02440          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02441       rtp->rtcp->schedid = -1;
02442       return 0;
02443    }
02444 
02445    extended = rtp->cycles + rtp->lastrxseqno;
02446    expected = extended - rtp->seedrxseqno + 1;
02447    lost = expected - rtp->rxcount;
02448    expected_interval = expected - rtp->rtcp->expected_prior;
02449    rtp->rtcp->expected_prior = expected;
02450    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02451    rtp->rtcp->received_prior = rtp->rxcount;
02452    lost_interval = expected_interval - received_interval;
02453    if (expected_interval == 0 || lost_interval <= 0)
02454       fraction = 0;
02455    else
02456       fraction = (lost_interval << 8) / expected_interval;
02457    gettimeofday(&now, NULL);
02458    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02459    rtcpheader = (unsigned int *)bdata;
02460    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
02461    rtcpheader[1] = htonl(rtp->ssrc);
02462    rtcpheader[2] = htonl(rtp->themssrc);
02463    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02464    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02465    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02466    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
02467    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02468 
02469    if (rtp->rtcp->sendfur) {
02470       rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
02471       rtcpheader[9] = htonl(rtp->ssrc);               /* Our SSRC */
02472       len += 8;
02473       rtp->rtcp->sendfur = 0;
02474    }
02475 
02476    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
02477    it can change mid call, and SDES can't) */
02478    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02479    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02480    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
02481    len += 12;
02482    
02483    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02484 
02485    if (res < 0) {
02486       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
02487       /* Remove the scheduler */
02488       if (rtp->rtcp->schedid > 0)
02489          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02490       rtp->rtcp->schedid = -1;
02491       return 0;
02492    }
02493 
02494    rtp->rtcp->rr_count++;
02495 
02496    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02497       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
02498          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 
02499          "  IA jitter: %.4f\n" 
02500          "  Their last SR: %u\n" 
02501          "  DLSR: %4.4f (sec)\n\n",
02502          ast_inet_ntoa(rtp->rtcp->them.sin_addr),
02503          ntohs(rtp->rtcp->them.sin_port),
02504          rtp->ssrc, rtp->themssrc, fraction, lost,
02505          rtp->rxjitter,
02506          rtp->rtcp->themrxlsr,
02507          (double)(ntohl(rtcpheader[7])/65536.0));
02508    }
02509 
02510    return res;
02511 }

static int ast_rtcp_write_sr ( void *  data  )  [static]

Send RTCP sender's report.

Definition at line 2303 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, 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().

02304 {
02305    struct ast_rtp *rtp = data;
02306    int res;
02307    int len = 0;
02308    struct timeval now;
02309    unsigned int now_lsw;
02310    unsigned int now_msw;
02311    unsigned int *rtcpheader;
02312    unsigned int lost;
02313    unsigned int extended;
02314    unsigned int expected;
02315    unsigned int expected_interval;
02316    unsigned int received_interval;
02317    int lost_interval;
02318    int fraction;
02319    struct timeval dlsr;
02320    char bdata[512];
02321 
02322    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
02323    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
02324       return 0;
02325    
02326    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
02327       ast_verbose("RTCP SR transmission error, rtcp halted\n");
02328       if (rtp->rtcp->schedid > 0)
02329          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02330       rtp->rtcp->schedid = -1;
02331       return 0;
02332    }
02333 
02334    gettimeofday(&now, NULL);
02335    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
02336    rtcpheader = (unsigned int *)bdata;
02337    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
02338    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
02339    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
02340    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
02341    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
02342    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
02343    len += 28;
02344    
02345    extended = rtp->cycles + rtp->lastrxseqno;
02346    expected = extended - rtp->seedrxseqno + 1;
02347    if (rtp->rxcount > expected) 
02348       expected += rtp->rxcount - expected;
02349    lost = expected - rtp->rxcount;
02350    expected_interval = expected - rtp->rtcp->expected_prior;
02351    rtp->rtcp->expected_prior = expected;
02352    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02353    rtp->rtcp->received_prior = rtp->rxcount;
02354    lost_interval = expected_interval - received_interval;
02355    if (expected_interval == 0 || lost_interval <= 0)
02356       fraction = 0;
02357    else
02358       fraction = (lost_interval << 8) / expected_interval;
02359    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02360    rtcpheader[7] = htonl(rtp->themssrc);
02361    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02362    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02363    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02364    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
02365    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02366    len += 24;
02367    
02368    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
02369 
02370    if (rtp->rtcp->sendfur) {
02371       rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
02372       rtcpheader[14] = htonl(rtp->ssrc);               /* Our SSRC */
02373       len += 8;
02374       rtp->rtcp->sendfur = 0;
02375    }
02376    
02377    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 
02378    /* it can change mid call, and SDES can't) */
02379    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02380    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02381    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
02382    len += 12;
02383    
02384    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02385    if (res < 0) {
02386       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));
02387       if (rtp->rtcp->schedid > 0)
02388          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02389       rtp->rtcp->schedid = -1;
02390       return 0;
02391    }
02392    
02393    /* FIXME Don't need to get a new one */
02394    gettimeofday(&rtp->rtcp->txlsr, NULL);
02395    rtp->rtcp->sr_count++;
02396 
02397    rtp->rtcp->lastsrtxcount = rtp->txcount;  
02398    
02399    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02400       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
02401       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
02402       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
02403       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
02404       ast_verbose("  Sent packets: %u\n", rtp->txcount);
02405       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
02406       ast_verbose("  Report block:\n");
02407       ast_verbose("  Fraction lost: %u\n", fraction);
02408       ast_verbose("  Cumulative loss: %u\n", lost);
02409       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
02410       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
02411       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
02412    }
02413    return res;
02414 }

size_t ast_rtp_alloc_size ( void   ) 

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

Returns:
number of bytes required

Definition at line 397 of file rtp.c.

Referenced by process_sdp().

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

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

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

Definition at line 3185 of file rtp.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_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(), FLAG_DTMF_COMPENSATE, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, option_debug, option_verbose, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

03186 {
03187    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03188    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03189    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03190    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03191    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03192    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03193    int codec0 = 0, codec1 = 0;
03194    void *pvt0 = NULL, *pvt1 = NULL;
03195 
03196    /* Lock channels */
03197    ast_channel_lock(c0);
03198    while(ast_channel_trylock(c1)) {
03199       ast_channel_unlock(c0);
03200       usleep(1);
03201       ast_channel_lock(c0);
03202    }
03203 
03204    /* Find channel driver interfaces */
03205    if (!(pr0 = get_proto(c0))) {
03206       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03207       ast_channel_unlock(c0);
03208       ast_channel_unlock(c1);
03209       return AST_BRIDGE_FAILED;
03210    }
03211    if (!(pr1 = get_proto(c1))) {
03212       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03213       ast_channel_unlock(c0);
03214       ast_channel_unlock(c1);
03215       return AST_BRIDGE_FAILED;
03216    }
03217 
03218    /* Get channel specific interface structures */
03219    pvt0 = c0->tech_pvt;
03220    pvt1 = c1->tech_pvt;
03221 
03222    /* Get audio and video interface (if native bridge is possible) */
03223    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03224    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03225    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03226    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03227 
03228    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03229    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03230       audio_p0_res = AST_RTP_GET_FAILED;
03231    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03232       audio_p1_res = AST_RTP_GET_FAILED;
03233 
03234    /* Check if a bridge is possible (partial/native) */
03235    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03236       /* Somebody doesn't want to play... */
03237       ast_channel_unlock(c0);
03238       ast_channel_unlock(c1);
03239       return AST_BRIDGE_FAILED_NOWARN;
03240    }
03241 
03242    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03243    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03244       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03245       audio_p0_res = AST_RTP_TRY_PARTIAL;
03246    }
03247 
03248    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03249       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03250       audio_p1_res = AST_RTP_TRY_PARTIAL;
03251    }
03252 
03253    /* If both sides are not using the same method of DTMF transmission 
03254     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03255     * --------------------------------------------------
03256     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03257     * |-----------|------------|-----------------------|
03258     * | Inband    | False      | True                  |
03259     * | RFC2833   | True       | True                  |
03260     * | SIP INFO  | False      | False                 |
03261     * --------------------------------------------------
03262     * However, if DTMF from both channels is being monitored by the core, then
03263     * we can still do packet-to-packet bridging, because passing through the 
03264     * core will handle DTMF mode translation.
03265     */
03266    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03267        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03268       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03269          ast_channel_unlock(c0);
03270          ast_channel_unlock(c1);
03271          return AST_BRIDGE_FAILED_NOWARN;
03272       }
03273       audio_p0_res = AST_RTP_TRY_PARTIAL;
03274       audio_p1_res = AST_RTP_TRY_PARTIAL;
03275    }
03276 
03277    /* If the core will need to compensate and the P2P bridge will need to feed up DTMF frames then we can not reliably do so yet, so do not P2P bridge */
03278    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF) && ast_test_flag(p0, FLAG_DTMF_COMPENSATE)) ||
03279        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF) && ast_test_flag(p1, FLAG_DTMF_COMPENSATE))) {
03280       ast_channel_unlock(c0);
03281       ast_channel_unlock(c1);
03282       return AST_BRIDGE_FAILED_NOWARN;
03283    }
03284 
03285    /* Get codecs from both sides */
03286    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03287    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03288    if (codec0 && codec1 && !(codec0 & codec1)) {
03289       /* Hey, we can't do native bridging if both parties speak different codecs */
03290       if (option_debug)
03291          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03292       ast_channel_unlock(c0);
03293       ast_channel_unlock(c1);
03294       return AST_BRIDGE_FAILED_NOWARN;
03295    }
03296 
03297    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03298    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03299       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03300       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03301          if (option_debug)
03302             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03303          ast_channel_unlock(c0);
03304          ast_channel_unlock(c1);
03305          return AST_BRIDGE_FAILED_NOWARN;
03306       }
03307       if (option_verbose > 2)
03308          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03309       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03310    } else {
03311       if (option_verbose > 2) 
03312          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03313       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03314    }
03315 
03316    return res;
03317 }

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2671 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

02672 {
02673    if (pt < 0 || pt > MAX_RTP_PT)
02674       return 0; /* bogus payload type */
02675 
02676    if (static_RTP_PT[pt].isAstFormat)
02677       return static_RTP_PT[pt].code;
02678    else
02679       return 0;
02680 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2666 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02667 {
02668    return &rtp->pref;
02669 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2653 of file rtp.c.

References ast_smoother_free(), ast_codec_pref::framing, ast_codec_pref::order, 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(), start_rtp(), and transmit_response_with_sdp().

02654 {
02655    int x;
02656    for (x = 0; x < 32; x++) {  /* Ugly way */
02657       rtp->pref.order[x] = prefs->order[x];
02658       rtp->pref.framing[x] = prefs->framing[x];
02659    }
02660    if (rtp->smoother)
02661       ast_smoother_free(rtp->smoother);
02662    rtp->smoother = NULL;
02663    return 0;
02664 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 2073 of file rtp.c.

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

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

02074 {
02075    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02076       /*Print some info on the call here */
02077       ast_verbose("  RTP-stats\n");
02078       ast_verbose("* Our Receiver:\n");
02079       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02080       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02081       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02082       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02083       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02084       ast_verbose("  RR-count:    %u\n", rtp->rtcp->rr_count);
02085       ast_verbose("* Our Sender:\n");
02086       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02087       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02088       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->reported_lost);
02089       ast_verbose("  Jitter:      %u\n", rtp->rtcp->reported_jitter);
02090       ast_verbose("  SR-count:    %u\n", rtp->rtcp->sr_count);
02091       ast_verbose("  RTT:      %f\n", rtp->rtcp->rtt);
02092    }
02093 
02094    if (rtp->smoother)
02095       ast_smoother_free(rtp->smoother);
02096    if (rtp->ioid)
02097       ast_io_remove(rtp->io, rtp->ioid);
02098    if (rtp->s > -1)
02099       close(rtp->s);
02100    if (rtp->rtcp) {
02101       if (rtp->rtcp->schedid > 0)
02102          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02103       close(rtp->rtcp->s);
02104       free(rtp->rtcp);
02105       rtp->rtcp=NULL;
02106    }
02107 
02108    ast_mutex_destroy(&rtp->bridge_lock);
02109 
02110    free(rtp);
02111 }

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

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

Referenced by wait_for_answer().

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 512 of file rtp.c.

References ast_rtp::s.

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

00513 {
00514    return rtp->s;
00515 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

Definition at line 1995 of file rtp.c.

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

Referenced by ast_rtp_read(), and do_monitor().

01996 {
01997    struct ast_rtp *bridged = NULL;
01998 
01999    ast_mutex_lock(&rtp->bridge_lock);
02000    bridged = rtp->bridged;
02001    ast_mutex_unlock(&rtp->bridge_lock);
02002 
02003    return bridged;
02004 }

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 1665 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 process_sdp().

01667 {
01668    int pt;
01669    
01670    ast_mutex_lock(&rtp->bridge_lock);
01671    
01672    *astFormats = *nonAstFormats = 0;
01673    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01674       if (rtp->current_RTP_PT[pt].isAstFormat) {
01675          *astFormats |= rtp->current_RTP_PT[pt].code;
01676       } else {
01677          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01678       }
01679    }
01680    
01681    ast_mutex_unlock(&rtp->bridge_lock);
01682    
01683    return;
01684 }

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

Definition at line 1977 of file rtp.c.

References ast_rtp::them.

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

01978 {
01979    if ((them->sin_family != AF_INET) ||
01980       (them->sin_port != rtp->them.sin_port) ||
01981       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
01982       them->sin_family = AF_INET;
01983       them->sin_port = rtp->them.sin_port;
01984       them->sin_addr = rtp->them.sin_addr;
01985       return 1;
01986    }
01987    return 0;
01988 }

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

Return RTCP quality string.

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

02044 {
02045    /*
02046    *ssrc          our ssrc
02047    *themssrc      their ssrc
02048    *lp            lost packets
02049    *rxjitter      our calculated jitter(rx)
02050    *rxcount       no. received packets
02051    *txjitter      reported jitter of the other end
02052    *txcount       transmitted packets
02053    *rlp           remote lost packets
02054    *rtt           round trip time
02055    */
02056 
02057    if (qual) {
02058       qual->local_ssrc = rtp->ssrc;
02059       qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02060       qual->local_jitter = rtp->rxjitter;
02061       qual->local_count = rtp->rxcount;
02062       qual->remote_ssrc = rtp->themssrc;
02063       qual->remote_lostpackets = rtp->rtcp->reported_lost;
02064       qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02065       qual->remote_count = rtp->txcount;
02066       qual->rtt = rtp->rtcp->rtt;
02067    }
02068    snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt);
02069    
02070    return rtp->rtcp->quality;
02071 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 567 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 575 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00576 {
00577    return rtp->rtpkeepalive;
00578 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 559 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

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

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

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

01991 {
01992    *us = rtp->us;
01993 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 595 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3702 of file rtp.c.

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

Referenced by main().

03703 {
03704    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03705    ast_rtp_reload();
03706 }

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

01709 {
01710    int pt = 0;
01711 
01712    ast_mutex_lock(&rtp->bridge_lock);
01713 
01714    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
01715       code == rtp->rtp_lookup_code_cache_code) {
01716       /* Use our cached mapping, to avoid the overhead of the loop below */
01717       pt = rtp->rtp_lookup_code_cache_result;
01718       ast_mutex_unlock(&rtp->bridge_lock);
01719       return pt;
01720    }
01721 
01722    /* Check the dynamic list first */
01723    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01724       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
01725          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01726          rtp->rtp_lookup_code_cache_code = code;
01727          rtp->rtp_lookup_code_cache_result = pt;
01728          ast_mutex_unlock(&rtp->bridge_lock);
01729          return pt;
01730       }
01731    }
01732 
01733    /* Then the static list */
01734    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01735       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
01736          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01737          rtp->rtp_lookup_code_cache_code = code;
01738          rtp->rtp_lookup_code_cache_result = pt;
01739          ast_mutex_unlock(&rtp->bridge_lock);
01740          return pt;
01741       }
01742    }
01743 
01744    ast_mutex_unlock(&rtp->bridge_lock);
01745 
01746    return -1;
01747 }

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

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

Referenced by process_sdp().

01770 {
01771    int format;
01772    unsigned len;
01773    char *end = buf;
01774    char *start = buf;
01775 
01776    if (!buf || !size)
01777       return NULL;
01778 
01779    snprintf(end, size, "0x%x (", capability);
01780 
01781    len = strlen(end);
01782    end += len;
01783    size -= len;
01784    start = end;
01785 
01786    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01787       if (capability & format) {
01788          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01789 
01790          snprintf(end, size, "%s|", name);
01791          len = strlen(end);
01792          end += len;
01793          size -= len;
01794       }
01795    }
01796 
01797    if (start == end)
01798       snprintf(start, size, "nothing)"); 
01799    else if (size > 1)
01800       *(end -1) = ')';
01801    
01802    return buf;
01803 }

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

01751 {
01752    unsigned int i;
01753 
01754    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01755       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01756          if (isAstFormat &&
01757              (code == AST_FORMAT_G726_AAL2) &&
01758              (options & AST_RTP_OPT_G726_NONSTANDARD))
01759             return "G726-32";
01760          else
01761             return mimeTypes[i].subtype;
01762       }
01763    }
01764 
01765    return "";
01766 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1686 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), MAX_RTP_PT, result, and static_RTP_PT.

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

01687 {
01688    struct rtpPayloadType result;
01689 
01690    result.isAstFormat = result.code = 0;
01691 
01692    if (pt < 0 || pt > MAX_RTP_PT) 
01693       return result; /* bogus payload type */
01694 
01695    /* Start with negotiated codecs */
01696    ast_mutex_lock(&rtp->bridge_lock);
01697    result = rtp->current_RTP_PT[pt];
01698    ast_mutex_unlock(&rtp->bridge_lock);
01699 
01700    /* If it doesn't exist, check our static RTP type list, just in case */
01701    if (!result.code) 
01702       result = static_RTP_PT[pt];
01703 
01704    return result;
01705 }

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

Definition at line 1547 of file rtp.c.

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

Referenced by wait_for_answer().

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

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

References ast_rtp_new_with_bindaddr(), io, and sched.

01950 {
01951    struct in_addr ia;
01952 
01953    memset(&ia, 0, sizeof(ia));
01954    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01955 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

01850 {
01851    ast_mutex_init(&rtp->bridge_lock);
01852 
01853    rtp->them.sin_family = AF_INET;
01854    rtp->us.sin_family = AF_INET;
01855    rtp->ssrc = ast_random();
01856    rtp->seqno = ast_random() & 0xffff;
01857    ast_set_flag(rtp, FLAG_HAS_DTMF);
01858 
01859    return;
01860 }

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

References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, FLAG_CALLBACK_MODE, free, io, LOG_ERROR, rtp_socket(), rtpread(), and sched.

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

01863 {
01864    struct ast_rtp *rtp;
01865    int x;
01866    int first;
01867    int startplace;
01868    
01869    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
01870       return NULL;
01871 
01872    ast_rtp_new_init(rtp);
01873 
01874    rtp->s = rtp_socket();
01875    if (rtp->s < 0) {
01876       free(rtp);
01877       ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
01878       return NULL;
01879    }
01880    if (sched && rtcpenable) {
01881       rtp->sched = sched;
01882       rtp->rtcp = ast_rtcp_new();
01883    }
01884    
01885    /* Select a random port number in the range of possible RTP */
01886    x = (ast_random() % (rtpend-rtpstart)) + rtpstart;
01887    x = x & ~1;
01888    /* Save it for future references. */
01889    startplace = x;
01890    /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
01891    for (;;) {
01892       /* Must be an even port number by RTP spec */
01893       rtp->us.sin_port = htons(x);
01894       rtp->us.sin_addr = addr;
01895       /* If there's rtcp, initialize it as well. */
01896       if (rtp->rtcp) {
01897          rtp->rtcp->us.sin_port = htons(x + 1);
01898          rtp->rtcp->us.sin_addr = addr;
01899       }
01900       /* Try to bind it/them. */
01901       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
01902          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
01903          break;
01904       if (!first) {
01905          /* Primary bind succeeded! Gotta recreate it */
01906          close(rtp->s);
01907          rtp->s = rtp_socket();
01908       }
01909       if (errno != EADDRINUSE) {
01910          /* We got an error that wasn't expected, abort! */
01911          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
01912          close(rtp->s);
01913          if (rtp->rtcp) {
01914             close(rtp->rtcp->s);
01915             free(rtp->rtcp);
01916          }
01917          free(rtp);
01918          return NULL;
01919       }
01920       /* The port was used, increment it (by two). */
01921       x += 2;
01922       /* Did we go over the limit ? */
01923       if (x > rtpend)
01924          /* then, start from the begingig. */
01925          x = (rtpstart + 1) & ~1;
01926       /* Check if we reached the place were we started. */
01927       if (x == startplace) {
01928          /* If so, there's no ports available. */
01929          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
01930          close(rtp->s);
01931          if (rtp->rtcp) {
01932             close(rtp->rtcp->s);
01933             free(rtp->rtcp);
01934          }
01935          free(rtp);
01936          return NULL;
01937       }
01938    }
01939    rtp->sched = sched;
01940    rtp->io = io;
01941    if (callbackmode) {
01942       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
01943       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
01944    }
01945    ast_rtp_pt_default(rtp);
01946    return rtp;
01947 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Definition at line 2770 of file rtp.c.

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

Referenced by load_module().

02771 {
02772    struct ast_rtp_protocol *cur;
02773 
02774    AST_LIST_LOCK(&protos);
02775    AST_LIST_TRAVERSE(&protos, cur, list) {   
02776       if (!strcmp(cur->type, proto->type)) {
02777          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02778          AST_LIST_UNLOCK(&protos);
02779          return -1;
02780       }
02781    }
02782    AST_LIST_INSERT_HEAD(&protos, proto, list);
02783    AST_LIST_UNLOCK(&protos);
02784    
02785    return 0;
02786 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2762 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.

Referenced by load_module(), and unload_module().

02763 {
02764    AST_LIST_LOCK(&protos);
02765    AST_LIST_REMOVE(&protos, proto, list);
02766    AST_LIST_UNLOCK(&protos);
02767 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1383 of file rtp.c.

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

Referenced by process_sdp().

01384 {
01385    int i;
01386 
01387    if (!rtp)
01388       return;
01389 
01390    ast_mutex_lock(&rtp->bridge_lock);
01391 
01392    for (i = 0; i < MAX_RTP_PT; ++i) {
01393       rtp->current_RTP_PT[i].isAstFormat = 0;
01394       rtp->current_RTP_PT[i].code = 0;
01395    }
01396 
01397    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01398    rtp->rtp_lookup_code_cache_code = 0;
01399    rtp->rtp_lookup_code_cache_result = 0;
01400 
01401    ast_mutex_unlock(&rtp->bridge_lock);
01402 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01424 {
01425    unsigned int i;
01426 
01427    ast_mutex_lock(&dest->bridge_lock);
01428    ast_mutex_lock(&src->bridge_lock);
01429 
01430    for (i=0; i < MAX_RTP_PT; ++i) {
01431       dest->current_RTP_PT[i].isAstFormat = 
01432          src->current_RTP_PT[i].isAstFormat;
01433       dest->current_RTP_PT[i].code = 
01434          src->current_RTP_PT[i].code; 
01435    }
01436    dest->rtp_lookup_code_cache_isAstFormat = 0;
01437    dest->rtp_lookup_code_cache_code = 0;
01438    dest->rtp_lookup_code_cache_result = 0;
01439 
01440    ast_mutex_unlock(&src->bridge_lock);
01441    ast_mutex_unlock(&dest->bridge_lock);
01442 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

Referenced by ast_rtp_new_with_bindaddr().

01405 {
01406    int i;
01407 
01408    ast_mutex_lock(&rtp->bridge_lock);
01409 
01410    /* Initialize to default payload types */
01411    for (i = 0; i < MAX_RTP_PT; ++i) {
01412       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01413       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01414    }
01415 
01416    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01417    rtp->rtp_lookup_code_cache_code = 0;
01418    rtp->rtp_lookup_code_cache_result = 0;
01419 
01420    ast_mutex_unlock(&rtp->bridge_lock);
01421 }

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

Definition at line 2564 of file rtp.c.

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

Referenced by ast_rtp_write().

02565 {
02566    unsigned char *rtpheader;
02567    int hdrlen = 12;
02568    int res;
02569    unsigned int ms;
02570    int pred;
02571    int mark = 0;
02572 
02573    ms = calc_txstamp(rtp, &f->delivery);
02574    /* Default prediction */
02575    if (f->subclass < AST_FORMAT_MAX_AUDIO) {
02576       pred = rtp->lastts + f->samples;
02577 
02578       /* Re-calculate last TS */
02579       rtp->lastts = rtp->lastts + ms * 8;
02580       if (ast_tvzero(f->delivery)) {
02581          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
02582             and if so, go with our prediction */
02583          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
02584             rtp->lastts = pred;
02585          else {
02586             if (option_debug > 2)
02587                ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
02588             mark = 1;
02589          }
02590       }
02591    } else {
02592       mark = f->subclass & 0x1;
02593       pred = rtp->lastovidtimestamp + f->samples;
02594       /* Re-calculate last TS */
02595       rtp->lastts = rtp->lastts + ms * 90;
02596       /* If it's close to our prediction, go for it */
02597       if (ast_tvzero(f->delivery)) {
02598          if (abs(rtp->lastts - pred) < 7200) {
02599             rtp->lastts = pred;
02600             rtp->lastovidtimestamp += f->samples;
02601          } else {
02602             if (option_debug > 2)
02603                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);
02604             rtp->lastovidtimestamp = rtp->lastts;
02605          }
02606       }
02607    }
02608    /* If the timestamp for non-digit packets has moved beyond the timestamp
02609       for digits, update the digit timestamp.
02610    */
02611    if (rtp->lastts > rtp->lastdigitts)
02612       rtp->lastdigitts = rtp->lastts;
02613 
02614    if (f->has_timing_info)
02615       rtp->lastts = f->ts * 8;
02616 
02617    /* Get a pointer to the header */
02618    rtpheader = (unsigned char *)(f->data - hdrlen);
02619 
02620    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
02621    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
02622    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
02623 
02624    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02625       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02626       if (res <0) {
02627          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
02628             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));
02629          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
02630             /* Only give this error message once if we are not RTP debugging */
02631             if (option_debug || rtpdebug)
02632                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));
02633             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
02634          }
02635       } else {
02636          rtp->txcount++;
02637          rtp->txoctetcount +=(res - hdrlen);
02638          
02639          if (rtp->rtcp && rtp->rtcp->schedid < 1) 
02640              rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
02641       }
02642             
02643       if (rtp_debug_test_addr(&rtp->them))
02644          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02645                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
02646    }
02647 
02648    rtp->seqno++;
02649 
02650    return 0;
02651 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1081 of file rtp.c.

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

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

int ast_rtp_reload ( void   ) 

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

03638 {
03639    struct ast_config *cfg;
03640    const char *s;
03641 
03642    rtpstart = 5000;
03643    rtpend = 31000;
03644    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03645    cfg = ast_config_load("rtp.conf");
03646    if (cfg) {
03647       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03648          rtpstart = atoi(s);
03649          if (rtpstart < 1024)
03650             rtpstart = 1024;
03651          if (rtpstart > 65535)
03652             rtpstart = 65535;
03653       }
03654       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03655          rtpend = atoi(s);
03656          if (rtpend < 1024)
03657             rtpend = 1024;
03658          if (rtpend > 65535)
03659             rtpend = 65535;
03660       }
03661       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03662          rtcpinterval = atoi(s);
03663          if (rtcpinterval == 0)
03664             rtcpinterval = 0; /* Just so we're clear... it's zero */
03665          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03666             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03667          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03668             rtcpinterval = RTCP_MAX_INTERVALMS;
03669       }
03670       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03671 #ifdef SO_NO_CHECK
03672          if (ast_false(s))
03673             nochecksums = 1;
03674          else
03675             nochecksums = 0;
03676 #else
03677          if (ast_false(s))
03678             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03679 #endif
03680       }
03681       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03682          dtmftimeout = atoi(s);
03683          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03684             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03685                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03686             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03687          };
03688       }
03689       ast_config_destroy(cfg);
03690    }
03691    if (rtpstart >= rtpend) {
03692       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03693       rtpstart = 5000;
03694       rtpend = 31000;
03695    }
03696    if (option_verbose > 1)
03697       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03698    return 0;
03699 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2023 of file rtp.c.

References ast_rtp::dtmfcount, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.

02024 {
02025    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02026    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02027    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02028    rtp->lastts = 0;
02029    rtp->lastdigitts = 0;
02030    rtp->lastrxts = 0;
02031    rtp->lastividtimestamp = 0;
02032    rtp->lastovidtimestamp = 0;
02033    rtp->lasteventseqn = 0;
02034    rtp->lastevent = 0;
02035    rtp->lasttxformat = 0;
02036    rtp->lastrxformat = 0;
02037    rtp->dtmfcount = 0;
02038    rtp->dtmfsamples = 0;
02039    rtp->seqno = 0;
02040    rtp->rxseqno = 0;
02041 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2530 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::data, ast_rtp::dtmfmute, 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().

02531 {
02532    unsigned int *rtpheader;
02533    int hdrlen = 12;
02534    int res;
02535    int payload;
02536    char data[256];
02537    level = 127 - (level & 0x7f);
02538    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
02539 
02540    /* If we have no peer, return immediately */ 
02541    if (!rtp->them.sin_addr.s_addr)
02542       return 0;
02543 
02544    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02545 
02546    /* Get a pointer to the header */
02547    rtpheader = (unsigned int *)data;
02548    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02549    rtpheader[1] = htonl(rtp->lastts);
02550    rtpheader[2] = htonl(rtp->ssrc); 
02551    data[12] = level;
02552    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02553       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02554       if (res <0) 
02555          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));
02556       if (rtp_debug_test_addr(&rtp->them))
02557          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
02558                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
02559          
02560    }
02561    return 0;
02562 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2133 of file rtp.c.

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

Referenced by oh323_digit_begin(), and sip_senddigit_begin().

02134 {
02135    unsigned int *rtpheader;
02136    int hdrlen = 12, res = 0, i = 0, payload = 0;
02137    char data[256];
02138 
02139    if ((digit <= '9') && (digit >= '0'))
02140       digit -= '0';
02141    else if (digit == '*')
02142       digit = 10;
02143    else if (digit == '#')
02144       digit = 11;
02145    else if ((digit >= 'A') && (digit <= 'D'))
02146       digit = digit - 'A' + 12;
02147    else if ((digit >= 'a') && (digit <= 'd'))
02148       digit = digit - 'a' + 12;
02149    else {
02150       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02151       return 0;
02152    }
02153 
02154    /* If we have no peer, return immediately */ 
02155    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02156       return 0;
02157 
02158    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02159 
02160    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02161    rtp->send_duration = 160;
02162    
02163    /* Get a pointer to the header */
02164    rtpheader = (unsigned int *)data;
02165    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02166    rtpheader[1] = htonl(rtp->lastdigitts);
02167    rtpheader[2] = htonl(rtp->ssrc); 
02168 
02169    for (i = 0; i < 2; i++) {
02170       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02171       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02172       if (res < 0) 
02173          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02174             ast_inet_ntoa(rtp->them.sin_addr),
02175             ntohs(rtp->them.sin_port), strerror(errno));
02176       if (rtp_debug_test_addr(&rtp->them))
02177          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02178                 ast_inet_ntoa(rtp->them.sin_addr),
02179                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02180       /* Increment sequence number */
02181       rtp->seqno++;
02182       /* Increment duration */
02183       rtp->send_duration += 160;
02184       /* Clear marker bit and set seqno */
02185       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02186    }
02187 
02188    /* Since we received a begin, we can safely store the digit and disable any compensation */
02189    rtp->sending_digit = 1;
02190    rtp->send_digit = digit;
02191    rtp->send_payload = payload;
02192 
02193    return 0;
02194 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

Definition at line 2197 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_verbose(), 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().

02198 {
02199    unsigned int *rtpheader;
02200    int hdrlen = 12, res = 0;
02201    char data[256];
02202 
02203    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02204       return 0;
02205 
02206    /* Setup packet to send */
02207    rtpheader = (unsigned int *)data;
02208         rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02209         rtpheader[1] = htonl(rtp->lastdigitts);
02210         rtpheader[2] = htonl(rtp->ssrc);
02211         rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
02212    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02213    
02214    /* Transmit */
02215    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02216    if (res < 0)
02217       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02218          ast_inet_ntoa(rtp->them.sin_addr),
02219          ntohs(rtp->them.sin_port), strerror(errno));
02220    if (rtp_debug_test_addr(&rtp->them))
02221       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02222              ast_inet_ntoa(rtp->them.sin_addr),
02223              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02224 
02225    /* Increment sequence number */
02226    rtp->seqno++;
02227    /* Increment duration */
02228    rtp->send_duration += 160;
02229 
02230    return 0;
02231 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2234 of file rtp.c.

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

Referenced by oh323_digit_end(), and sip_senddigit_end().

02235 {
02236    unsigned int *rtpheader;
02237    int hdrlen = 12, res = 0, i = 0;
02238    char data[256];
02239    
02240    /* If no address, then bail out */
02241    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02242       return 0;
02243    
02244    if ((digit <= '9') && (digit >= '0'))
02245       digit -= '0';
02246    else if (digit == '*')
02247       digit = 10;
02248    else if (digit == '#')
02249       digit = 11;
02250    else if ((digit >= 'A') && (digit <= 'D'))
02251       digit = digit - 'A' + 12;
02252    else if ((digit >= 'a') && (digit <= 'd'))
02253       digit = digit - 'a' + 12;
02254    else {
02255       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02256       return 0;
02257    }
02258 
02259    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02260 
02261    rtpheader = (unsigned int *)data;
02262    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02263    rtpheader[1] = htonl(rtp->lastdigitts);
02264    rtpheader[2] = htonl(rtp->ssrc);
02265    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02266    /* Set end bit */
02267    rtpheader[3] |= htonl((1 << 23));
02268    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02269    /* Send 3 termination packets */
02270    for (i = 0; i < 3; i++) {
02271       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02272       if (res < 0)
02273          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02274             ast_inet_ntoa(rtp->them.sin_addr),
02275             ntohs(rtp->them.sin_port), strerror(errno));
02276       if (rtp_debug_test_addr(&rtp->them))
02277          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02278                 ast_inet_ntoa(rtp->them.sin_addr),
02279                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02280    }
02281    rtp->sending_digit = 0;
02282    rtp->send_digit = 0;
02283    /* Increment lastdigitts */
02284    rtp->lastdigitts += 960;
02285    rtp->seqno++;
02286 
02287    return res;
02288 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 585 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 580 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

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

Definition at line 1622 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_newcall(), and process_sdp().

01623 {
01624    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01625       return; /* bogus payload type */
01626 
01627    ast_mutex_lock(&rtp->bridge_lock);
01628    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01629    ast_mutex_unlock(&rtp->bridge_lock);
01630 } 

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

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

01967 {
01968    rtp->them.sin_port = them->sin_port;
01969    rtp->them.sin_addr = them->sin_addr;
01970    if (rtp->rtcp) {
01971       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
01972       rtp->rtcp->them.sin_addr = them->sin_addr;
01973    }
01974    rtp->rxseqno = 0;
01975 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 547 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

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

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 553 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

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

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

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

Definition at line 1635 of file rtp.c.

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

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

01638 {
01639    unsigned int i;
01640 
01641    if (pt < 0 || pt > MAX_RTP_PT) 
01642       return; /* bogus payload type */
01643    
01644    ast_mutex_lock(&rtp->bridge_lock);
01645 
01646    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01647       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01648           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01649          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01650          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01651              mimeTypes[i].payloadType.isAstFormat &&
01652              (options & AST_RTP_OPT_G726_NONSTANDARD))
01653             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01654          break;
01655       }
01656    }
01657 
01658    ast_mutex_unlock(&rtp->bridge_lock);
01659 
01660    return;
01661 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 541 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 534 of file rtp.c.

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

Referenced by handle_response_invite().

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

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

Definition at line 600 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_DTMF.

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

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

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

Definition at line 605 of file rtp.c.

References ast_set2_flag, and FLAG_DTMF_COMPENSATE.

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

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

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 590 of file rtp.c.

References ast_rtp::nat.

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

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

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 610 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 1957 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

01958 {
01959    int res;
01960 
01961    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
01962       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01963    return res;
01964 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

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

02007 {
02008    if (rtp->rtcp && rtp->rtcp->schedid > 0) {
02009       ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02010       rtp->rtcp->schedid = -1;
02011    }
02012 
02013    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02014    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02015    if (rtp->rtcp) {
02016       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02017       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02018    }
02019    
02020    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02021 }

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

Definition at line 402 of file rtp.c.

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

Referenced by gtalk_update_stun().

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

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2682 of file rtp.c.

References ast_codec_pref_getsize(), 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_frame::datalen, f, fmt, ast_frame::frametype, 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().

02683 {
02684    struct ast_frame *f;
02685    int codec;
02686    int hdrlen = 12;
02687    int subclass;
02688    
02689 
02690    /* If we have no peer, return immediately */ 
02691    if (!rtp->them.sin_addr.s_addr)
02692       return 0;
02693 
02694    /* If there is no data length, return immediately */
02695    if (!_f->datalen) 
02696       return 0;
02697    
02698    /* Make sure we have enough space for RTP header */
02699    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02700       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02701       return -1;
02702    }
02703 
02704    subclass = _f->subclass;
02705    if (_f->frametype == AST_FRAME_VIDEO)
02706       subclass &= ~0x1;
02707 
02708    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02709    if (codec < 0) {
02710       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02711       return -1;
02712    }
02713 
02714    if (rtp->lasttxformat != subclass) {
02715       /* New format, reset the smoother */
02716       if (option_debug)
02717          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02718       rtp->lasttxformat = subclass;
02719       if (rtp->smoother)
02720          ast_smoother_free(rtp->smoother);
02721       rtp->smoother = NULL;
02722    }
02723 
02724    if (!rtp->smoother) {
02725       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02726       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02727          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02728             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));
02729             return -1;
02730          }
02731          if (fmt.flags)
02732             ast_smoother_set_flags(rtp->smoother, fmt.flags);
02733          if (option_debug)
02734             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));
02735       }
02736    }
02737    if (rtp->smoother) {
02738       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
02739          ast_smoother_feed_be(rtp->smoother, _f);
02740       } else {
02741          ast_smoother_feed(rtp->smoother, _f);
02742       }
02743 
02744       while((f = ast_smoother_read(rtp->smoother)))
02745          ast_rtp_raw_write(rtp, f, codec);
02746    } else {
02747            /* Don't buffer outgoing frames; send them one-per-packet: */
02748       if (_f->offset < hdrlen) {
02749          f = ast_frdup(_f);
02750       } else {
02751          f = _f;
02752       }
02753       ast_rtp_raw_write(rtp, f, codec);
02754       if (f != _f)
02755          ast_frfree(f);
02756    }
02757       
02758    return 0;
02759 }

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 2789 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_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate_data(), ast_inet_ntoa(), ast_log(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), ast_frame::data, ast_frame::datalen, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, inaddrcmp(), LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

02790 {
02791    struct ast_frame *fr = NULL;
02792    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
02793    int oldcodec0 = codec0, oldcodec1 = codec1;
02794    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
02795    struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
02796    
02797    /* Set it up so audio goes directly between the two endpoints */
02798 
02799    /* Test the first channel */
02800    if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
02801       ast_rtp_get_peer(p1, &ac1);
02802       if (vp1)
02803          ast_rtp_get_peer(vp1, &vac1);
02804    } else
02805       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
02806    
02807    /* Test the second channel */
02808    if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
02809       ast_rtp_get_peer(p0, &ac0);
02810       if (vp0)
02811          ast_rtp_get_peer(vp0, &vac0);
02812    } else
02813       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
02814 
02815    /* Now we can unlock and move into our loop */
02816    ast_channel_unlock(c0);
02817    ast_channel_unlock(c1);
02818 
02819    /* Throw our channels into the structure and enter the loop */
02820    cs[0] = c0;
02821    cs[1] = c1;
02822    cs[2] = NULL;
02823    for (;;) {
02824       /* Check if anything changed */
02825       if ((c0->tech_pvt != pvt0) ||
02826           (c1->tech_pvt != pvt1) ||
02827           (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
02828          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
02829          if (c0->tech_pvt == pvt0)
02830             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02831                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02832          if (c1->tech_pvt == pvt1)
02833             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02834                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02835          return AST_BRIDGE_RETRY;
02836       }
02837 
02838       /* Check if they have changed their address */
02839       ast_rtp_get_peer(p1, &t1);
02840       if (vp1)
02841          ast_rtp_get_peer(vp1, &vt1);
02842       if (pr1->get_codec)
02843          codec1 = pr1->get_codec(c1);
02844       ast_rtp_get_peer(p0, &t0);
02845       if (vp0)
02846          ast_rtp_get_peer(vp0, &vt0);
02847       if (pr0->get_codec)
02848          codec0 = pr0->get_codec(c0);
02849       if ((inaddrcmp(&t1, &ac1)) ||
02850           (vp1 && inaddrcmp(&vt1, &vac1)) ||
02851           (codec1 != oldcodec1)) {
02852          if (option_debug > 1) {
02853             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02854                c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
02855             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
02856                c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
02857             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02858                c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
02859             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02860                c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
02861          }
02862          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)))
02863             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
02864          memcpy(&ac1, &t1, sizeof(ac1));
02865          memcpy(&vac1, &vt1, sizeof(vac1));
02866          oldcodec1 = codec1;
02867       }
02868       if ((inaddrcmp(&t0, &ac0)) ||
02869           (vp0 && inaddrcmp(&vt0, &vac0))) {
02870          if (option_debug > 1) {
02871             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02872                c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
02873             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02874                c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
02875          }
02876          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)))
02877             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
02878          memcpy(&ac0, &t0, sizeof(ac0));
02879          memcpy(&vac0, &vt0, sizeof(vac0));
02880          oldcodec0 = codec0;
02881       }
02882 
02883       /* Wait for frame to come in on the channels */
02884       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
02885          if (!timeoutms)
02886             return AST_BRIDGE_RETRY;
02887          if (option_debug)
02888             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
02889          if (ast_check_hangup(c0) || ast_check_hangup(c1))
02890             break;
02891          continue;
02892       }
02893       fr = ast_read(who);
02894       other = (who == c0) ? c1 : c0;
02895       if (!fr || ((fr->frametype == AST_FRAME_DTMF) &&
02896              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
02897               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
02898          /* Break out of bridge */
02899          *fo = fr;
02900          *rc = who;
02901          if (option_debug)
02902             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
02903          if (c0->tech_pvt == pvt0)
02904             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02905                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02906          if (c1->tech_pvt == pvt1)
02907             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02908                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02909          return AST_BRIDGE_COMPLETE;
02910       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02911          if ((fr->subclass == AST_CONTROL_HOLD) ||
02912              (fr->subclass == AST_CONTROL_UNHOLD) ||
02913              (fr->subclass == AST_CONTROL_VIDUPDATE)) {
02914             if (fr->subclass == AST_CONTROL_HOLD) {
02915                /* If we someone went on hold we want the other side to reinvite back to us */
02916                if (who == c0)
02917                   pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
02918                else
02919                   pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
02920             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
02921                /* If they went off hold they should go back to being direct */
02922                if (who == c0)
02923                   pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
02924                else
02925                   pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
02926             }
02927             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
02928             ast_frfree(fr);
02929          } else {
02930             *fo = fr;
02931             *rc = who;
02932             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
02933             return AST_BRIDGE_COMPLETE;
02934          }
02935       } else {
02936          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
02937              (fr->frametype == AST_FRAME_DTMF) ||
02938              (fr->frametype == AST_FRAME_VOICE) ||
02939              (fr->frametype == AST_FRAME_VIDEO) ||
02940              (fr->frametype == AST_FRAME_IMAGE) ||
02941              (fr->frametype == AST_FRAME_HTML) ||
02942              (fr->frametype == AST_FRAME_MODEM) ||
02943              (fr->frametype == AST_FRAME_TEXT)) {
02944             ast_write(other, fr);
02945          }
02946          ast_frfree(fr);
02947       }
02948       /* Swap priority */
02949       cs[2] = cs[0];
02950       cs[0] = cs[1];
02951       cs[1] = cs[2];
02952    }
02953 
02954    return AST_BRIDGE_FAILED;
02955 }

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

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate_data(), ast_log(), ast_read(), ast_waitfor_n(), ast_write(), ast_frame::data, ast_frame::datalen, FLAG_P2P_SENT_MARK, ast_frame::frametype, LOG_NOTICE, ast_channel::masq, ast_channel::masqr, option_debug, p2p_callback_disable(), p2p_callback_enable(), p2p_set_bridge(), ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

03054 {
03055    struct ast_frame *fr = NULL;
03056    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03057    int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
03058    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03059    int p0_callback = 0, p1_callback = 0;
03060    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03061 
03062    /* Okay, setup each RTP structure to do P2P forwarding */
03063    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03064    p2p_set_bridge(p0, p1);
03065    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03066    p2p_set_bridge(p1, p0);
03067 
03068    /* Activate callback modes if possible */
03069    p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03070    p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03071 
03072    /* Now let go of the channel locks and be on our way */
03073    ast_channel_unlock(c0);
03074    ast_channel_unlock(c1);
03075 
03076    /* Go into a loop forwarding frames until we don't need to anymore */
03077    cs[0] = c0;
03078    cs[1] = c1;
03079    cs[2] = NULL;
03080    for (;;) {
03081       /* Check if anything changed */
03082       if ((c0->tech_pvt != pvt0) ||
03083           (c1->tech_pvt != pvt1) ||
03084           (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
03085          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03086          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03087             ast_frfree(fr);
03088          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03089             ast_frfree(fr);
03090          res = AST_BRIDGE_RETRY;
03091          break;
03092       }
03093       /* Wait on a channel to feed us a frame */
03094       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03095          if (!timeoutms) {
03096             res = AST_BRIDGE_RETRY;
03097             break;
03098          }
03099          if (option_debug)
03100             ast_log(LOG_NOTICE, "Ooh, empty read...\n");
03101          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03102             break;
03103          continue;
03104       }
03105       /* Read in frame from channel */
03106       fr = ast_read(who);
03107       other = (who == c0) ? c1 : c0;
03108       /* Dependong on the frame we may need to break out of our bridge */
03109       if (!fr || ((fr->frametype == AST_FRAME_DTMF) &&
03110              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03111              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03112          /* Record received frame and who */
03113          *fo = fr;
03114          *rc = who;
03115          if (option_debug)
03116             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03117          res = AST_BRIDGE_COMPLETE;
03118          break;
03119       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03120          if ((fr->subclass == AST_CONTROL_HOLD) ||
03121              (fr->subclass == AST_CONTROL_UNHOLD) ||
03122              (fr->subclass == AST_CONTROL_VIDUPDATE)) {
03123             /* If we are going on hold, then break callback mode and P2P bridging */
03124             if (fr->subclass == AST_CONTROL_HOLD) {
03125                if (p0_callback)
03126                   p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03127                if (p1_callback)
03128                   p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03129                p2p_set_bridge(p0, NULL);
03130                p2p_set_bridge(p1, NULL);
03131             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03132                /* If we are off hold, then go back to callback mode and P2P bridging */
03133                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03134                p2p_set_bridge(p0, p1);
03135                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03136                p2p_set_bridge(p1, p0);
03137                p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03138                p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03139             }
03140             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03141             ast_frfree(fr);
03142          } else {
03143             *fo = fr;
03144             *rc = who;
03145             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03146             res = AST_BRIDGE_COMPLETE;
03147             break;
03148          }
03149       } else {
03150          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03151              (fr->frametype == AST_FRAME_DTMF) ||
03152              (fr->frametype == AST_FRAME_VOICE) ||
03153              (fr->frametype == AST_FRAME_VIDEO) ||
03154              (fr->frametype == AST_FRAME_IMAGE) ||
03155              (fr->frametype == AST_FRAME_HTML) ||
03156              (fr->frametype == AST_FRAME_MODEM) ||
03157              (fr->frametype == AST_FRAME_TEXT)) {
03158             ast_write(other, fr);
03159          }
03160 
03161          ast_frfree(fr);
03162       }
03163       /* Swap priority */
03164       cs[2] = cs[0];
03165       cs[0] = cs[1];
03166       cs[1] = cs[2];
03167    }
03168 
03169    /* If we are totally avoiding the core, then restore our link to it */
03170    if (p0_callback)
03171       p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03172    if (p1_callback)
03173       p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03174 
03175    /* Break out of the direct bridge */
03176    p2p_set_bridge(p0, NULL);
03177    p2p_set_bridge(p1, NULL);
03178 
03179    return res;
03180 }

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 1030 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, ext, 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, rtp_debug_test_addr(), ast_rtp::s, and ast_rtp::them.

Referenced by ast_rtp_read().

01031 {
01032    int res = 0, payload = 0, bridged_payload = 0, version, padding, mark, ext;
01033    struct rtpPayloadType rtpPT;
01034    unsigned int seqno;
01035    
01036    /* Get fields from packet */
01037    seqno = ntohl(rtpheader[0]);
01038    version = (seqno & 0xC0000000) >> 30;
01039    payload = (seqno & 0x7f0000) >> 16;
01040    padding = seqno & (1 << 29);
01041    mark = (seqno & 0x800000) >> 23;
01042    ext = seqno & (1 << 28);
01043    seqno &= 0xffff;
01044 
01045    /* Check what the payload value should be */
01046    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01047 
01048    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01049    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01050       return -1;
01051 
01052    /* Otherwise adjust bridged payload to match */
01053    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01054 
01055    /* If the mark bit has not been sent yet... do it now */
01056    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01057       mark = 1;
01058       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01059    }
01060 
01061    /* Reconstruct part of the packet */
01062    rtpheader[0] = htonl((version << 30) | (mark << 23) | (bridged_payload << 16) | (seqno));
01063 
01064    /* Send the packet back out */
01065    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01066    if (res < 0) {
01067       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01068          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));
01069       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01070          if (option_debug || rtpdebug)
01071             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));
01072          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01073       }
01074       return 0;
01075    } else if (rtp_debug_test_addr(&bridged->them))
01076          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);
01077 
01078    return 0;
01079 }

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

Definition at line 981 of file rtp.c.

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

Referenced by ast_rtp_read(), and schedule_delivery().

00982 {
00983    struct timeval now;
00984    double transit;
00985    double current_time;
00986    double d;
00987    double dtv;
00988    double prog;
00989    
00990    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
00991       gettimeofday(&rtp->rxcore, NULL);
00992       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
00993       /* map timestamp to a real time */
00994       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
00995       rtp->rxcore.tv_sec -= timestamp / 8000;
00996       rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
00997       /* Round to 0.1ms for nice, pretty timestamps */
00998       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
00999       if (rtp->rxcore.tv_usec < 0) {
01000          /* Adjust appropriately if necessary */
01001          rtp->rxcore.tv_usec += 1000000;
01002          rtp->rxcore.tv_sec -= 1;
01003       }
01004    }
01005 
01006    gettimeofday(&now,NULL);
01007    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01008    tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
01009    tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
01010    if (tv->tv_usec >= 1000000) {
01011       tv->tv_usec -= 1000000;
01012       tv->tv_sec += 1;
01013    }
01014    prog = (double)((timestamp-rtp->seedrxts)/8000.);
01015    dtv = (double)rtp->drxcore + (double)(prog);
01016    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01017    transit = current_time - dtv;
01018    d = transit - rtp->rxtransit;
01019    rtp->rxtransit = transit;
01020    if (d<0)
01021       d=-d;
01022    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01023    if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
01024       rtp->rtcp->maxrxjitter = rtp->rxjitter;
01025    if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01026       rtp->rtcp->minrxjitter = rtp->rxjitter;
01027 }

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

Definition at line 2113 of file rtp.c.

References t, and ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

02114 {
02115    struct timeval t;
02116    long ms;
02117    if (ast_tvzero(rtp->txcore)) {
02118       rtp->txcore = ast_tvnow();
02119       /* Round to 20ms for nice, pretty timestamps */
02120       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02121    }
02122    /* Use previous txcore if available */
02123    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02124    ms = ast_tvdiff_ms(t, rtp->txcore);
02125    if (ms < 0)
02126       ms = 0;
02127    /* Use what we just got for next time */
02128    rtp->txcore = t;
02129    return (unsigned int) ms;
02130 }

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

Get channel driver interface structure.

Definition at line 1445 of file rtp.c.

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

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

01446 {
01447    struct ast_rtp_protocol *cur = NULL;
01448 
01449    AST_LIST_LOCK(&protos);
01450    AST_LIST_TRAVERSE(&protos, cur, list) {
01451       if (cur->type == chan->tech->type)
01452          break;
01453    }
01454    AST_LIST_UNLOCK(&protos);
01455 
01456    return cur;
01457 }

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

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

Referenced by bridge_p2p_loop().

03025 {
03026    ast_channel_lock(chan);
03027 
03028    /* Remove the callback from the IO context */
03029    ast_io_remove(rtp->io, iod[0]);
03030 
03031    /* Restore file descriptors */
03032    chan->fds[0] = fds[0];
03033    ast_channel_unlock(chan);
03034 
03035    /* Restore callback mode if previously used */
03036    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03037       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03038 
03039    return 0;
03040 }

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

P2P RTP Callback.

Definition at line 3017 of file rtp.c.

Referenced by bridge_p2p_loop().

03018 {
03019    return 0;
03020 }

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

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

Referenced by bridge_p2p_loop().

03044 {
03045    ast_mutex_lock(&rtp0->bridge_lock);
03046    rtp0->bridged = rtp1;
03047    ast_mutex_unlock(&rtp0->bridge_lock);
03048 
03049    return;
03050 }

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

Definition at line 669 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Process RTP DTMF and events according to RFC 2833.

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

Parameters:
rtp 
data 
len 
seqno 
Returns:

Definition at line 708 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

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

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

Definition at line 655 of file rtp.c.

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

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

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

Definition at line 3434 of file rtp.c.

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

03434                                                          {
03435    if (argc != 2) {
03436       if (argc != 4)
03437          return RESULT_SHOWUSAGE;
03438       return rtcp_do_debug_ip(fd, argc, argv);
03439    }
03440    rtcpdebug = 1;
03441    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03442    ast_cli(fd, "RTCP Debugging Enabled\n");
03443    return RESULT_SUCCESS;
03444 }

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

Definition at line 3422 of file rtp.c.

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

03422                                                                     {
03423    if (argc != 3) {
03424       if (argc != 5)
03425          return RESULT_SHOWUSAGE;
03426       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03427    }
03428    rtcpdebug = 1;
03429    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03430    ast_cli(fd, "RTCP Debugging Enabled\n");
03431    return RESULT_SUCCESS;
03432 }

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

Definition at line 3379 of file rtp.c.

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

Referenced by rtcp_do_debug().

03380 {
03381    struct hostent *hp;
03382    struct ast_hostent ahp;
03383    int port = 0;
03384    char *p, *arg;
03385    if (argc != 4)
03386       return RESULT_SHOWUSAGE;
03387 
03388    arg = argv[3];
03389    p = strstr(arg, ":");
03390    if (p) {
03391       *p = '\0';
03392       p++;
03393       port = atoi(p);
03394    }
03395    hp = ast_gethostbyname(arg, &ahp);
03396    if (hp == NULL)
03397       return RESULT_SHOWUSAGE;
03398    rtcpdebugaddr.sin_family = AF_INET;
03399    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03400    rtcpdebugaddr.sin_port = htons(port);
03401    if (port == 0)
03402       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03403    else
03404       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03405    rtcpdebug = 1;
03406    return RESULT_SUCCESS;
03407 }

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

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

03350 {
03351    struct hostent *hp;
03352    struct ast_hostent ahp;
03353    int port = 0;
03354    char *p, *arg;
03355    if (argc != 5)
03356       return RESULT_SHOWUSAGE;
03357 
03358    arg = argv[4];
03359    p = strstr(arg, ":");
03360    if (p) {
03361       *p = '\0';
03362       p++;
03363       port = atoi(p);
03364    }
03365    hp = ast_gethostbyname(arg, &ahp);
03366    if (hp == NULL)
03367       return RESULT_SHOWUSAGE;
03368    rtcpdebugaddr.sin_family = AF_INET;
03369    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03370    rtcpdebugaddr.sin_port = htons(port);
03371    if (port == 0)
03372       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03373    else
03374       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03375    rtcpdebug = 1;
03376    return RESULT_SUCCESS;
03377 }

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

Definition at line 3455 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03455                                                          {
03456    if (argc != 2) {
03457       return RESULT_SHOWUSAGE;
03458    }
03459    rtcpstats = 1;
03460    ast_cli(fd, "RTCP Stats Enabled\n");
03461    return RESULT_SUCCESS;
03462 }

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

Definition at line 3446 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03446                                                                     {
03447    if (argc != 3) {
03448       return RESULT_SHOWUSAGE;
03449    }
03450    rtcpstats = 1;
03451    ast_cli(fd, "RTCP Stats Enabled\n");
03452    return RESULT_SUCCESS;
03453 }

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

Definition at line 3482 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03483 {
03484    if (argc != 3)
03485       return RESULT_SHOWUSAGE;
03486    rtcpdebug = 0;
03487    ast_cli(fd,"RTCP Debugging Disabled\n");
03488    return RESULT_SUCCESS;
03489 }

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

Definition at line 3473 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03474 {
03475    if (argc != 4)
03476       return RESULT_SHOWUSAGE;
03477    rtcpdebug = 0;
03478    ast_cli(fd,"RTCP Debugging Disabled\n");
03479    return RESULT_SUCCESS;
03480 }

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

Definition at line 3500 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03501 {
03502    if (argc != 3)
03503       return RESULT_SHOWUSAGE;
03504    rtcpstats = 0;
03505    ast_cli(fd,"RTCP Stats Disabled\n");
03506    return RESULT_SUCCESS;
03507 }

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

Definition at line 3491 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03492 {
03493    if (argc != 4)
03494       return RESULT_SHOWUSAGE;
03495    rtcpstats = 0;
03496    ast_cli(fd,"RTCP Stats Disabled\n");
03497    return RESULT_SUCCESS;
03498 }

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

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

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

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

Definition at line 3409 of file rtp.c.

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

03410 {
03411    if (argc != 2) {
03412       if (argc != 4)
03413          return RESULT_SHOWUSAGE;
03414       return rtp_do_debug_ip(fd, argc, argv);
03415    }
03416    rtpdebug = 1;
03417    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03418    ast_cli(fd, "RTP Debugging Enabled\n");
03419    return RESULT_SUCCESS;
03420 }

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

Definition at line 3319 of file rtp.c.

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

Referenced by rtp_do_debug().

03320 {
03321    struct hostent *hp;
03322    struct ast_hostent ahp;
03323    int port = 0;
03324    char *p, *arg;
03325 
03326    if (argc != 4)
03327       return RESULT_SHOWUSAGE;
03328    arg = argv[3];
03329    p = strstr(arg, ":");
03330    if (p) {
03331       *p = '\0';
03332       p++;
03333       port = atoi(p);
03334    }
03335    hp = ast_gethostbyname(arg, &ahp);
03336    if (hp == NULL)
03337       return RESULT_SHOWUSAGE;
03338    rtpdebugaddr.sin_family = AF_INET;
03339    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
03340    rtpdebugaddr.sin_port = htons(port);
03341    if (port == 0)
03342       ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
03343    else
03344       ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
03345    rtpdebug = 1;
03346    return RESULT_SUCCESS;
03347 }

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

Definition at line 3464 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03465 {
03466    if (argc != 3)
03467       return RESULT_SHOWUSAGE;
03468    rtpdebug = 0;
03469    ast_cli(fd,"RTP Debugging Disabled\n");
03470    return RESULT_SUCCESS;
03471 }

static int rtp_socket ( void   )  [static]

Definition at line 1805 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01806 {
01807    int s;
01808    long flags;
01809    s = socket(AF_INET, SOCK_DGRAM, 0);
01810    if (s > -1) {
01811       flags = fcntl(s, F_GETFL);
01812       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01813 #ifdef SO_NO_CHECK
01814       if (nochecksums)
01815          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01816 #endif
01817    }
01818    return s;
01819 }

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

Definition at line 810 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

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

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

Definition at line 615 of file rtp.c.

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

Referenced by process_cisco_dtmf(), and process_rfc2833().

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

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

Definition at line 299 of file rtp.c.

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

Referenced by stun_handle_packet(), and stun_process_attr().

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

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

Definition at line 3509 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03510 {
03511    if (argc != 2) {
03512       return RESULT_SHOWUSAGE;
03513    }
03514    stundebug = 1;
03515    ast_cli(fd, "STUN Debugging Enabled\n");
03516    return RESULT_SUCCESS;
03517 }

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

Definition at line 423 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Definition at line 280 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3519 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03520 {
03521    if (argc != 3)
03522       return RESULT_SHOWUSAGE;
03523    stundebug = 0;
03524    ast_cli(fd, "STUN Debugging Disabled\n");
03525    return RESULT_SUCCESS;
03526 }

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

Definition at line 333 of file rtp.c.

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

Referenced by stun_handle_packet().

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

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 390 of file rtp.c.

References ast_random(), and stun_header::id.

Referenced by ast_rtp_stun_request().

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

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

Definition at line 384 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Definition at line 502 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3595 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 3560 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 3570 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 3565 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 3575 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 3585 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 3580 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 3590 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 3528 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 3532 of file rtp.c.

struct stun_addr packed

struct stun_attr packed

struct stun_header packed

Referenced by get_unaligned_uint16(), get_unaligned_uint32(), put_unaligned_uint16(), and put_unaligned_uint32().

struct rtpPayloadType payloadType

Definition at line 1318 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 3544 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 3548 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 3556 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

Definition at line 3552 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 1350 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 3536 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3540 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1320 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1319 of file rtp.c.

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


Generated on Mon May 14 04:50:59 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1