Wed Aug 15 01:25:31 2007

Asterisk developer's documentation


rtp.c File Reference

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

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

Include dependency graph for rtp.c:

Go to the source code of this file.

Data Structures

struct  __attribute__
struct  ast_rtcp
 Structure defining an RTCP session. More...
struct  ast_rtp
 RTP session description. More...
struct  rtpPayloadType
 Structure representing a RTP session. More...
struct  stun_addr
struct  stun_attr
struct  stun_header
struct  stun_state

Defines

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

Functions

static void append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
static void append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
static AST_LIST_HEAD_STATIC (protos, ast_rtp_protocol)
 List of current sessions.
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
struct ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Public function: Send an H.261 fast update request, some devices need this rather than SIP XML.
static int ast_rtcp_write (void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (void *data)
 Send RTCP recepient's report.
static int ast_rtcp_write_sr (void *data)
 Send RTCP sender's report.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
enum ast_bridge_result ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
int ast_rtp_codec_getformat (int pt)
struct 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)
struct 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):.
struct 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)
struct 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.
struct 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)
struct ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
static int ast_rtp_senddigit_continuation (struct ast_rtp *rtp)
 Send continuation frame for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
void ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
static enum
ast_bridge_result 
bridge_native_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for true native bridge (reinvite).
static enum
ast_bridge_result 
bridge_p2p_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for partial native bridge (packet2packet).
static int bridge_p2p_rtp_write (struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen)
 Perform a Packet2Packet RTP write.
static void calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
static struct
ast_rtp_protocol
get_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 {
   struct rtpPayloadType   payloadType
   char *   subtype
   char *   type
mimeTypes []
static char no_debug_usage []
struct stun_addr packed
struct stun_attr packed
struct stun_header packed
static char rtcp_debug_usage []
static char rtcp_no_debug_usage []
static char rtcp_no_stats_usage []
static char rtcp_stats_usage []
static int rtcpdebug
static struct sockaddr_in rtcpdebugaddr
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static int rtcpstats
static int rtpdebug
static struct sockaddr_in rtpdebugaddr
static int rtpend
static int rtpstart
static struct
rtpPayloadType 
static_RTP_PT [MAX_RTP_PT]
static char stun_debug_usage []
static char stun_no_debug_usage []
static int stundebug


Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

#define DEFAULT_DTMF_TIMEOUT   3000

samples

Definition at line 76 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 186 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 193 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 194 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

Definition at line 190 of file rtp.c.

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

#define FLAG_HAS_STUN   (1 << 8)

Definition at line 195 of file rtp.c.

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 187 of file rtp.c.

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

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 188 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 189 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_P2P_NEED_DTMF   (1 << 5)

Definition at line 192 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 191 of file rtp.c.

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

#define MAX_TIMESTAMP_SKEW   20

Definition at line 60 of file rtp.c.

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

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 63 of file rtp.c.

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 65 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 64 of file rtp.c.

Referenced by ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 72 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 71 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

Definition at line 67 of file rtp.c.

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

#define RTCP_PT_RR   201

Definition at line 69 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

Definition at line 70 of file rtp.c.

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

#define RTCP_PT_SR   200

Definition at line 68 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 74 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 62 of file rtp.c.

Referenced by ast_rtp_read().

#define STUN_ACCEPT   (1)

Definition at line 259 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 263 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 261 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 262 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 258 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 268 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 269 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 264 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 273 of file rtp.c.

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


Function Documentation

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

Definition at line 366 of file rtp.c.

References stun_addr::addr, stun_addr::family, stun_addr::port, and stun_addr::unused.

Referenced by stun_handle_packet().

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

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

Definition at line 353 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

static AST_LIST_HEAD_STATIC ( protos  ,
ast_rtp_protocol   
) [static]

List of current sessions.

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Todo:
XXX Do a more reasonable calculation on this one Look in RFC 3550 Section A.7 for an example

Definition at line 524 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 517 of file rtp.c.

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static, read]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1833 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

01834 {
01835    struct ast_rtcp *rtcp;
01836 
01837    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01838       return NULL;
01839    rtcp->s = rtp_socket();
01840    rtcp->us.sin_family = AF_INET;
01841    rtcp->them.sin_family = AF_INET;
01842 
01843    if (rtcp->s < 0) {
01844       free(rtcp);
01845       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01846       return NULL;
01847    }
01848 
01849    return rtcp;
01850 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  )  [read]

Definition at line 822 of file rtp.c.

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

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

int ast_rtcp_send_h261fur ( void *  data  ) 

Public function: Send an H.261 fast update request, some devices need this rather than SIP XML.

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

Definition at line 2298 of file rtp.c.

02299 {
02300    struct ast_rtp *rtp = data;
02301    int res;
02302 
02303    rtp->rtcp->sendfur = 1;
02304    res = ast_rtcp_write(data);
02305    
02306    return res;
02307 }

static int ast_rtcp_write ( void *  data  )  [static]

Write and RTCP packet to the far end.

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

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

02524 {
02525    struct ast_rtp *rtp = data;
02526    int res;
02527    
02528    if (!rtp || !rtp->rtcp)
02529       return 0;
02530 
02531    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02532       res = ast_rtcp_write_sr(data);
02533    else
02534       res = ast_rtcp_write_rr(data);
02535    
02536    return res;
02537 }

static int ast_rtcp_write_rr ( 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 2424 of file rtp.c.

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

Referenced by ast_rtcp_write().

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

static int ast_rtcp_write_sr ( void *  data  )  [static]

Send RTCP sender's report.

Definition at line 2310 of file rtp.c.

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

Referenced by ast_rtcp_write().

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

size_t ast_rtp_alloc_size ( void   ) 

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

Returns:
number of bytes required

Definition at line 397 of file rtp.c.

Referenced by process_sdp().

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

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

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

Definition at line 3206 of file rtp.c.

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

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2681 of file rtp.c.

Referenced by process_sdp().

02682 {
02683    if (pt < 0 || pt > MAX_RTP_PT)
02684       return 0; /* bogus payload type */
02685 
02686    if (static_RTP_PT[pt].isAstFormat)
02687       return static_RTP_PT[pt].code;
02688    else
02689       return 0;
02690 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  )  [read]

Definition at line 2676 of file rtp.c.

Referenced by add_codec_to_sdp(), and process_sdp().

02677 {
02678    return &rtp->pref;
02679 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2663 of file rtp.c.

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

02664 {
02665    int x;
02666    for (x = 0; x < 32; x++) {  /* Ugly way */
02667       rtp->pref.order[x] = prefs->order[x];
02668       rtp->pref.framing[x] = prefs->framing[x];
02669    }
02670    if (rtp->smoother)
02671       ast_smoother_free(rtp->smoother);
02672    rtp->smoother = NULL;
02673    return 0;
02674 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 2080 of file rtp.c.

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

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

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

Referenced by wait_for_answer().

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 512 of file rtp.c.

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

00513 {
00514    return rtp->s;
00515 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  )  [read]

Definition at line 2002 of file rtp.c.

Referenced by ast_rtp_read(), and do_monitor().

02003 {
02004    struct ast_rtp *bridged = NULL;
02005 
02006    ast_mutex_lock(&rtp->bridge_lock);
02007    bridged = rtp->bridged;
02008    ast_mutex_unlock(&rtp->bridge_lock);
02009 
02010    return bridged;
02011 }

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

Referenced by process_sdp().

01674 {
01675    int pt;
01676    
01677    ast_mutex_lock(&rtp->bridge_lock);
01678    
01679    *astFormats = *nonAstFormats = 0;
01680    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01681       if (rtp->current_RTP_PT[pt].isAstFormat) {
01682          *astFormats |= rtp->current_RTP_PT[pt].code;
01683       } else {
01684          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01685       }
01686    }
01687    
01688    ast_mutex_unlock(&rtp->bridge_lock);
01689    
01690    return;
01691 }

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

Definition at line 1984 of file rtp.c.

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

01985 {
01986    if ((them->sin_family != AF_INET) ||
01987       (them->sin_port != rtp->them.sin_port) ||
01988       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
01989       them->sin_family = AF_INET;
01990       them->sin_port = rtp->them.sin_port;
01991       them->sin_addr = rtp->them.sin_addr;
01992       return 1;
01993    }
01994    return 0;
01995 }

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

Return RTCP quality string.

Definition at line 2050 of file rtp.c.

Referenced by acf_channel_read(), handle_request_bye(), and sip_hangup().

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

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 567 of file rtp.c.

Referenced by do_monitor().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 575 of file rtp.c.

Referenced by do_monitor().

00576 {
00577    return rtp->rtpkeepalive;
00578 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 559 of file rtp.c.

Referenced by do_monitor().

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

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

Definition at line 1997 of file rtp.c.

Referenced by add_sdp(), external_rtp_create(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), and oh323_set_rtp_peer().

01998 {
01999    *us = rtp->us;
02000 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 595 of file rtp.c.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3736 of file rtp.c.

Referenced by main().

03737 {
03738    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03739    ast_rtp_reload();
03740 }

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

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

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

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

Referenced by process_sdp().

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

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

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

01758 {
01759    unsigned int i;
01760 
01761    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01762       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01763          if (isAstFormat &&
01764              (code == AST_FORMAT_G726_AAL2) &&
01765              (options & AST_RTP_OPT_G726_NONSTANDARD))
01766             return "G726-32";
01767          else
01768             return mimeTypes[i].subtype;
01769       }
01770    }
01771 
01772    return "";
01773 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
) [read]

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1693 of file rtp.c.

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

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

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

Definition at line 1554 of file rtp.c.

Referenced by wait_for_answer().

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

struct ast_rtp* ast_rtp_new ( struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode 
) [read]

Initializate a RTP session.

Parameters:
sched 
io 
rtcpenable 
callbackmode 
Returns:
A representation (structure) of an RTP session.

Definition at line 1956 of file rtp.c.

01957 {
01958    struct in_addr ia;
01959 
01960    memset(&ia, 0, sizeof(ia));
01961    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01962 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

Definition at line 1856 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().

01857 {
01858    ast_mutex_init(&rtp->bridge_lock);
01859 
01860    rtp->them.sin_family = AF_INET;
01861    rtp->us.sin_family = AF_INET;
01862    rtp->ssrc = ast_random();
01863    rtp->seqno = ast_random() & 0xffff;
01864    ast_set_flag(rtp, FLAG_HAS_DTMF);
01865 
01866    return;
01867 }

struct ast_rtp* ast_rtp_new_with_bindaddr ( struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode,
struct in_addr  in 
) [read]

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

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Definition at line 2781 of file rtp.c.

Referenced by load_module().

02782 {
02783    struct ast_rtp_protocol *cur;
02784 
02785    AST_LIST_LOCK(&protos);
02786    AST_LIST_TRAVERSE(&protos, cur, list) {   
02787       if (!strcmp(cur->type, proto->type)) {
02788          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02789          AST_LIST_UNLOCK(&protos);
02790          return -1;
02791       }
02792    }
02793    AST_LIST_INSERT_HEAD(&protos, proto, list);
02794    AST_LIST_UNLOCK(&protos);
02795    
02796    return 0;
02797 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2773 of file rtp.c.

Referenced by load_module(), and unload_module().

02774 {
02775    AST_LIST_LOCK(&protos);
02776    AST_LIST_REMOVE(&protos, proto, list);
02777    AST_LIST_UNLOCK(&protos);
02778 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1390 of file rtp.c.

Referenced by process_sdp().

01391 {
01392    int i;
01393 
01394    if (!rtp)
01395       return;
01396 
01397    ast_mutex_lock(&rtp->bridge_lock);
01398 
01399    for (i = 0; i < MAX_RTP_PT; ++i) {
01400       rtp->current_RTP_PT[i].isAstFormat = 0;
01401       rtp->current_RTP_PT[i].code = 0;
01402    }
01403 
01404    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01405    rtp->rtp_lookup_code_cache_code = 0;
01406    rtp->rtp_lookup_code_cache_result = 0;
01407 
01408    ast_mutex_unlock(&rtp->bridge_lock);
01409 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

Definition at line 1430 of file rtp.c.

Referenced by ast_rtp_make_compatible(), and process_sdp().

01431 {
01432    unsigned int i;
01433 
01434    ast_mutex_lock(&dest->bridge_lock);
01435    ast_mutex_lock(&src->bridge_lock);
01436 
01437    for (i=0; i < MAX_RTP_PT; ++i) {
01438       dest->current_RTP_PT[i].isAstFormat = 
01439          src->current_RTP_PT[i].isAstFormat;
01440       dest->current_RTP_PT[i].code = 
01441          src->current_RTP_PT[i].code; 
01442    }
01443    dest->rtp_lookup_code_cache_isAstFormat = 0;
01444    dest->rtp_lookup_code_cache_code = 0;
01445    dest->rtp_lookup_code_cache_result = 0;
01446 
01447    ast_mutex_unlock(&src->bridge_lock);
01448    ast_mutex_unlock(&dest->bridge_lock);
01449 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 1411 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr().

01412 {
01413    int i;
01414 
01415    ast_mutex_lock(&rtp->bridge_lock);
01416 
01417    /* Initialize to default payload types */
01418    for (i = 0; i < MAX_RTP_PT; ++i) {
01419       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01420       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
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 }

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

Definition at line 2574 of file rtp.c.

References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_frame::has_timing_info, 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_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, ast_rtp::them, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

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

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  )  [read]

Definition at line 1097 of file rtp.c.

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

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

int ast_rtp_reload ( void   ) 

Definition at line 3671 of file rtp.c.

Referenced by ast_rtp_init().

03672 {
03673    struct ast_config *cfg;
03674    const char *s;
03675 
03676    rtpstart = 5000;
03677    rtpend = 31000;
03678    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03679    cfg = ast_config_load("rtp.conf");
03680    if (cfg) {
03681       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03682          rtpstart = atoi(s);
03683          if (rtpstart < 1024)
03684             rtpstart = 1024;
03685          if (rtpstart > 65535)
03686             rtpstart = 65535;
03687       }
03688       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03689          rtpend = atoi(s);
03690          if (rtpend < 1024)
03691             rtpend = 1024;
03692          if (rtpend > 65535)
03693             rtpend = 65535;
03694       }
03695       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03696          rtcpinterval = atoi(s);
03697          if (rtcpinterval == 0)
03698             rtcpinterval = 0; /* Just so we're clear... it's zero */
03699          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03700             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03701          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03702             rtcpinterval = RTCP_MAX_INTERVALMS;
03703       }
03704       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03705 #ifdef SO_NO_CHECK
03706          if (ast_false(s))
03707             nochecksums = 1;
03708          else
03709             nochecksums = 0;
03710 #else
03711          if (ast_false(s))
03712             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03713 #endif
03714       }
03715       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03716          dtmftimeout = atoi(s);
03717          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03718             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03719                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03720             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03721          };
03722       }
03723       ast_config_destroy(cfg);
03724    }
03725    if (rtpstart >= rtpend) {
03726       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03727       rtpstart = 5000;
03728       rtpend = 31000;
03729    }
03730    if (option_verbose > 1)
03731       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03732    return 0;
03733 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2030 of file rtp.c.

02031 {
02032    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02033    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02034    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02035    rtp->lastts = 0;
02036    rtp->lastdigitts = 0;
02037    rtp->lastrxts = 0;
02038    rtp->lastividtimestamp = 0;
02039    rtp->lastovidtimestamp = 0;
02040    rtp->lasteventseqn = 0;
02041    rtp->lastevent = 0;
02042    rtp->lasttxformat = 0;
02043    rtp->lastrxformat = 0;
02044    rtp->dtmfcount = 0;
02045    rtp->dtmfsamples = 0;
02046    rtp->seqno = 0;
02047    rtp->rxseqno = 0;
02048 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2540 of file rtp.c.

Referenced by do_monitor().

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2140 of file rtp.c.

Referenced by oh323_digit_begin(), and sip_senddigit_begin().

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

Definition at line 2204 of file rtp.c.

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

Referenced by ast_rtp_read().

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2241 of file rtp.c.

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

Referenced by oh323_digit_end(), and sip_senddigit_end().

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

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 585 of file rtp.c.

Referenced by start_rtp().

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

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 580 of file rtp.c.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

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

Definition at line 1629 of file rtp.c.

Referenced by gtalk_newcall(), and process_sdp().

01630 {
01631    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01632       return; /* bogus payload type */
01633 
01634    ast_mutex_lock(&rtp->bridge_lock);
01635    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01636    ast_mutex_unlock(&rtp->bridge_lock);
01637 } 

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

Definition at line 1973 of file rtp.c.

Referenced by handle_open_receive_channel_ack_message(), process_sdp(), and setup_rtp_connection().

01974 {
01975    rtp->them.sin_port = them->sin_port;
01976    rtp->them.sin_addr = them->sin_addr;
01977    if (rtp->rtcp) {
01978       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
01979       rtp->rtcp->them.sin_addr = them->sin_addr;
01980    }
01981    rtp->rxseqno = 0;
01982 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 547 of file rtp.c.

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

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

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 553 of file rtp.c.

Referenced by create_addr_from_peer(), and sip_alloc().

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

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

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

Definition at line 1642 of file rtp.c.

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

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

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 541 of file rtp.c.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 534 of file rtp.c.

Referenced by handle_response_invite().

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

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

Definition at line 600 of file rtp.c.

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

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

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

Definition at line 605 of file rtp.c.

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

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

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 590 of file rtp.c.

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

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

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 610 of file rtp.c.

Referenced by gtalk_new().

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

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 1964 of file rtp.c.

Referenced by __oh323_rtp_create(), and sip_alloc().

01965 {
01966    int res;
01967 
01968    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
01969       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01970    return res;
01971 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Definition at line 2013 of file rtp.c.

Referenced by process_sdp(), setup_rtp_connection(), and stop_media_flows().

02014 {
02015    if (rtp->rtcp && rtp->rtcp->schedid > 0) {
02016       ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02017       rtp->rtcp->schedid = -1;
02018    }
02019 
02020    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02021    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02022    if (rtp->rtcp) {
02023       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02024       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02025    }
02026    
02027    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02028 }

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

Definition at line 402 of file rtp.c.

Referenced by gtalk_update_stun().

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

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2692 of file rtp.c.

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

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

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

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

Referenced by ast_rtp_bridge().

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

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

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

Referenced by ast_rtp_bridge().

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

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 1048 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, 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().

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

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

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

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

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

Definition at line 2120 of file rtp.c.

References ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

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

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

Get channel driver interface structure.

Definition at line 1452 of file rtp.c.

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

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

01453 {
01454    struct ast_rtp_protocol *cur = NULL;
01455 
01456    AST_LIST_LOCK(&protos);
01457    AST_LIST_TRAVERSE(&protos, cur, list) {
01458       if (cur->type == chan->tech->type)
01459          break;
01460    }
01461    AST_LIST_UNLOCK(&protos);
01462 
01463    return cur;
01464 }

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

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

Referenced by bridge_p2p_loop().

03046 {
03047    ast_channel_lock(chan);
03048 
03049    /* Remove the callback from the IO context */
03050    ast_io_remove(rtp->io, iod[0]);
03051 
03052    /* Restore file descriptors */
03053    chan->fds[0] = fds[0];
03054    ast_channel_unlock(chan);
03055 
03056    /* Restore callback mode if previously used */
03057    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03058       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03059 
03060    return 0;
03061 }

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

P2P RTP Callback.

Definition at line 3038 of file rtp.c.

Referenced by bridge_p2p_loop().

03039 {
03040    return 0;
03041 }

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

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

Referenced by bridge_p2p_loop().

03065 {
03066    ast_mutex_lock(&rtp0->bridge_lock);
03067    rtp0->bridged = rtp1;
03068    ast_mutex_unlock(&rtp0->bridge_lock);
03069 
03070    return;
03071 }

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

Definition at line 669 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Process RTP DTMF and events according to RFC 2833.

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

Parameters:
rtp 
data 
len 
seqno 
Returns:

Definition at line 708 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Process Comfort Noise RTP.

This is incomplete at the moment.

Definition at line 773 of file rtp.c.

References AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, f, FLAG_3389_WARNING, ast_frame::frametype, ast_rtp::lastrxformat, LOG_DEBUG, LOG_NOTICE, ast_frame::offset, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_read().

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

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

Definition at line 655 of file rtp.c.

References rtcpdebugaddr.

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

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

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

Definition at line 3468 of file rtp.c.

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

03468                                                          {
03469    if (argc != 2) {
03470       if (argc != 4)
03471          return RESULT_SHOWUSAGE;
03472       return rtcp_do_debug_ip(fd, argc, argv);
03473    }
03474    rtcpdebug = 1;
03475    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03476    ast_cli(fd, "RTCP Debugging Enabled\n");
03477    return RESULT_SUCCESS;
03478 }

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

Definition at line 3456 of file rtp.c.

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

03456                                                                     {
03457    if (argc != 3) {
03458       if (argc != 5)
03459          return RESULT_SHOWUSAGE;
03460       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03461    }
03462    rtcpdebug = 1;
03463    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03464    ast_cli(fd, "RTCP Debugging Enabled\n");
03465    return RESULT_SUCCESS;
03466 }

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

Definition at line 3413 of file rtp.c.

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

Referenced by rtcp_do_debug().

03414 {
03415    struct hostent *hp;
03416    struct ast_hostent ahp;
03417    int port = 0;
03418    char *p, *arg;
03419    if (argc != 4)
03420       return RESULT_SHOWUSAGE;
03421 
03422    arg = argv[3];
03423    p = strstr(arg, ":");
03424    if (p) {
03425       *p = '\0';
03426       p++;
03427       port = atoi(p);
03428    }
03429    hp = ast_gethostbyname(arg, &ahp);
03430    if (hp == NULL)
03431       return RESULT_SHOWUSAGE;
03432    rtcpdebugaddr.sin_family = AF_INET;
03433    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03434    rtcpdebugaddr.sin_port = htons(port);
03435    if (port == 0)
03436       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03437    else
03438       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03439    rtcpdebug = 1;
03440    return RESULT_SUCCESS;
03441 }

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

Definition at line 3383 of file rtp.c.

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

Referenced by rtcp_do_debug_deprecated().

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

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

Definition at line 3489 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03489                                                          {
03490    if (argc != 2) {
03491       return RESULT_SHOWUSAGE;
03492    }
03493    rtcpstats = 1;
03494    ast_cli(fd, "RTCP Stats Enabled\n");
03495    return RESULT_SUCCESS;
03496 }

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

Definition at line 3480 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03480                                                                     {
03481    if (argc != 3) {
03482       return RESULT_SHOWUSAGE;
03483    }
03484    rtcpstats = 1;
03485    ast_cli(fd, "RTCP Stats Enabled\n");
03486    return RESULT_SUCCESS;
03487 }

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

Definition at line 3516 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03517 {
03518    if (argc != 3)
03519       return RESULT_SHOWUSAGE;
03520    rtcpdebug = 0;
03521    ast_cli(fd,"RTCP Debugging Disabled\n");
03522    return RESULT_SUCCESS;
03523 }

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

Definition at line 3507 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03508 {
03509    if (argc != 4)
03510       return RESULT_SHOWUSAGE;
03511    rtcpdebug = 0;
03512    ast_cli(fd,"RTCP Debugging Disabled\n");
03513    return RESULT_SUCCESS;
03514 }

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

Definition at line 3534 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03535 {
03536    if (argc != 3)
03537       return RESULT_SHOWUSAGE;
03538    rtcpstats = 0;
03539    ast_cli(fd,"RTCP Stats Disabled\n");
03540    return RESULT_SUCCESS;
03541 }

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

Definition at line 3525 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03526 {
03527    if (argc != 4)
03528       return RESULT_SHOWUSAGE;
03529    rtcpstats = 0;
03530    ast_cli(fd,"RTCP Stats Disabled\n");
03531    return RESULT_SUCCESS;
03532 }

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

Definition at line 642 of file rtp.c.

References rtpdebugaddr.

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

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

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

Definition at line 3443 of file rtp.c.

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

03444 {
03445    if (argc != 2) {
03446       if (argc != 4)
03447          return RESULT_SHOWUSAGE;
03448       return rtp_do_debug_ip(fd, argc, argv);
03449    }
03450    rtpdebug = 1;
03451    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03452    ast_cli(fd, "RTP Debugging Enabled\n");
03453    return RESULT_SUCCESS;
03454 }

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

Definition at line 3353 of file rtp.c.

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

Referenced by rtp_do_debug().

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

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

Definition at line 3498 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03499 {
03500    if (argc != 3)
03501       return RESULT_SHOWUSAGE;
03502    rtpdebug = 0;
03503    ast_cli(fd,"RTP Debugging Disabled\n");
03504    return RESULT_SUCCESS;
03505 }

static int rtp_socket ( void   )  [static]

Definition at line 1812 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01813 {
01814    int s;
01815    long flags;
01816    s = socket(AF_INET, SOCK_DGRAM, 0);
01817    if (s > -1) {
01818       flags = fcntl(s, F_GETFL);
01819       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01820 #ifdef SO_NO_CHECK
01821       if (nochecksums)
01822          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01823 #endif
01824    }
01825    return s;
01826 }

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

Definition at line 810 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

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

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

Definition at line 615 of file rtp.c.

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

Referenced by process_cisco_dtmf(), and process_rfc2833().

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

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

Definition at line 299 of file rtp.c.

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

Referenced by stun_handle_packet(), and stun_process_attr().

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

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

Definition at line 3543 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03544 {
03545    if (argc != 2) {
03546       return RESULT_SHOWUSAGE;
03547    }
03548    stundebug = 1;
03549    ast_cli(fd, "STUN Debugging Enabled\n");
03550    return RESULT_SUCCESS;
03551 }

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

Definition at line 423 of file rtp.c.

References append_attr_address(), append_attr_string(), ast_log(), ast_verbose(), stun_attr::attr, stun_header::id, stun_header::ies, stun_attr::len, 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(), STUN_USERNAME, and stun_state::username.

Referenced by ast_rtp_read().

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

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

Definition at line 280 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

Definition at line 3553 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03554 {
03555    if (argc != 3)
03556       return RESULT_SHOWUSAGE;
03557    stundebug = 0;
03558    ast_cli(fd, "STUN Debugging Disabled\n");
03559    return RESULT_SUCCESS;
03560 }

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

Definition at line 333 of file rtp.c.

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

Referenced by stun_handle_packet().

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

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 390 of file rtp.c.

References ast_random(), and stun_header::id.

Referenced by ast_rtp_stun_request().

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

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

Definition at line 384 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Definition at line 502 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3629 of file rtp.c.

struct ast_cli_entry cli_rtp_no_debug_deprecated [static]

Initial value:

 {
   { "rtp", "no", "debug", NULL },
   rtp_no_debug, NULL,
        NULL }

Definition at line 3594 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 3604 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 3599 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 3609 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 3619 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 3614 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 3624 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 3562 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 3566 of file rtp.c.

struct stun_addr packed

struct stun_attr packed

struct stun_header packed

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

struct rtpPayloadType payloadType

Definition at line 1327 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 3578 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 3582 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 3590 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

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

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

Referenced by rtcp_debug_test_addr(), rtcp_do_debug(), rtcp_do_debug_deprecated(), rtcp_do_debug_ip(), and rtcp_do_debug_ip_deprecated().

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.

Referenced by rtp_debug_test_addr(), rtp_do_debug(), and rtp_do_debug_ip().

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

char stun_debug_usage[] [static]

Initial value:

  "Usage: stun debug\n"
  "       Enable STUN (Simple Traversal of UDP through NATs) debugging\n"

Definition at line 3570 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

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

Definition at line 3574 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1329 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1328 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(), parse_information(), parse_setup(), sla_load_config(), subscription_type2str(), and yyparse().


Generated on Wed Aug 15 01:25:31 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.3