Thu Feb 5 16:26:23 2009

Asterisk developer's documentation


rtp.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

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

Variables

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


Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

#define DEFAULT_DTMF_TIMEOUT   3000

samples

Definition at line 76 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 187 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 194 of file rtp.c.

Referenced by p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 195 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

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

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

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

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 264 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 262 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 263 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 273 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 259 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 269 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 279 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 267 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

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

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Definition at line 354 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 525 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1867 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

01868 {
01869    struct ast_rtcp *rtcp;
01870 
01871    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01872       return NULL;
01873    rtcp->s = rtp_socket();
01874    if (option_debug > 3)
01875          ast_log(LOG_DEBUG, "socket RTPaux (RTCP) fd: %i\n", rtcp->s);
01876    rtcp->us.sin_family = AF_INET;
01877    rtcp->them.sin_family = AF_INET;
01878    rtcp->schedid = -1;
01879 
01880    if (rtcp->s < 0) {
01881       free(rtcp);
01882       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01883       return NULL;
01884    }
01885 
01886    return rtcp;
01887 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 827 of file rtp.c.

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

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

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

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

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

02362 {
02363    struct ast_rtp *rtp = data;
02364    int res;
02365 
02366    rtp->rtcp->sendfur = 1;
02367    res = ast_rtcp_write(data);
02368    
02369    return res;
02370 }

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

Write and RTCP packet to the far end.

Note:
Decide if we are going to send an SR (with Reception Block) or RR RR is sent if we have not sent any rtp packets in the previous interval

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

02579 {
02580    struct ast_rtp *rtp = (struct ast_rtp *)data;
02581    int res;
02582    
02583    if (!rtp || !rtp->rtcp)
02584       return 0;
02585 
02586    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02587       res = ast_rtcp_write_sr(data);
02588    else
02589       res = ast_rtcp_write_rr(data);
02590    
02591    return res;
02592 }

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

Send RTCP recepient's report.

Note:
Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos it can change mid call, and SDES can't)

Definition at line 2483 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), ast_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, len(), LOG_ERROR, ast_rtcp::received_prior, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, and ast_rtp::themssrc.

Referenced by ast_rtcp_write().

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

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

Send RTCP sender's report.

Definition at line 2373 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), ast_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len(), LOG_ERROR, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.

Referenced by ast_rtcp_write().

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

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

Referenced by process_sdp().

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

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

References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_channel::name, option_debug, option_verbose, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

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

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2749 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

02750 {
02751    if (pt < 0 || pt > MAX_RTP_PT)
02752       return 0; /* bogus payload type */
02753 
02754    if (static_RTP_PT[pt].isAstFormat)
02755       return static_RTP_PT[pt].code;
02756    else
02757       return 0;
02758 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Definition at line 2744 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02745 {
02746    return &rtp->pref;
02747 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2731 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(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

02732 {
02733    int x;
02734    for (x = 0; x < 32; x++) {  /* Ugly way */
02735       rtp->pref.order[x] = prefs->order[x];
02736       rtp->pref.framing[x] = prefs->framing[x];
02737    }
02738    if (rtp->smoother)
02739       ast_smoother_free(rtp->smoother);
02740    rtp->smoother = NULL;
02741    return 0;
02742 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

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

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

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

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

Referenced by wait_for_answer().

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00514 {
00515    return rtp->s;
00516 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

Definition at line 2053 of file rtp.c.

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

Referenced by __sip_destroy(), and ast_rtp_read().

02054 {
02055    struct ast_rtp *bridged = NULL;
02056 
02057    ast_mutex_lock(&rtp->bridge_lock);
02058    bridged = rtp->bridged;
02059    ast_mutex_unlock(&rtp->bridge_lock);
02060 
02061    return bridged;
02062 }

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

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

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

01708 {
01709    int pt;
01710    
01711    ast_mutex_lock(&rtp->bridge_lock);
01712    
01713    *astFormats = *nonAstFormats = 0;
01714    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01715       if (rtp->current_RTP_PT[pt].isAstFormat) {
01716          *astFormats |= rtp->current_RTP_PT[pt].code;
01717       } else {
01718          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01719       }
01720    }
01721    
01722    ast_mutex_unlock(&rtp->bridge_lock);
01723    
01724    return;
01725 }

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

Definition at line 2035 of file rtp.c.

References ast_rtp::them.

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

02036 {
02037    if ((them->sin_family != AF_INET) ||
02038       (them->sin_port != rtp->them.sin_port) ||
02039       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02040       them->sin_family = AF_INET;
02041       them->sin_port = rtp->them.sin_port;
02042       them->sin_addr = rtp->them.sin_addr;
02043       return 1;
02044    }
02045    return 0;
02046 }

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

Return RTCP quality string.

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

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

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 568 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 576 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00577 {
00578    return rtp->rtpkeepalive;
00579 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 560 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

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

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

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

02049 {
02050    *us = rtp->us;
02051 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 596 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3843 of file rtp.c.

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

Referenced by main().

03844 {
03845    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03846    ast_rtp_reload();
03847 }

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

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

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

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

Referenced by process_sdp().

01811 {
01812    int format;
01813    unsigned len;
01814    char *end = buf;
01815    char *start = buf;
01816 
01817    if (!buf || !size)
01818       return NULL;
01819 
01820    snprintf(end, size, "0x%x (", capability);
01821 
01822    len = strlen(end);
01823    end += len;
01824    size -= len;
01825    start = end;
01826 
01827    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01828       if (capability & format) {
01829          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01830 
01831          snprintf(end, size, "%s|", name);
01832          len = strlen(end);
01833          end += len;
01834          size -= len;
01835       }
01836    }
01837 
01838    if (start == end)
01839       snprintf(start, size, "nothing)"); 
01840    else if (size > 1)
01841       *(end -1) = ')';
01842    
01843    return buf;
01844 }

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

01792 {
01793    unsigned int i;
01794 
01795    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01796       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01797          if (isAstFormat &&
01798              (code == AST_FORMAT_G726_AAL2) &&
01799              (options & AST_RTP_OPT_G726_NONSTANDARD))
01800             return "G726-32";
01801          else
01802             return mimeTypes[i].subtype;
01803       }
01804    }
01805 
01806    return "";
01807 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1727 of file rtp.c.

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

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

01728 {
01729    struct rtpPayloadType result;
01730 
01731    result.isAstFormat = result.code = 0;
01732 
01733    if (pt < 0 || pt > MAX_RTP_PT) 
01734       return result; /* bogus payload type */
01735 
01736    /* Start with negotiated codecs */
01737    ast_mutex_lock(&rtp->bridge_lock);
01738    result = rtp->current_RTP_PT[pt];
01739    ast_mutex_unlock(&rtp->bridge_lock);
01740 
01741    /* If it doesn't exist, check our static RTP type list, just in case */
01742    if (!result.code) 
01743       result = static_RTP_PT[pt];
01744 
01745    return result;
01746 }

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

Definition at line 1572 of file rtp.c.

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

Referenced by wait_for_answer().

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

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02000 {
02001    struct in_addr ia;
02002 
02003    memset(&ia, 0, sizeof(ia));
02004    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02005 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

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

01894 {
01895    ast_mutex_init(&rtp->bridge_lock);
01896 
01897    rtp->them.sin_family = AF_INET;
01898    rtp->us.sin_family = AF_INET;
01899    rtp->ssrc = ast_random();
01900    rtp->seqno = ast_random() & 0xffff;
01901    ast_set_flag(rtp, FLAG_HAS_DTMF);
01902 
01903    return;
01904 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2016 of file rtp.c.

References ast_rtp::set_marker_bit.

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

02017 {
02018    if (rtp) {
02019       rtp->set_marker_bit = 1;
02020    }
02021    return;
02022 }

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

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

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Definition at line 2860 of file rtp.c.

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

Referenced by load_module().

02861 {
02862    struct ast_rtp_protocol *cur;
02863 
02864    AST_LIST_LOCK(&protos);
02865    AST_LIST_TRAVERSE(&protos, cur, list) {   
02866       if (!strcmp(cur->type, proto->type)) {
02867          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02868          AST_LIST_UNLOCK(&protos);
02869          return -1;
02870       }
02871    }
02872    AST_LIST_INSERT_HEAD(&protos, proto, list);
02873    AST_LIST_UNLOCK(&protos);
02874    
02875    return 0;
02876 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2852 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by load_module(), and unload_module().

02853 {
02854    AST_LIST_LOCK(&protos);
02855    AST_LIST_REMOVE(&protos, proto, list);
02856    AST_LIST_UNLOCK(&protos);
02857 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1409 of file rtp.c.

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

Referenced by gtalk_alloc(), and process_sdp().

01410 {
01411    int i;
01412 
01413    if (!rtp)
01414       return;
01415 
01416    ast_mutex_lock(&rtp->bridge_lock);
01417 
01418    for (i = 0; i < MAX_RTP_PT; ++i) {
01419       rtp->current_RTP_PT[i].isAstFormat = 0;
01420       rtp->current_RTP_PT[i].code = 0;
01421    }
01422 
01423    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01424    rtp->rtp_lookup_code_cache_code = 0;
01425    rtp->rtp_lookup_code_cache_result = 0;
01426 
01427    ast_mutex_unlock(&rtp->bridge_lock);
01428 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01450 {
01451    unsigned int i;
01452 
01453    ast_mutex_lock(&dest->bridge_lock);
01454    ast_mutex_lock(&src->bridge_lock);
01455 
01456    for (i=0; i < MAX_RTP_PT; ++i) {
01457       dest->current_RTP_PT[i].isAstFormat = 
01458          src->current_RTP_PT[i].isAstFormat;
01459       dest->current_RTP_PT[i].code = 
01460          src->current_RTP_PT[i].code; 
01461    }
01462    dest->rtp_lookup_code_cache_isAstFormat = 0;
01463    dest->rtp_lookup_code_cache_code = 0;
01464    dest->rtp_lookup_code_cache_result = 0;
01465 
01466    ast_mutex_unlock(&src->bridge_lock);
01467    ast_mutex_unlock(&dest->bridge_lock);
01468 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

01431 {
01432    int i;
01433 
01434    ast_mutex_lock(&rtp->bridge_lock);
01435 
01436    /* Initialize to default payload types */
01437    for (i = 0; i < MAX_RTP_PT; ++i) {
01438       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01439       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01440    }
01441 
01442    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01443    rtp->rtp_lookup_code_cache_code = 0;
01444    rtp->rtp_lookup_code_cache_result = 0;
01445 
01446    ast_mutex_unlock(&rtp->bridge_lock);
01447 }

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

Definition at line 2629 of file rtp.c.

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

Referenced by ast_rtp_write().

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

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1110 of file rtp.c.

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

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

int ast_rtp_reload ( void   ) 

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

03779 {
03780    struct ast_config *cfg;
03781    const char *s;
03782 
03783    rtpstart = 5000;
03784    rtpend = 31000;
03785    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03786    cfg = ast_config_load("rtp.conf");
03787    if (cfg) {
03788       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03789          rtpstart = atoi(s);
03790          if (rtpstart < 1024)
03791             rtpstart = 1024;
03792          if (rtpstart > 65535)
03793             rtpstart = 65535;
03794       }
03795       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03796          rtpend = atoi(s);
03797          if (rtpend < 1024)
03798             rtpend = 1024;
03799          if (rtpend > 65535)
03800             rtpend = 65535;
03801       }
03802       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03803          rtcpinterval = atoi(s);
03804          if (rtcpinterval == 0)
03805             rtcpinterval = 0; /* Just so we're clear... it's zero */
03806          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03807             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03808          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03809             rtcpinterval = RTCP_MAX_INTERVALMS;
03810       }
03811       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03812 #ifdef SO_NO_CHECK
03813          if (ast_false(s))
03814             nochecksums = 1;
03815          else
03816             nochecksums = 0;
03817 #else
03818          if (ast_false(s))
03819             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03820 #endif
03821       }
03822       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03823          dtmftimeout = atoi(s);
03824          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03825             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03826                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03827             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03828          };
03829       }
03830       ast_config_destroy(cfg);
03831    }
03832    if (rtpstart >= rtpend) {
03833       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03834       rtpstart = 5000;
03835       rtpend = 31000;
03836    }
03837    if (option_verbose > 1)
03838       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03839    return 0;
03840 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

02081 {
02082    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02083    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02084    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02085    rtp->lastts = 0;
02086    rtp->lastdigitts = 0;
02087    rtp->lastrxts = 0;
02088    rtp->lastividtimestamp = 0;
02089    rtp->lastovidtimestamp = 0;
02090    rtp->lasteventseqn = 0;
02091    rtp->lastevent = 0;
02092    rtp->lasttxformat = 0;
02093    rtp->lastrxformat = 0;
02094    rtp->dtmfcount = 0;
02095    rtp->dtmfsamples = 0;
02096    rtp->seqno = 0;
02097    rtp->rxseqno = 0;
02098 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2595 of file rtp.c.

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

Referenced by do_monitor().

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2203 of file rtp.c.

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

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

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

Definition at line 2268 of file rtp.c.

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

Referenced by ast_rtp_read().

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2305 of file rtp.c.

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

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

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

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 586 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 581 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

Definition at line 1647 of file rtp.c.

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

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

01648 {
01649    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01650       return; /* bogus payload type */
01651 
01652    ast_mutex_lock(&rtp->bridge_lock);
01653    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01654    ast_mutex_unlock(&rtp->bridge_lock);
01655 } 

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

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

02025 {
02026    rtp->them.sin_port = them->sin_port;
02027    rtp->them.sin_addr = them->sin_addr;
02028    if (rtp->rtcp) {
02029       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02030       rtp->rtcp->them.sin_addr = them->sin_addr;
02031    }
02032    rtp->rxseqno = 0;
02033 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 548 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

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

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 554 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

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

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

Initiate payload type to a known MIME media type for a codec.

Returns:
0 if the MIME type was found and set, -1 if it wasn't found

Definition at line 1674 of file rtp.c.

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

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

01677 {
01678    unsigned int i;
01679    int found = 0;
01680 
01681    if (pt < 0 || pt > MAX_RTP_PT) 
01682       return -1; /* bogus payload type */
01683    
01684    ast_mutex_lock(&rtp->bridge_lock);
01685 
01686    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01687       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01688           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01689          found = 1;
01690          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01691          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01692              mimeTypes[i].payloadType.isAstFormat &&
01693              (options & AST_RTP_OPT_G726_NONSTANDARD))
01694             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01695          break;
01696       }
01697    }
01698 
01699    ast_mutex_unlock(&rtp->bridge_lock);
01700 
01701    return (found ? 0 : -1);
01702 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 542 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 535 of file rtp.c.

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

Referenced by handle_response_invite().

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

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

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

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

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

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 591 of file rtp.c.

References ast_rtp::nat.

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

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

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 611 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 2007 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

02008 {
02009    int res;
02010 
02011    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
02012       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
02013    return res;
02014 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

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

02065 {
02066    if (rtp->rtcp) {
02067       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02068    }
02069 
02070    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02071    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02072    if (rtp->rtcp) {
02073       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02074       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02075    }
02076    
02077    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02078 }

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

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

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

Definition at line 1659 of file rtp.c.

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

Referenced by process_sdp().

01660 {
01661    if (pt < 0 || pt > MAX_RTP_PT)
01662       return; /* bogus payload type */
01663 
01664    ast_mutex_lock(&rtp->bridge_lock);
01665    rtp->current_RTP_PT[pt].isAstFormat = 0;
01666    rtp->current_RTP_PT[pt].code = 0;
01667    ast_mutex_unlock(&rtp->bridge_lock);
01668 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2760 of file rtp.c.

References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

Referenced by gtalk_write(), mgcp_write(), oh323_write(), sip_write(), and skinny_write().

02761 {
02762    struct ast_frame *f;
02763    int codec;
02764    int hdrlen = 12;
02765    int subclass;
02766    
02767 
02768    /* If we have no peer, return immediately */ 
02769    if (!rtp->them.sin_addr.s_addr)
02770       return 0;
02771 
02772    /* If there is no data length, return immediately */
02773    if (!_f->datalen) 
02774       return 0;
02775    
02776    /* Make sure we have enough space for RTP header */
02777    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02778       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02779       return -1;
02780    }
02781 
02782    subclass = _f->subclass;
02783    if (_f->frametype == AST_FRAME_VIDEO)
02784       subclass &= ~0x1;
02785 
02786    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02787    if (codec < 0) {
02788       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02789       return -1;
02790    }
02791 
02792    if (rtp->lasttxformat != subclass) {
02793       /* New format, reset the smoother */
02794       if (option_debug)
02795          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02796       rtp->lasttxformat = subclass;
02797       if (rtp->smoother)
02798          ast_smoother_free(rtp->smoother);
02799       rtp->smoother = NULL;
02800    }
02801 
02802    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
02803       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02804       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02805          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02806             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));
02807             return -1;
02808          }
02809          if (fmt.flags)
02810             ast_smoother_set_flags(rtp->smoother, fmt.flags);
02811          if (option_debug)
02812             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));
02813       }
02814    }
02815    if (rtp->smoother) {
02816       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
02817          ast_smoother_feed_be(rtp->smoother, _f);
02818       } else {
02819          ast_smoother_feed(rtp->smoother, _f);
02820       }
02821 
02822       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
02823          if (f->subclass == AST_FORMAT_G722) {
02824             /* G.722 is silllllllllllllly */
02825             f->samples /= 2;
02826          }
02827 
02828          ast_rtp_raw_write(rtp, f, codec);
02829       }
02830    } else {
02831       /* Don't buffer outgoing frames; send them one-per-packet: */
02832       if (_f->offset < hdrlen) {
02833          f = ast_frdup(_f);
02834       } else {
02835          f = _f;
02836       }
02837       if (f->data) {
02838          if (f->subclass == AST_FORMAT_G722) {
02839             /* G.722 is silllllllllllllly */
02840             f->samples /= 2;
02841          }
02842          ast_rtp_raw_write(rtp, f, codec);
02843       }
02844       if (f != _f)
02845          ast_frfree(f);
02846    }
02847       
02848    return 0;
02849 }

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

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

Referenced by ast_rtp_bridge().

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

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

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

Referenced by ast_rtp_bridge().

03166 {
03167    struct ast_frame *fr = NULL;
03168    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03169    int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
03170    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03171    int p0_callback = 0, p1_callback = 0;
03172    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03173 
03174    /* Okay, setup each RTP structure to do P2P forwarding */
03175    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03176    p2p_set_bridge(p0, p1);
03177    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03178    p2p_set_bridge(p1, p0);
03179 
03180    /* Activate callback modes if possible */
03181    p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03182    p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03183 
03184    /* Now let go of the channel locks and be on our way */
03185    ast_channel_unlock(c0);
03186    ast_channel_unlock(c1);
03187 
03188    /* Go into a loop forwarding frames until we don't need to anymore */
03189    cs[0] = c0;
03190    cs[1] = c1;
03191    cs[2] = NULL;
03192    for (;;) {
03193       /* If the underlying formats have changed force this bridge to break */
03194       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
03195          ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n");
03196          res = AST_BRIDGE_FAILED_NOWARN;
03197          break;
03198       }
03199       /* Check if anything changed */
03200       if ((c0->tech_pvt != pvt0) ||
03201           (c1->tech_pvt != pvt1) ||
03202           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03203           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03204          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03205          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03206             ast_frfree(fr);
03207          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03208             ast_frfree(fr);
03209          res = AST_BRIDGE_RETRY;
03210          break;
03211       }
03212       /* Wait on a channel to feed us a frame */
03213       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03214          if (!timeoutms) {
03215             res = AST_BRIDGE_RETRY;
03216             break;
03217          }
03218          if (option_debug)
03219             ast_log(LOG_NOTICE, "Ooh, empty read...\n");
03220          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03221             break;
03222          continue;
03223       }
03224       /* Read in frame from channel */
03225       fr = ast_read(who);
03226       other = (who == c0) ? c1 : c0;
03227       /* Dependong on the frame we may need to break out of our bridge */
03228       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03229              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03230              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03231          /* Record received frame and who */
03232          *fo = fr;
03233          *rc = who;
03234          if (option_debug)
03235             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03236          res = AST_BRIDGE_COMPLETE;
03237          break;
03238       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03239          if ((fr->subclass == AST_CONTROL_HOLD) ||
03240              (fr->subclass == AST_CONTROL_UNHOLD) ||
03241              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03242              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03243             /* If we are going on hold, then break callback mode and P2P bridging */
03244             if (fr->subclass == AST_CONTROL_HOLD) {
03245                if (p0_callback)
03246                   p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03247                if (p1_callback)
03248                   p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03249                p2p_set_bridge(p0, NULL);
03250                p2p_set_bridge(p1, NULL);
03251             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03252                /* If we are off hold, then go back to callback mode and P2P bridging */
03253                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03254                p2p_set_bridge(p0, p1);
03255                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03256                p2p_set_bridge(p1, p0);
03257                p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03258                p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03259             }
03260             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03261             ast_frfree(fr);
03262          } else {
03263             *fo = fr;
03264             *rc = who;
03265             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03266             res = AST_BRIDGE_COMPLETE;
03267             break;
03268          }
03269       } else {
03270          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03271              (fr->frametype == AST_FRAME_DTMF_END) ||
03272              (fr->frametype == AST_FRAME_VOICE) ||
03273              (fr->frametype == AST_FRAME_VIDEO) ||
03274              (fr->frametype == AST_FRAME_IMAGE) ||
03275              (fr->frametype == AST_FRAME_HTML) ||
03276              (fr->frametype == AST_FRAME_MODEM) ||
03277              (fr->frametype == AST_FRAME_TEXT)) {
03278             ast_write(other, fr);
03279          }
03280 
03281          ast_frfree(fr);
03282       }
03283       /* Swap priority */
03284       cs[2] = cs[0];
03285       cs[0] = cs[1];
03286       cs[1] = cs[2];
03287    }
03288 
03289    /* If we are totally avoiding the core, then restore our link to it */
03290    if (p0_callback)
03291       p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03292    if (p1_callback)
03293       p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03294 
03295    /* Break out of the direct bridge */
03296    p2p_set_bridge(p0, NULL);
03297    p2p_set_bridge(p1, NULL);
03298 
03299    return res;
03300 }

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

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

Referenced by ast_rtp_read().

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

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

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

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

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

Definition at line 2183 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

02184 {
02185    struct timeval t;
02186    long ms;
02187    if (ast_tvzero(rtp->txcore)) {
02188       rtp->txcore = ast_tvnow();
02189       /* Round to 20ms for nice, pretty timestamps */
02190       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02191    }
02192    /* Use previous txcore if available */
02193    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02194    ms = ast_tvdiff_ms(t, rtp->txcore);
02195    if (ms < 0)
02196       ms = 0;
02197    /* Use what we just got for next time */
02198    rtp->txcore = t;
02199    return (unsigned int) ms;
02200 }

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

Get channel driver interface structure.

Definition at line 1471 of file rtp.c.

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

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

01472 {
01473    struct ast_rtp_protocol *cur = NULL;
01474 
01475    AST_LIST_LOCK(&protos);
01476    AST_LIST_TRAVERSE(&protos, cur, list) {
01477       if (cur->type == chan->tech->type)
01478          break;
01479    }
01480    AST_LIST_UNLOCK(&protos);
01481 
01482    return cur;
01483 }

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

03137 {
03138    ast_channel_lock(chan);
03139 
03140    /* Remove the callback from the IO context */
03141    ast_io_remove(rtp->io, iod[0]);
03142 
03143    /* Restore file descriptors */
03144    chan->fds[0] = fds[0];
03145    ast_channel_unlock(chan);
03146 
03147    /* Restore callback mode if previously used */
03148    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03149       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03150 
03151    return 0;
03152 }

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

P2P RTP Callback.

Definition at line 3129 of file rtp.c.

Referenced by bridge_p2p_loop().

03130 {
03131    return 0;
03132 }

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

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

Referenced by bridge_p2p_loop().

03156 {
03157    ast_mutex_lock(&rtp0->bridge_lock);
03158    rtp0->bridged = rtp1;
03159    ast_mutex_unlock(&rtp0->bridge_lock);
03160 
03161    return;
03162 }

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

Definition at line 670 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_null_frame, ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), ast_rtp::dtmfcount, ast_rtp::dtmfsamples, 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().

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

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

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

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

Definition at line 656 of file rtp.c.

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

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

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

Definition at line 3575 of file rtp.c.

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

03575                                                          {
03576    if (argc != 2) {
03577       if (argc != 4)
03578          return RESULT_SHOWUSAGE;
03579       return rtcp_do_debug_ip(fd, argc, argv);
03580    }
03581    rtcpdebug = 1;
03582    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03583    ast_cli(fd, "RTCP Debugging Enabled\n");
03584    return RESULT_SUCCESS;
03585 }

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

Definition at line 3563 of file rtp.c.

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

03563                                                                     {
03564    if (argc != 3) {
03565       if (argc != 5)
03566          return RESULT_SHOWUSAGE;
03567       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03568    }
03569    rtcpdebug = 1;
03570    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03571    ast_cli(fd, "RTCP Debugging Enabled\n");
03572    return RESULT_SUCCESS;
03573 }

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

Definition at line 3520 of file rtp.c.

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

Referenced by rtcp_do_debug().

03521 {
03522    struct hostent *hp;
03523    struct ast_hostent ahp;
03524    int port = 0;
03525    char *p, *arg;
03526    if (argc != 4)
03527       return RESULT_SHOWUSAGE;
03528 
03529    arg = argv[3];
03530    p = strstr(arg, ":");
03531    if (p) {
03532       *p = '\0';
03533       p++;
03534       port = atoi(p);
03535    }
03536    hp = ast_gethostbyname(arg, &ahp);
03537    if (hp == NULL)
03538       return RESULT_SHOWUSAGE;
03539    rtcpdebugaddr.sin_family = AF_INET;
03540    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03541    rtcpdebugaddr.sin_port = htons(port);
03542    if (port == 0)
03543       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03544    else
03545       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03546    rtcpdebug = 1;
03547    return RESULT_SUCCESS;
03548 }

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

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

03491 {
03492    struct hostent *hp;
03493    struct ast_hostent ahp;
03494    int port = 0;
03495    char *p, *arg;
03496    if (argc != 5)
03497       return RESULT_SHOWUSAGE;
03498 
03499    arg = argv[4];
03500    p = strstr(arg, ":");
03501    if (p) {
03502       *p = '\0';
03503       p++;
03504       port = atoi(p);
03505    }
03506    hp = ast_gethostbyname(arg, &ahp);
03507    if (hp == NULL)
03508       return RESULT_SHOWUSAGE;
03509    rtcpdebugaddr.sin_family = AF_INET;
03510    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03511    rtcpdebugaddr.sin_port = htons(port);
03512    if (port == 0)
03513       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03514    else
03515       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03516    rtcpdebug = 1;
03517    return RESULT_SUCCESS;
03518 }

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

Definition at line 3596 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03596                                                          {
03597    if (argc != 2) {
03598       return RESULT_SHOWUSAGE;
03599    }
03600    rtcpstats = 1;
03601    ast_cli(fd, "RTCP Stats Enabled\n");
03602    return RESULT_SUCCESS;
03603 }

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

Definition at line 3587 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03587                                                                     {
03588    if (argc != 3) {
03589       return RESULT_SHOWUSAGE;
03590    }
03591    rtcpstats = 1;
03592    ast_cli(fd, "RTCP Stats Enabled\n");
03593    return RESULT_SUCCESS;
03594 }

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

Definition at line 3623 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03624 {
03625    if (argc != 3)
03626       return RESULT_SHOWUSAGE;
03627    rtcpdebug = 0;
03628    ast_cli(fd,"RTCP Debugging Disabled\n");
03629    return RESULT_SUCCESS;
03630 }

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

Definition at line 3614 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03615 {
03616    if (argc != 4)
03617       return RESULT_SHOWUSAGE;
03618    rtcpdebug = 0;
03619    ast_cli(fd,"RTCP Debugging Disabled\n");
03620    return RESULT_SUCCESS;
03621 }

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

Definition at line 3641 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03642 {
03643    if (argc != 3)
03644       return RESULT_SHOWUSAGE;
03645    rtcpstats = 0;
03646    ast_cli(fd,"RTCP Stats Disabled\n");
03647    return RESULT_SUCCESS;
03648 }

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

Definition at line 3632 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03633 {
03634    if (argc != 4)
03635       return RESULT_SHOWUSAGE;
03636    rtcpstats = 0;
03637    ast_cli(fd,"RTCP Stats Disabled\n");
03638    return RESULT_SUCCESS;
03639 }

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

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

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

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

Definition at line 3550 of file rtp.c.

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

03551 {
03552    if (argc != 2) {
03553       if (argc != 4)
03554          return RESULT_SHOWUSAGE;
03555       return rtp_do_debug_ip(fd, argc, argv);
03556    }
03557    rtpdebug = 1;
03558    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03559    ast_cli(fd, "RTP Debugging Enabled\n");
03560    return RESULT_SUCCESS;
03561 }

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

Definition at line 3460 of file rtp.c.

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

Referenced by rtp_do_debug().

03461 {
03462    struct hostent *hp;
03463    struct ast_hostent ahp;
03464    int port = 0;
03465    char *p, *arg;
03466 
03467    if (argc != 4)
03468       return RESULT_SHOWUSAGE;
03469    arg = argv[3];
03470    p = strstr(arg, ":");
03471    if (p) {
03472       *p = '\0';
03473       p++;
03474       port = atoi(p);
03475    }
03476    hp = ast_gethostbyname(arg, &ahp);
03477    if (hp == NULL)
03478       return RESULT_SHOWUSAGE;
03479    rtpdebugaddr.sin_family = AF_INET;
03480    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
03481    rtpdebugaddr.sin_port = htons(port);
03482    if (port == 0)
03483       ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
03484    else
03485       ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
03486    rtpdebug = 1;
03487    return RESULT_SUCCESS;
03488 }

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

Definition at line 3605 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03606 {
03607    if (argc != 3)
03608       return RESULT_SHOWUSAGE;
03609    rtpdebug = 0;
03610    ast_cli(fd,"RTP Debugging Disabled\n");
03611    return RESULT_SUCCESS;
03612 }

static int rtp_socket ( void   )  [static]

Definition at line 1846 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01847 {
01848    int s;
01849    long flags;
01850    s = socket(AF_INET, SOCK_DGRAM, 0);
01851    if (s > -1) {
01852       flags = fcntl(s, F_GETFL);
01853       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01854 #ifdef SO_NO_CHECK
01855       if (nochecksums)
01856          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01857 #endif
01858    }
01859    return s;
01860 }

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

Definition at line 815 of file rtp.c.

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

Referenced by p2p_callback_disable().

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

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

Definition at line 616 of file rtp.c.

References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_test_flag, ast_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::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().

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

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

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

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

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

Definition at line 3650 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03651 {
03652    if (argc != 2) {
03653       return RESULT_SHOWUSAGE;
03654    }
03655    stundebug = 1;
03656    ast_cli(fd, "STUN Debugging Enabled\n");
03657    return RESULT_SUCCESS;
03658 }

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

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

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

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

Definition at line 281 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3660 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03661 {
03662    if (argc != 3)
03663       return RESULT_SHOWUSAGE;
03664    stundebug = 0;
03665    ast_cli(fd, "STUN Debugging Disabled\n");
03666    return RESULT_SUCCESS;
03667 }

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

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

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

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 391 of file rtp.c.

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

Referenced by ast_rtp_stun_request().

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

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

Definition at line 385 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Definition at line 503 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3736 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 3701 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 3711 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 3706 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 3716 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 3726 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 3721 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 3731 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 3669 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 3673 of file rtp.c.

struct rtpPayloadType payloadType

Definition at line 1342 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 3685 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 3689 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 3697 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

Definition at line 3693 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 1377 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 3677 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3681 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1344 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1343 of file rtp.c.

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


Generated on Thu Feb 5 16:26:23 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7