Fri Nov 12 12:09:06 2010

Asterisk developer's documentation


rtp.c File Reference

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

#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <math.h>
#include "asterisk/rtp.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
Include dependency graph for rtp.c:

Go to the source code of this file.

Data Structures

struct  ast_rtcp
 Structure defining an RTCP session. More...
struct  ast_rtp
 Structure representing a RTP session. More...
struct  mimeType
struct  protos
 List of current sessions. More...
struct  rtp_red
struct  stun_addr
struct  stun_attr
struct  stun_header
struct  stun_state
 here we store credentials extracted from a message More...
struct  stun_trans_id
 STUN support code. More...

Defines

#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))
#define FLAG_3389_WARNING   (1 << 0)
#define FLAG_CALLBACK_MODE   (1 << 6)
#define FLAG_DTMF_COMPENSATE   (1 << 7)
#define FLAG_HAS_DTMF   (1 << 3)
#define FLAG_HAS_STUN   (1 << 8)
#define FLAG_NAT_ACTIVE   (3 << 1)
#define FLAG_NAT_INACTIVE   (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
#define FLAG_P2P_NEED_DTMF   (1 << 5)
#define FLAG_P2P_SENT_MARK   (1 << 4)
#define MAX_TIMESTAMP_SKEW   640
#define RTCP_DEFAULT_INTERVALMS   5000
#define RTCP_JITTER_FORMAT1
#define RTCP_JITTER_FORMAT2   "rxjitter=%f;"
#define RTCP_LOSS_FORMAT1
#define RTCP_LOSS_FORMAT2
#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 SQUARE(x)   ((x) * (x))
#define STUN_ACCEPT   (1)
#define STUN_BINDERR   0x0111
#define STUN_BINDREQ   0x0001
 STUN message types 'BIND' refers to transactions used to determine the externally visible addresses. 'SEC' refers to transactions used to establish a session key for subsequent requests. 'SEC' functionality is not supported here.
#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
 Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7fff).
#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

Typedefs

typedef int( stun_cb_f )(struct stun_attr *attr, void *arg)
 callback type to be invoked on stun responses.

Enumerations

enum  strict_rtp_state { STRICT_RTP_OPEN = 0, STRICT_RTP_LEARN, STRICT_RTP_CLOSED }

Functions

static double __ast_rtp_get_qos (struct ast_rtp *rtp, const char *qos, int *found)
static char * __ast_rtp_get_quality (struct ast_rtp *rtp)
static char * __ast_rtp_get_quality_jitter (struct ast_rtp *rtp)
static char * __ast_rtp_get_quality_loss (struct ast_rtp *rtp)
static char * __ast_rtp_get_quality_rtt (struct ast_rtp *rtp)
static int __ast_rtp_reload (int reload)
static void append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sock_in, int *len, int *left)
 append an address to an STUN message
static void append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
 append a string to an STUN message
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 (const void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (const void *data)
 Send RTCP recipient's report.
static int ast_rtcp_write_sr (const void *data)
 Send RTCP sender's report.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
enum ast_bridge_result ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
int ast_rtp_codec_getformat (int pt)
 get format from predefined dynamic payload format
struct ast_codec_prefast_rtp_codec_getpref (struct ast_rtp *rtp)
 Get codec preference.
void ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs)
 Set codec preference.
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_early_bridge (struct ast_channel *c0, struct ast_channel *c1)
 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)
int ast_rtp_get_qos (struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen)
 Get QOS stats on a RTP channel.
unsigned int ast_rtp_get_qosvalue (struct ast_rtp *rtp, enum ast_rtp_qos_vars value)
 Return RTP and RTCP QoS values.
char * ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype)
 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:.
unsigned int ast_rtp_lookup_sample_rate (int isAstFormat, int code)
 Get the sample rate associated with known RTP payload types.
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.
void ast_rtp_new_source (struct ast_rtp *rtp)
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)
 Write RTP packet with audio or video media frames into UDP packet.
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_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt)
 set potential alternate source for RTP media
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_constantssrc (struct ast_rtp *rtp)
 When changing sources, don't generate a new SSRC.
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
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Set payload type to a known MIME media type for a codec.
int ast_rtp_set_rtpmap_type_rate (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options, unsigned int sample_rate)
 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_set_vars (struct ast_channel *chan, struct ast_rtp *rtp)
 Set RTPAUDIOQOS(...) variables on a channel when it is being hung up.
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)
int ast_rtp_setqos (struct ast_rtp *rtp, int type_of_service, int class_of_service, char *desc)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
 send a STUN BIND request to the given destination. Optionally, add a username if specified.
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 remove setting from payload type list if the rtpmap header indicates an unknown media type
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
int ast_stun_request (int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
 Generic STUN request Send a generic stun request to the server specified, possibly waiting for a reply and filling the 'reply' field with the externally visible address. Note that in this case the request will be blocking. (Note, the interface may change slightly in the future).
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 *tp0, struct ast_rtp *tp1, 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 *when, struct ast_rtp *rtp, unsigned int timestamp, int mark)
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
static struct ast_rtp_protocolget_proto (struct ast_channel *chan)
 Get channel driver interface structure.
static char * handle_cli_rtcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtcp_set_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_stun_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static double normdev_compute (double normdev, double sample, unsigned int sample_count)
 Calculate normal deviation.
static int p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, 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 **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.
void red_buffer_t140 (struct ast_rtp *rtp, struct ast_frame *f)
 Buffer t140 from chan_sip.
static struct ast_framered_t140_to_red (struct rtp_red *red)
 Construct a redundant frame.
static int red_write (const void *data)
 Write t140 redundacy frame.
static int rtcp_debug_test_addr (struct sockaddr_in *addr)
static char * rtcp_do_debug_ip (struct ast_cli_args *a)
static void rtp_bridge_lock (struct ast_rtp *rtp)
static void rtp_bridge_unlock (struct ast_rtp *rtp)
static int rtp_debug_test_addr (struct sockaddr_in *addr)
static char * rtp_do_debug_ip (struct ast_cli_args *a)
static int rtp_get_rate (int subclass)
int rtp_red_init (struct ast_rtp *rtp, int ti, int *red_data_pt, int num_gen)
 Initialize t140 redundancy.
static int rtp_socket (const char *type)
 Open RTP or RTCP socket for a session. Print a message on failure.
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 double stddev_compute (double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
static const char * stun_attr2str (int msg)
 helper function to print attribute names
static int stun_get_mapped (struct stun_attr *attr, void *arg)
 Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_response when called from ast_stun_request.
static int stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
 handle an incoming STUN message.
static const char * stun_msg2str (int msg)
 helper function to print message names
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
static void stun_req_id (struct stun_header *req)
 helper function to generate a random request id
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
 wrapper to send an STUN message
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)

Variables

static struct ast_cli_entry cli_rtp []
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
static struct mimeType mimeTypes []
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 = 31000
static int rtpstart = 5000
static struct rtpPayloadType static_RTP_PT [MAX_RTP_PT]
 Mapping between Asterisk codecs and rtp payload types.
static int strictrtp
static int stundebug

Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

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

samples

Definition at line 67 of file rtp.c.

Referenced by __ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 209 of file rtp.c.

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 216 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 217 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)
#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 211 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 212 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 215 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 214 of file rtp.c.

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

#define MAX_TIMESTAMP_SKEW   640

Definition at line 51 of file rtp.c.

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 54 of file rtp.c.

#define RTCP_JITTER_FORMAT1
#define RTCP_JITTER_FORMAT2   "rxjitter=%f;"
#define RTCP_LOSS_FORMAT1
#define RTCP_LOSS_FORMAT2
Value:
"lost=%d;" \
   "expected=%d;"

Referenced by __ast_rtp_get_quality_loss().

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

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

Referenced by __ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 63 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 62 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

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

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

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

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 65 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 53 of file rtp.c.

Referenced by ast_rtp_read().

#define SQUARE (  )     ((x) * (x))

Referenced by stddev_compute().

#define STUN_ACCEPT   (1)

Definition at line 339 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 350 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

STUN message types 'BIND' refers to transactions used to determine the externally visible addresses. 'SEC' refers to transactions used to establish a session key for subsequent requests. 'SEC' functionality is not supported here.

Definition at line 348 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 349 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 360 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 362 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 366 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 338 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7fff).

Definition at line 358 of file rtp.c.

Referenced by stun_attr2str(), stun_get_mapped(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 365 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 364 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 368 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 359 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 353 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 351 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 352 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 361 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 367 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 363 of file rtp.c.

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


Typedef Documentation

typedef int( stun_cb_f)(struct stun_attr *attr, void *arg)

callback type to be invoked on stun responses.

Definition at line 500 of file rtp.c.


Enumeration Type Documentation

Enumerator:
STRICT_RTP_OPEN 
STRICT_RTP_LEARN 

No RTP packets should be dropped, all sources accepted

STRICT_RTP_CLOSED 

Accept next packet as source

Definition at line 85 of file rtp.c.

00085                       {
00086    STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
00087    STRICT_RTP_LEARN,    /*! Accept next packet as source */
00088    STRICT_RTP_CLOSED,   /*! Drop all RTP packets not coming from source that was learned */
00089 };


Function Documentation

static double __ast_rtp_get_qos ( struct ast_rtp rtp,
const char *  qos,
int *  found 
) [static]

Definition at line 2784 of file rtp.c.

References ast_rtcp::maxrtt, ast_rtcp::maxrxjitter, ast_rtcp::minrtt, ast_rtcp::minrxjitter, ast_rtcp::normdev_rxjitter, ast_rtcp::normdevrtt, ast_rtcp::reported_maxjitter, ast_rtcp::reported_minjitter, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_stdev_jitter, ast_rtp::rtcp, ast_rtcp::stdev_rxjitter, and ast_rtcp::stdevrtt.

Referenced by ast_rtp_get_qos().

02785 {
02786    *found = 1;
02787 
02788    if (!strcasecmp(qos, "remote_maxjitter"))
02789       return rtp->rtcp->reported_maxjitter * 1000.0;
02790    if (!strcasecmp(qos, "remote_minjitter"))
02791       return rtp->rtcp->reported_minjitter * 1000.0;
02792    if (!strcasecmp(qos, "remote_normdevjitter"))
02793       return rtp->rtcp->reported_normdev_jitter * 1000.0;
02794    if (!strcasecmp(qos, "remote_stdevjitter"))
02795       return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0;
02796 
02797    if (!strcasecmp(qos, "local_maxjitter"))
02798       return rtp->rtcp->maxrxjitter * 1000.0;
02799    if (!strcasecmp(qos, "local_minjitter"))
02800       return rtp->rtcp->minrxjitter * 1000.0;
02801    if (!strcasecmp(qos, "local_normdevjitter"))
02802       return rtp->rtcp->normdev_rxjitter * 1000.0;
02803    if (!strcasecmp(qos, "local_stdevjitter"))
02804       return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0;
02805 
02806    if (!strcasecmp(qos, "maxrtt"))
02807       return rtp->rtcp->maxrtt * 1000.0;
02808    if (!strcasecmp(qos, "minrtt"))
02809       return rtp->rtcp->minrtt * 1000.0;
02810    if (!strcasecmp(qos, "normdevrtt"))
02811       return rtp->rtcp->normdevrtt * 1000.0;
02812    if (!strcasecmp(qos, "stdevrtt"))
02813       return sqrt(rtp->rtcp->stdevrtt) * 1000.0;
02814 
02815    *found = 0;
02816 
02817    return 0.0;
02818 }

static char* __ast_rtp_get_quality ( struct ast_rtp rtp  )  [static]

Definition at line 2987 of file rtp.c.

References ast_rtcp::expected_prior, ast_rtcp::quality, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtcp_info, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by ast_rtp_get_quality().

02988 {
02989    /*
02990    *ssrc          our ssrc
02991    *themssrc      their ssrc
02992    *lp            lost packets
02993    *rxjitter      our calculated jitter(rx)
02994    *rxcount       no. received packets
02995    *txjitter      reported jitter of the other end
02996    *txcount       transmitted packets
02997    *rlp           remote lost packets
02998    *rtt           round trip time
02999    */ 
03000 
03001    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
03002       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
03003          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
03004          rtp->ssrc,
03005          rtp->themssrc,
03006          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
03007          rtp->rxjitter,
03008          rtp->rxcount,
03009          (double)rtp->rtcp->reported_jitter / 65536.0,
03010          rtp->txcount,
03011          rtp->rtcp->reported_lost,
03012          rtp->rtcp->rtt
03013       );
03014    } else {
03015       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;",
03016          rtp->ssrc,
03017          rtp->themssrc,
03018          rtp->rxjitter,
03019          rtp->rxcount,
03020          rtp->txcount
03021       );
03022    }
03023 
03024    return rtp->rtcp->quality;
03025 }

static char* __ast_rtp_get_quality_jitter ( struct ast_rtp rtp  )  [static]

Definition at line 2866 of file rtp.c.

References ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtcp::normdev_rxjitter, ast_rtcp::quality_jitter, ast_rtcp::reported_maxjitter, ast_rtcp::reported_minjitter, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_stdev_jitter, ast_rtp::rtcp, ast_rtcp::rtcp_info, RTCP_JITTER_FORMAT1, RTCP_JITTER_FORMAT2, ast_rtp::rxjitter, and ast_rtcp::stdev_rxjitter.

Referenced by ast_rtp_get_quality().

02867 {
02868    /*
02869    *ssrc          our ssrc
02870    *themssrc      their ssrc
02871    *lp            lost packets
02872    *rxjitter      our calculated jitter(rx)
02873    *rxcount       no. received packets
02874    *txjitter      reported jitter of the other end
02875    *txcount       transmitted packets
02876    *rlp           remote lost packets
02877    *rtt           round trip time
02878    */
02879 #define RTCP_JITTER_FORMAT1 \
02880    "minrxjitter=%f;" \
02881    "maxrxjitter=%f;" \
02882    "avgrxjitter=%f;" \
02883    "stdevrxjitter=%f;" \
02884    "reported_minjitter=%f;" \
02885    "reported_maxjitter=%f;" \
02886    "reported_avgjitter=%f;" \
02887    "reported_stdevjitter=%f;"
02888 
02889 #define RTCP_JITTER_FORMAT2 \
02890    "rxjitter=%f;"
02891 
02892    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02893       snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1,
02894          rtp->rtcp->minrxjitter,
02895          rtp->rtcp->maxrxjitter,
02896          rtp->rtcp->normdev_rxjitter,
02897          sqrt(rtp->rtcp->stdev_rxjitter),
02898          rtp->rtcp->reported_minjitter,
02899          rtp->rtcp->reported_maxjitter,
02900          rtp->rtcp->reported_normdev_jitter,
02901          sqrt(rtp->rtcp->reported_stdev_jitter)
02902       );
02903    } else {
02904       snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2,
02905          rtp->rxjitter
02906       );
02907    }
02908 
02909    return rtp->rtcp->quality_jitter;
02910 
02911 #undef RTCP_JITTER_FORMAT1
02912 #undef RTCP_JITTER_FORMAT2
02913 }

static char* __ast_rtp_get_quality_loss ( struct ast_rtp rtp  )  [static]

Definition at line 2915 of file rtp.c.

References ast_rtp::cycles, ast_rtp::lastrxseqno, ast_rtcp::maxrxlost, ast_rtcp::minrxlost, ast_rtcp::normdev_rxlost, ast_rtcp::quality_loss, ast_rtcp::reported_maxlost, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, ast_rtcp::rtcp_info, RTCP_LOSS_FORMAT1, RTCP_LOSS_FORMAT2, ast_rtp::rxcount, ast_rtp::seedrxseqno, and ast_rtcp::stdev_rxlost.

Referenced by ast_rtp_get_quality().

02916 {
02917    unsigned int lost;
02918    unsigned int extended;
02919    unsigned int expected;
02920    int fraction;
02921 
02922 #define RTCP_LOSS_FORMAT1 \
02923    "minrxlost=%f;" \
02924    "maxrxlost=%f;" \
02925    "avgrxlostr=%f;" \
02926    "stdevrxlost=%f;" \
02927    "reported_minlost=%f;" \
02928    "reported_maxlost=%f;" \
02929    "reported_avglost=%f;" \
02930    "reported_stdevlost=%f;"
02931 
02932 #define RTCP_LOSS_FORMAT2 \
02933    "lost=%d;" \
02934    "expected=%d;"
02935    
02936    if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) {
02937       snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1,
02938          rtp->rtcp->minrxlost,
02939          rtp->rtcp->maxrxlost,
02940          rtp->rtcp->normdev_rxlost,
02941          sqrt(rtp->rtcp->stdev_rxlost),
02942          rtp->rtcp->reported_minlost,
02943          rtp->rtcp->reported_maxlost,
02944          rtp->rtcp->reported_normdev_lost,
02945          sqrt(rtp->rtcp->reported_stdev_lost)
02946       );
02947    } else {
02948       extended = rtp->cycles + rtp->lastrxseqno;
02949       expected = extended - rtp->seedrxseqno + 1;
02950       if (rtp->rxcount > expected) 
02951          expected += rtp->rxcount - expected;
02952       lost = expected - rtp->rxcount;
02953 
02954       if (!expected || lost <= 0)
02955          fraction = 0;
02956       else
02957          fraction = (lost << 8) / expected;
02958 
02959       snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2,
02960          lost,
02961          expected
02962       );
02963    }
02964 
02965    return rtp->rtcp->quality_loss;
02966 
02967 #undef RTCP_LOSS_FORMAT1
02968 #undef RTCP_LOSS_FORMAT2
02969 }

static char* __ast_rtp_get_quality_rtt ( struct ast_rtp rtp  )  [static]

Definition at line 2971 of file rtp.c.

References ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtcp::normdevrtt, ast_rtcp::quality_rtt, ast_rtp::rtcp, ast_rtcp::rtcp_info, and ast_rtcp::stdevrtt.

Referenced by ast_rtp_get_quality().

02972 {
02973    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02974       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
02975          rtp->rtcp->minrtt,
02976          rtp->rtcp->maxrtt,
02977          rtp->rtcp->normdevrtt,
02978          sqrt(rtp->rtcp->stdevrtt)
02979       );
02980    } else {
02981       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available");
02982    }
02983 
02984    return rtp->rtcp->quality_rtt;
02985 }

static int __ast_rtp_reload ( int  reload  )  [static]

Definition at line 4739 of file rtp.c.

References ast_config_destroy(), ast_config_load2(), ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTMF_TIMEOUT, LOG_WARNING, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and STRICT_RTP_OPEN.

Referenced by ast_rtp_init(), and ast_rtp_reload().

04740 {
04741    struct ast_config *cfg;
04742    const char *s;
04743    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04744 
04745    cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
04746    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
04747       return 0;
04748    }
04749 
04750    rtpstart = 5000;
04751    rtpend = 31000;
04752    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04753    strictrtp = STRICT_RTP_OPEN;
04754    if (cfg) {
04755       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
04756          rtpstart = atoi(s);
04757          if (rtpstart < 1024)
04758             rtpstart = 1024;
04759          if (rtpstart > 65535)
04760             rtpstart = 65535;
04761       }
04762       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
04763          rtpend = atoi(s);
04764          if (rtpend < 1024)
04765             rtpend = 1024;
04766          if (rtpend > 65535)
04767             rtpend = 65535;
04768       }
04769       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
04770          rtcpinterval = atoi(s);
04771          if (rtcpinterval == 0)
04772             rtcpinterval = 0; /* Just so we're clear... it's zero */
04773          if (rtcpinterval < RTCP_MIN_INTERVALMS)
04774             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
04775          if (rtcpinterval > RTCP_MAX_INTERVALMS)
04776             rtcpinterval = RTCP_MAX_INTERVALMS;
04777       }
04778       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
04779 #ifdef SO_NO_CHECK
04780          if (ast_false(s))
04781             nochecksums = 1;
04782          else
04783             nochecksums = 0;
04784 #else
04785          if (ast_false(s))
04786             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
04787 #endif
04788       }
04789       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
04790          dtmftimeout = atoi(s);
04791          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
04792             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
04793                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
04794             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04795          };
04796       }
04797       if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
04798          strictrtp = ast_true(s);
04799       }
04800       ast_config_destroy(cfg);
04801    }
04802    if (rtpstart >= rtpend) {
04803       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
04804       rtpstart = 5000;
04805       rtpend = 31000;
04806    }
04807    ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
04808    return 0;
04809 }

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

append an address to an STUN message

Definition at line 461 of file rtp.c.

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

Referenced by stun_handle_packet().

00462 {
00463    int size = sizeof(**attr) + 8;
00464    struct stun_addr *addr;
00465    if (*left > size) {
00466       (*attr)->attr = htons(attrval);
00467       (*attr)->len = htons(8);
00468       addr = (struct stun_addr *)((*attr)->value);
00469       addr->unused = 0;
00470       addr->family = 0x01;
00471       addr->port = sock_in->sin_port;
00472       addr->addr = sock_in->sin_addr.s_addr;
00473       (*attr) = (struct stun_attr *)((*attr)->value + 8);
00474       *len += size;
00475       *left -= size;
00476    }
00477 }

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

append a string to an STUN message

Definition at line 447 of file rtp.c.

Referenced by ast_stun_request(), and stun_handle_packet().

00448 {
00449    int size = sizeof(**attr) + strlen(s);
00450    if (*left > size) {
00451       (*attr)->attr = htons(attrval);
00452       (*attr)->len = htons(strlen(s));
00453       memcpy((*attr)->value, s, strlen(s));
00454       (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
00455       *len += size;
00456       *left -= size;
00457    }
00458 }

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

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00736 {
00737    unsigned int interval;
00738    /*! \todo XXX Do a more reasonable calculation on this one
00739     * Look in RFC 3550 Section A.7 for an example*/
00740    interval = rtcpinterval;
00741    return interval;
00742 }

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 723 of file rtp.c.

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

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

00724 {
00725    if (rtp->rtcp)
00726       return rtp->rtcp->s;
00727    return -1;
00728 }

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

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 2496 of file rtp.c.

References ast_calloc, ast_free, rtp_socket(), ast_rtcp::s, ast_rtcp::schedid, ast_rtcp::them, and ast_rtcp::us.

Referenced by ast_rtp_new_with_bindaddr().

02497 {
02498    struct ast_rtcp *rtcp;
02499 
02500    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
02501       return NULL;
02502    rtcp->s = rtp_socket("RTCP");
02503    rtcp->us.sin_family = AF_INET;
02504    rtcp->them.sin_family = AF_INET;
02505    rtcp->schedid = -1;
02506 
02507    if (rtcp->s < 0) {
02508       ast_free(rtcp);
02509       return NULL;
02510    }
02511 
02512    return rtcp;
02513 }

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

Definition at line 1168 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_rtcp::altthem, ast_assert, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose, ast_frame::datalen, errno, EVENT_FLAG_REPORTING, ast_rtp::f, f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, normdev_compute(), ast_rtcp::normdevrtt, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_jitter_count, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtcp_info, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, stddev_compute(), ast_rtcp::stdevrtt, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().

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

01169 {
01170    socklen_t len;
01171    int position, i, packetwords;
01172    int res;
01173    struct sockaddr_in sock_in;
01174    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
01175    unsigned int *rtcpheader;
01176    int pt;
01177    struct timeval now;
01178    unsigned int length;
01179    int rc;
01180    double rttsec;
01181    uint64_t rtt = 0;
01182    unsigned int dlsr;
01183    unsigned int lsr;
01184    unsigned int msw;
01185    unsigned int lsw;
01186    unsigned int comp;
01187    struct ast_frame *f = &ast_null_frame;
01188    
01189    double reported_jitter;
01190    double reported_normdev_jitter_current;
01191    double normdevrtt_current;
01192    double reported_lost;
01193    double reported_normdev_lost_current;
01194 
01195    if (!rtp || !rtp->rtcp)
01196       return &ast_null_frame;
01197 
01198    len = sizeof(sock_in);
01199    
01200    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
01201                0, (struct sockaddr *)&sock_in, &len);
01202    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
01203    
01204    if (res < 0) {
01205       ast_assert(errno != EBADF);
01206       if (errno != EAGAIN) {
01207          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
01208          return NULL;
01209       }
01210       return &ast_null_frame;
01211    }
01212 
01213    packetwords = res / 4;
01214    
01215    if (rtp->nat) {
01216       /* Send to whoever sent to us */
01217       if (((rtp->rtcp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01218           (rtp->rtcp->them.sin_port != sock_in.sin_port)) && 
01219           ((rtp->rtcp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 
01220           (rtp->rtcp->altthem.sin_port != sock_in.sin_port))) {
01221          memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
01222          if (option_debug || rtpdebug)
01223             ast_debug(0, "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));
01224       }
01225    }
01226 
01227    ast_debug(1, "Got RTCP report of %d bytes\n", res);
01228 
01229    /* Process a compound packet */
01230    position = 0;
01231    while (position < packetwords) {
01232       i = position;
01233       length = ntohl(rtcpheader[i]);
01234       pt = (length & 0xff0000) >> 16;
01235       rc = (length & 0x1f000000) >> 24;
01236       length &= 0xffff;
01237  
01238       if ((i + length) > packetwords) {
01239          if (option_debug || rtpdebug)
01240             ast_log(LOG_DEBUG, "RTCP Read too short\n");
01241          return &ast_null_frame;
01242       }
01243       
01244       if (rtcp_debug_test_addr(&sock_in)) {
01245          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port));
01246          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
01247          ast_verbose("Reception reports: %d\n", rc);
01248          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
01249       }
01250  
01251       i += 2; /* Advance past header and ssrc */
01252       
01253       switch (pt) {
01254       case RTCP_PT_SR:
01255          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
01256          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
01257          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
01258          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
01259  
01260          if (rtcp_debug_test_addr(&sock_in)) {
01261             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
01262             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
01263             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
01264          }
01265          i += 5;
01266          if (rc < 1)
01267             break;
01268          /* Intentional fall through */
01269       case RTCP_PT_RR:
01270          /* Don't handle multiple reception reports (rc > 1) yet */
01271          /* Calculate RTT per RFC */
01272          gettimeofday(&now, NULL);
01273          timeval2ntp(now, &msw, &lsw);
01274          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
01275             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
01276             lsr = ntohl(rtcpheader[i + 4]);
01277             dlsr = ntohl(rtcpheader[i + 5]);
01278             rtt = comp - lsr - dlsr;
01279 
01280             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
01281                sess->ee_delay = (eedelay * 1000) / 65536; */
01282             if (rtt < 4294) {
01283                 rtt = (rtt * 1000000) >> 16;
01284             } else {
01285                 rtt = (rtt * 1000) >> 16;
01286                 rtt *= 1000;
01287             }
01288             rtt = rtt / 1000.;
01289             rttsec = rtt / 1000.;
01290             rtp->rtcp->rtt = rttsec;
01291 
01292             if (comp - dlsr >= lsr) {
01293                rtp->rtcp->accumulated_transit += rttsec;
01294 
01295                if (rtp->rtcp->rtt_count == 0) 
01296                   rtp->rtcp->minrtt = rttsec;
01297 
01298                if (rtp->rtcp->maxrtt<rttsec)
01299                   rtp->rtcp->maxrtt = rttsec;
01300 
01301                if (rtp->rtcp->minrtt>rttsec)
01302                   rtp->rtcp->minrtt = rttsec;
01303 
01304                normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
01305 
01306                rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
01307 
01308                rtp->rtcp->normdevrtt = normdevrtt_current;
01309 
01310                rtp->rtcp->rtt_count++;
01311             } else if (rtcp_debug_test_addr(&sock_in)) {
01312                ast_verbose("Internal RTCP NTP clock skew detected: "
01313                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
01314                         "diff=%d\n",
01315                         lsr, comp, dlsr, dlsr / 65536,
01316                         (dlsr % 65536) * 1000 / 65536,
01317                         dlsr - (comp - lsr));
01318             }
01319          }
01320 
01321          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01322          reported_jitter = (double) rtp->rtcp->reported_jitter;
01323 
01324          if (rtp->rtcp->reported_jitter_count == 0) 
01325             rtp->rtcp->reported_minjitter = reported_jitter;
01326 
01327          if (reported_jitter < rtp->rtcp->reported_minjitter) 
01328             rtp->rtcp->reported_minjitter = reported_jitter;
01329 
01330          if (reported_jitter > rtp->rtcp->reported_maxjitter) 
01331             rtp->rtcp->reported_maxjitter = reported_jitter;
01332 
01333          reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
01334 
01335          rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
01336 
01337          rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
01338 
01339          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01340 
01341          reported_lost = (double) rtp->rtcp->reported_lost;
01342 
01343          /* using same counter as for jitter */
01344          if (rtp->rtcp->reported_jitter_count == 0)
01345             rtp->rtcp->reported_minlost = reported_lost;
01346 
01347          if (reported_lost < rtp->rtcp->reported_minlost)
01348             rtp->rtcp->reported_minlost = reported_lost;
01349 
01350          if (reported_lost > rtp->rtcp->reported_maxlost) 
01351             rtp->rtcp->reported_maxlost = reported_lost;
01352 
01353          reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
01354 
01355          rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
01356 
01357          rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
01358 
01359          rtp->rtcp->reported_jitter_count++;
01360 
01361          if (rtcp_debug_test_addr(&sock_in)) {
01362             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01363             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01364             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01365             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01366             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01367             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01368             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01369             if (rtt)
01370                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
01371          }
01372 
01373          if (rtt) {
01374             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01375                             "PT: %d(%s)\r\n"
01376                             "ReceptionReports: %d\r\n"
01377                             "SenderSSRC: %u\r\n"
01378                             "FractionLost: %ld\r\n"
01379                             "PacketsLost: %d\r\n"
01380                             "HighestSequence: %ld\r\n"
01381                             "SequenceNumberCycles: %ld\r\n"
01382                             "IAJitter: %u\r\n"
01383                             "LastSR: %lu.%010lu\r\n"
01384                             "DLSR: %4.4f(sec)\r\n"
01385                             "RTT: %llu(sec)\r\n",
01386                             ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
01387                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01388                             rc,
01389                             rtcpheader[i + 1],
01390                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01391                             rtp->rtcp->reported_lost,
01392                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01393                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01394                             rtp->rtcp->reported_jitter,
01395                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01396                             ntohl(rtcpheader[i + 5])/65536.0,
01397                             (unsigned long long)rtt);
01398          } else {
01399             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01400                             "PT: %d(%s)\r\n"
01401                             "ReceptionReports: %d\r\n"
01402                             "SenderSSRC: %u\r\n"
01403                             "FractionLost: %ld\r\n"
01404                             "PacketsLost: %d\r\n"
01405                             "HighestSequence: %ld\r\n"
01406                             "SequenceNumberCycles: %ld\r\n"
01407                             "IAJitter: %u\r\n"
01408                             "LastSR: %lu.%010lu\r\n"
01409                             "DLSR: %4.4f(sec)\r\n",
01410                             ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
01411                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01412                             rc,
01413                             rtcpheader[i + 1],
01414                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01415                             rtp->rtcp->reported_lost,
01416                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01417                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01418                             rtp->rtcp->reported_jitter,
01419                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
01420                             ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01421                             ntohl(rtcpheader[i + 5])/65536.0);
01422          }
01423          break;
01424       case RTCP_PT_FUR:
01425          if (rtcp_debug_test_addr(&sock_in))
01426             ast_verbose("Received an RTCP Fast Update Request\n");
01427          rtp->f.frametype = AST_FRAME_CONTROL;
01428          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
01429          rtp->f.datalen = 0;
01430          rtp->f.samples = 0;
01431          rtp->f.mallocd = 0;
01432          rtp->f.src = "RTP";
01433          f = &rtp->f;
01434          break;
01435       case RTCP_PT_SDES:
01436          if (rtcp_debug_test_addr(&sock_in))
01437             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01438          break;
01439       case RTCP_PT_BYE:
01440          if (rtcp_debug_test_addr(&sock_in))
01441             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01442          break;
01443       default:
01444          ast_debug(1, "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));
01445          break;
01446       }
01447       position += (length + 1);
01448    }
01449    rtp->rtcp->rtcp_info = 1;  
01450    return f;
01451 }

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

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

03300 {
03301    struct ast_rtp *rtp = data;
03302    int res;
03303 
03304    rtp->rtcp->sendfur = 1;
03305    res = ast_rtcp_write(data);
03306    
03307    return res;
03308 }

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

Write and RTCP packet to the far end.

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

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

03558 {
03559    struct ast_rtp *rtp = (struct ast_rtp *)data;
03560    int res;
03561    
03562    if (!rtp || !rtp->rtcp)
03563       return 0;
03564 
03565    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
03566       res = ast_rtcp_write_sr(data);
03567    else
03568       res = ast_rtcp_write_rr(data);
03569    
03570    return res;
03571 }

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

Send RTCP recipient's report.

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

Definition at line 3444 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose, ast_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, len(), LOG_ERROR, ast_rtcp::maxrxlost, ast_rtcp::minrxlost, normdev_compute(), ast_rtcp::normdev_rxlost, 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::rxlost, ast_rtcp::rxlost_count, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtp::ssrc, stddev_compute(), ast_rtcp::stdev_rxlost, ast_rtcp::them, ast_rtcp::themrxlsr, and ast_rtp::themssrc.

Referenced by ast_rtcp_write().

03445 {
03446    struct ast_rtp *rtp = (struct ast_rtp *)data;
03447    int res;
03448    int len = 32;
03449    unsigned int lost;
03450    unsigned int extended;
03451    unsigned int expected;
03452    unsigned int expected_interval;
03453    unsigned int received_interval;
03454    int lost_interval;
03455    struct timeval now;
03456    unsigned int *rtcpheader;
03457    char bdata[1024];
03458    struct timeval dlsr;
03459    int fraction;
03460 
03461    double rxlost_current;
03462    
03463    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
03464       return 0;
03465      
03466    if (!rtp->rtcp->them.sin_addr.s_addr) {
03467       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
03468       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03469       return 0;
03470    }
03471 
03472    extended = rtp->cycles + rtp->lastrxseqno;
03473    expected = extended - rtp->seedrxseqno + 1;
03474    lost = expected - rtp->rxcount;
03475    expected_interval = expected - rtp->rtcp->expected_prior;
03476    rtp->rtcp->expected_prior = expected;
03477    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
03478    rtp->rtcp->received_prior = rtp->rxcount;
03479    lost_interval = expected_interval - received_interval;
03480 
03481    if (lost_interval <= 0)
03482       rtp->rtcp->rxlost = 0;
03483    else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
03484    if (rtp->rtcp->rxlost_count == 0)
03485       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
03486    if (lost_interval < rtp->rtcp->minrxlost) 
03487       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
03488    if (lost_interval > rtp->rtcp->maxrxlost) 
03489       rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
03490 
03491    rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
03492    rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
03493    rtp->rtcp->normdev_rxlost = rxlost_current;
03494    rtp->rtcp->rxlost_count++;
03495 
03496    if (expected_interval == 0 || lost_interval <= 0)
03497       fraction = 0;
03498    else
03499       fraction = (lost_interval << 8) / expected_interval;
03500    gettimeofday(&now, NULL);
03501    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
03502    rtcpheader = (unsigned int *)bdata;
03503    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
03504    rtcpheader[1] = htonl(rtp->ssrc);
03505    rtcpheader[2] = htonl(rtp->themssrc);
03506    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
03507    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
03508    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
03509    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
03510    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
03511 
03512    if (rtp->rtcp->sendfur) {
03513       rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
03514       rtcpheader[9] = htonl(rtp->ssrc);               /* Our SSRC */
03515       len += 8;
03516       rtp->rtcp->sendfur = 0;
03517    }
03518 
03519    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
03520    it can change mid call, and SDES can't) */
03521    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
03522    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
03523    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
03524    len += 12;
03525    
03526    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
03527 
03528    if (res < 0) {
03529       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
03530       /* Remove the scheduler */
03531       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03532       return 0;
03533    }
03534 
03535    rtp->rtcp->rr_count++;
03536 
03537    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
03538       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
03539          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 
03540          "  IA jitter: %.4f\n" 
03541          "  Their last SR: %u\n" 
03542          "  DLSR: %4.4f (sec)\n\n",
03543          ast_inet_ntoa(rtp->rtcp->them.sin_addr),
03544          ntohs(rtp->rtcp->them.sin_port),
03545          rtp->ssrc, rtp->themssrc, fraction, lost,
03546          rtp->rxjitter,
03547          rtp->rtcp->themrxlsr,
03548          (double)(ntohl(rtcpheader[7])/65536.0));
03549    }
03550 
03551    return res;
03552 }

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

Send RTCP sender's report.

Definition at line 3311 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose, ast_rtp::cycles, errno, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len(), LOG_ERROR, manager_event, 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().

03312 {
03313    struct ast_rtp *rtp = (struct ast_rtp *)data;
03314    int res;
03315    int len = 0;
03316    struct timeval now;
03317    unsigned int now_lsw;
03318    unsigned int now_msw;
03319    unsigned int *rtcpheader;
03320    unsigned int lost;
03321    unsigned int extended;
03322    unsigned int expected;
03323    unsigned int expected_interval;
03324    unsigned int received_interval;
03325    int lost_interval;
03326    int fraction;
03327    struct timeval dlsr;
03328    char bdata[512];
03329 
03330    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
03331    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
03332       return 0;
03333    
03334    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
03335       ast_verbose("RTCP SR transmission error, rtcp halted\n");
03336       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03337       return 0;
03338    }
03339 
03340    gettimeofday(&now, NULL);
03341    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
03342    rtcpheader = (unsigned int *)bdata;
03343    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
03344    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
03345    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
03346    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
03347    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
03348    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
03349    len += 28;
03350    
03351    extended = rtp->cycles + rtp->lastrxseqno;
03352    expected = extended - rtp->seedrxseqno + 1;
03353    if (rtp->rxcount > expected) 
03354       expected += rtp->rxcount - expected;
03355    lost = expected - rtp->rxcount;
03356    expected_interval = expected - rtp->rtcp->expected_prior;
03357    rtp->rtcp->expected_prior = expected;
03358    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
03359    rtp->rtcp->received_prior = rtp->rxcount;
03360    lost_interval = expected_interval - received_interval;
03361    if (expected_interval == 0 || lost_interval <= 0)
03362       fraction = 0;
03363    else
03364       fraction = (lost_interval << 8) / expected_interval;
03365    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
03366    rtcpheader[7] = htonl(rtp->themssrc);
03367    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
03368    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
03369    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
03370    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
03371    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
03372    len += 24;
03373    
03374    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
03375 
03376    if (rtp->rtcp->sendfur) {
03377       rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
03378       rtcpheader[14] = htonl(rtp->ssrc);               /* Our SSRC */
03379       len += 8;
03380       rtp->rtcp->sendfur = 0;
03381    }
03382    
03383    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 
03384    /* it can change mid call, and SDES can't) */
03385    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
03386    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
03387    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
03388    len += 12;
03389    
03390    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
03391    if (res < 0) {
03392       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));
03393       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03394       return 0;
03395    }
03396    
03397    /* FIXME Don't need to get a new one */
03398    gettimeofday(&rtp->rtcp->txlsr, NULL);
03399    rtp->rtcp->sr_count++;
03400 
03401    rtp->rtcp->lastsrtxcount = rtp->txcount;  
03402    
03403    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
03404       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
03405       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
03406       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
03407       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
03408       ast_verbose("  Sent packets: %u\n", rtp->txcount);
03409       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
03410       ast_verbose("  Report block:\n");
03411       ast_verbose("  Fraction lost: %u\n", fraction);
03412       ast_verbose("  Cumulative loss: %u\n", lost);
03413       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
03414       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
03415       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
03416    }
03417    manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n"
03418                    "OurSSRC: %u\r\n"
03419                    "SentNTP: %u.%010u\r\n"
03420                    "SentRTP: %u\r\n"
03421                    "SentPackets: %u\r\n"
03422                    "SentOctets: %u\r\n"
03423                    "ReportBlock:\r\n"
03424                    "FractionLost: %u\r\n"
03425                    "CumulativeLoss: %u\r\n"
03426                    "IAJitter: %.4f\r\n"
03427                    "TheirLastSR: %u\r\n"
03428                    "DLSR: %4.4f (sec)\r\n",
03429                    ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
03430                    rtp->ssrc,
03431                    (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
03432                    rtp->lastts,
03433                    rtp->txcount,
03434                    rtp->txoctetcount,
03435                    fraction,
03436                    lost,
03437                    rtp->rxjitter,
03438                    rtp->rtcp->themrxlsr,
03439                    (double)(ntohl(rtcpheader[12])/65536.0));
03440    return res;
03441 }

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

Referenced by process_sdp().

00495 {
00496    return sizeof(struct ast_rtp);
00497 }

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.

The RTP bridge.

Definition at line 4398 of file rtp.c.

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

04399 {
04400    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
04401    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
04402    struct ast_rtp *tp0 = NULL, *tp1 = NULL;  /* Text RTP channels */
04403    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
04404    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED, text_p0_res = AST_RTP_GET_FAILED;
04405    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED, text_p1_res = AST_RTP_GET_FAILED;
04406    enum ast_bridge_result res = AST_BRIDGE_FAILED;
04407    int codec0 = 0, codec1 = 0;
04408    void *pvt0 = NULL, *pvt1 = NULL;
04409 
04410    /* Lock channels */
04411    ast_channel_lock(c0);
04412    while (ast_channel_trylock(c1)) {
04413       ast_channel_unlock(c0);
04414       usleep(1);
04415       ast_channel_lock(c0);
04416    }
04417 
04418    /* Ensure neither channel got hungup during lock avoidance */
04419    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
04420       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
04421       ast_channel_unlock(c0);
04422       ast_channel_unlock(c1);
04423       return AST_BRIDGE_FAILED;
04424    }
04425       
04426    /* Find channel driver interfaces */
04427    if (!(pr0 = get_proto(c0))) {
04428       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
04429       ast_channel_unlock(c0);
04430       ast_channel_unlock(c1);
04431       return AST_BRIDGE_FAILED;
04432    }
04433    if (!(pr1 = get_proto(c1))) {
04434       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
04435       ast_channel_unlock(c0);
04436       ast_channel_unlock(c1);
04437       return AST_BRIDGE_FAILED;
04438    }
04439 
04440    /* Get channel specific interface structures */
04441    pvt0 = c0->tech_pvt;
04442    pvt1 = c1->tech_pvt;
04443 
04444    /* Get audio and video interface (if native bridge is possible) */
04445    audio_p0_res = pr0->get_rtp_info(c0, &p0);
04446    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04447    text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04448    audio_p1_res = pr1->get_rtp_info(c1, &p1);
04449    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04450    text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04451 
04452    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
04453    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
04454       audio_p0_res = AST_RTP_GET_FAILED;
04455    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
04456       audio_p1_res = AST_RTP_GET_FAILED;
04457 
04458    /* Check if a bridge is possible (partial/native) */
04459    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
04460       /* Somebody doesn't want to play... */
04461       ast_channel_unlock(c0);
04462       ast_channel_unlock(c1);
04463       return AST_BRIDGE_FAILED_NOWARN;
04464    }
04465 
04466    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
04467    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
04468       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
04469       audio_p0_res = AST_RTP_TRY_PARTIAL;
04470    }
04471 
04472    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
04473       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
04474       audio_p1_res = AST_RTP_TRY_PARTIAL;
04475    }
04476 
04477    /* If both sides are not using the same method of DTMF transmission 
04478     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
04479     * --------------------------------------------------
04480     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
04481     * |-----------|------------|-----------------------|
04482     * | Inband    | False      | True                  |
04483     * | RFC2833   | True       | True                  |
04484     * | SIP INFO  | False      | False                 |
04485     * --------------------------------------------------
04486     * However, if DTMF from both channels is being monitored by the core, then
04487     * we can still do packet-to-packet bridging, because passing through the 
04488     * core will handle DTMF mode translation.
04489     */
04490    if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
04491       (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
04492       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
04493          ast_channel_unlock(c0);
04494          ast_channel_unlock(c1);
04495          return AST_BRIDGE_FAILED_NOWARN;
04496       }
04497       audio_p0_res = AST_RTP_TRY_PARTIAL;
04498       audio_p1_res = AST_RTP_TRY_PARTIAL;
04499    }
04500 
04501    /* If we need to feed frames into the core don't do a P2P bridge */
04502    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
04503        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
04504       ast_channel_unlock(c0);
04505       ast_channel_unlock(c1);
04506       return AST_BRIDGE_FAILED_NOWARN;
04507    }
04508 
04509    /* Get codecs from both sides */
04510    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
04511    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
04512    if (codec0 && codec1 && !(codec0 & codec1)) {
04513       /* Hey, we can't do native bridging if both parties speak different codecs */
04514       ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
04515       ast_channel_unlock(c0);
04516       ast_channel_unlock(c1);
04517       return AST_BRIDGE_FAILED_NOWARN;
04518    }
04519 
04520    /* If either side can only do a partial bridge, then don't try for a true native bridge */
04521    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
04522       struct ast_format_list fmt0, fmt1;
04523 
04524       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
04525       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
04526          ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
04527          ast_channel_unlock(c0);
04528          ast_channel_unlock(c1);
04529          return AST_BRIDGE_FAILED_NOWARN;
04530       }
04531       /* They must also be using the same packetization */
04532       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
04533       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
04534       if (fmt0.cur_ms != fmt1.cur_ms) {
04535          ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
04536          ast_channel_unlock(c0);
04537          ast_channel_unlock(c1);
04538          return AST_BRIDGE_FAILED_NOWARN;
04539       }
04540 
04541       ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
04542       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
04543    } else {
04544       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04545       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
04546    }
04547 
04548    return res;
04549 }

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3779 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp_a_audio().

03780 {
03781    if (pt < 0 || pt >= MAX_RTP_PT)
03782       return 0; /* bogus payload type */
03783 
03784    if (static_RTP_PT[pt].isAstFormat)
03785       return static_RTP_PT[pt].code;
03786    else
03787       return 0;
03788 }

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

Get codec preference.

Definition at line 3774 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

03775 {
03776    return &rtp->pref;
03777 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

Definition at line 3728 of file rtp.c.

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

Referenced by __oh323_rtp_create(), check_peer_ok(), create_addr_from_peer(), gtalk_new(), jingle_new(), process_sdp_a_audio(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

03729 {
03730    struct ast_format_list current_format_old, current_format_new;
03731 
03732    /* if no packets have been sent through this session yet, then
03733     *  changing preferences does not require any extra work
03734     */
03735    if (rtp->lasttxformat == 0) {
03736       rtp->pref = *prefs;
03737       return;
03738    }
03739 
03740    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03741 
03742    rtp->pref = *prefs;
03743 
03744    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03745 
03746    /* if the framing desired for the current format has changed, we may have to create
03747     * or adjust the smoother for this session
03748     */
03749    if ((current_format_new.inc_ms != 0) &&
03750        (current_format_new.cur_ms != current_format_old.cur_ms)) {
03751       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
03752 
03753       if (rtp->smoother) {
03754          ast_smoother_reconfigure(rtp->smoother, new_size);
03755          if (option_debug) {
03756             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
03757          }
03758       } else {
03759          if (!(rtp->smoother = ast_smoother_new(new_size))) {
03760             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03761             return;
03762          }
03763          if (current_format_new.flags) {
03764             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
03765          }
03766          if (option_debug) {
03767             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03768          }
03769       }
03770    }
03771 
03772 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

Definition at line 3058 of file rtp.c.

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

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

03059 {
03060    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
03061       /*Print some info on the call here */
03062       ast_verbose("  RTP-stats\n");
03063       ast_verbose("* Our Receiver:\n");
03064       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
03065       ast_verbose("  Received packets: %u\n", rtp->rxcount);
03066       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
03067       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
03068       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
03069       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
03070       ast_verbose("* Our Sender:\n");
03071       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
03072       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
03073       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
03074       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
03075       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
03076       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
03077    }
03078 
03079    manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
03080                    "ReceivedPackets: %u\r\n"
03081                    "LostPackets: %u\r\n"
03082                    "Jitter: %.4f\r\n"
03083                    "Transit: %.4f\r\n"
03084                    "RRCount: %u\r\n",
03085                    rtp->themssrc,
03086                    rtp->rxcount,
03087                    rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
03088                    rtp->rxjitter,
03089                    rtp->rxtransit,
03090                    rtp->rtcp ? rtp->rtcp->rr_count : 0);
03091    manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
03092                    "SentPackets: %u\r\n"
03093                    "LostPackets: %u\r\n"
03094                    "Jitter: %u\r\n"
03095                    "SRCount: %u\r\n"
03096                    "RTT: %f\r\n",
03097                    rtp->ssrc,
03098                    rtp->txcount,
03099                    rtp->rtcp ? rtp->rtcp->reported_lost : 0,
03100                    rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
03101                    rtp->rtcp ? rtp->rtcp->sr_count : 0,
03102                    rtp->rtcp ? rtp->rtcp->rtt : 0);
03103    if (rtp->smoother)
03104       ast_smoother_free(rtp->smoother);
03105    if (rtp->ioid)
03106       ast_io_remove(rtp->io, rtp->ioid);
03107    if (rtp->s > -1)
03108       close(rtp->s);
03109    if (rtp->rtcp) {
03110       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03111       close(rtp->rtcp->s);
03112       ast_free(rtp->rtcp);
03113       rtp->rtcp=NULL;
03114    }
03115 #ifdef P2P_INTENSE
03116    ast_mutex_destroy(&rtp->bridge_lock);
03117 #endif
03118    ast_free(rtp);
03119 }

int ast_rtp_early_bridge ( struct ast_channel c0,
struct ast_channel c1 
)

If possible, create an early bridge directly between the devices without having to send a re-invite later.

Definition at line 2071 of file rtp.c.

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

02072 {
02073    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02074    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02075    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02076    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02077    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
02078    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
02079    int srccodec, destcodec, nat_active = 0;
02080 
02081    /* Lock channels */
02082    ast_channel_lock(c0);
02083    if (c1) {
02084       while (ast_channel_trylock(c1)) {
02085          ast_channel_unlock(c0);
02086          usleep(1);
02087          ast_channel_lock(c0);
02088       }
02089    }
02090 
02091    /* Find channel driver interfaces */
02092    destpr = get_proto(c0);
02093    if (c1)
02094       srcpr = get_proto(c1);
02095    if (!destpr) {
02096       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
02097       ast_channel_unlock(c0);
02098       if (c1)
02099          ast_channel_unlock(c1);
02100       return -1;
02101    }
02102    if (!srcpr) {
02103       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
02104       ast_channel_unlock(c0);
02105       if (c1)
02106          ast_channel_unlock(c1);
02107       return -1;
02108    }
02109 
02110    /* Get audio, video  and text interface (if native bridge is possible) */
02111    audio_dest_res = destpr->get_rtp_info(c0, &destp);
02112    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
02113    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
02114    if (srcpr) {
02115       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
02116       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
02117       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
02118    }
02119 
02120    /* Check if bridge is still possible (In SIP directmedia=no stops this, like NAT) */
02121    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
02122       /* Somebody doesn't want to play... */
02123       ast_channel_unlock(c0);
02124       if (c1)
02125          ast_channel_unlock(c1);
02126       return -1;
02127    }
02128    if (audio_src_res == AST_RTP_TRY_NATIVE && (video_src_res == AST_RTP_GET_FAILED || video_src_res == AST_RTP_TRY_NATIVE) && srcpr->get_codec)
02129       srccodec = srcpr->get_codec(c1);
02130    else
02131       srccodec = 0;
02132    if (audio_dest_res == AST_RTP_TRY_NATIVE && (video_dest_res == AST_RTP_GET_FAILED || video_dest_res == AST_RTP_TRY_NATIVE) && destpr->get_codec)
02133       destcodec = destpr->get_codec(c0);
02134    else
02135       destcodec = 0;
02136    /* Ensure we have at least one matching codec */
02137    if (srcp && !(srccodec & destcodec)) {
02138       ast_channel_unlock(c0);
02139       ast_channel_unlock(c1);
02140       return 0;
02141    }
02142    /* Consider empty media as non-existent */
02143    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
02144       srcp = NULL;
02145    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02146       nat_active = 1;
02147    /* Bridge media early */
02148    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
02149       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02150    ast_channel_unlock(c0);
02151    if (c1)
02152       ast_channel_unlock(c1);
02153    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02154    return 0;
02155 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 718 of file rtp.c.

References ast_rtp::s.

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

00719 {
00720    return rtp->s;
00721 }

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

Definition at line 2699 of file rtp.c.

References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by __sip_destroy(), ast_rtp_read(), and dialog_needdestroy().

02700 {
02701    struct ast_rtp *bridged = NULL;
02702 
02703    rtp_bridge_lock(rtp);
02704    bridged = rtp->bridged;
02705    rtp_bridge_unlock(rtp);
02706 
02707    return bridged;
02708 }

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

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().

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

02321 {
02322    int pt;
02323    
02324    rtp_bridge_lock(rtp);
02325    
02326    *astFormats = *nonAstFormats = 0;
02327    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02328       if (rtp->current_RTP_PT[pt].isAstFormat) {
02329          *astFormats |= rtp->current_RTP_PT[pt].code;
02330       } else {
02331          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02332       }
02333    }
02334 
02335    rtp_bridge_unlock(rtp);
02336 }

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

Definition at line 2681 of file rtp.c.

References ast_rtp::them.

Referenced by acf_channel_read(), add_sdp(), bridge_native_loop(), check_rtp_timeout(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), skinny_set_rtp_peer(), and transmit_modify_with_sdp().

02682 {
02683    if ((them->sin_family != AF_INET) ||
02684       (them->sin_port != rtp->them.sin_port) ||
02685       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02686       them->sin_family = AF_INET;
02687       them->sin_port = rtp->them.sin_port;
02688       them->sin_addr = rtp->them.sin_addr;
02689       return 1;
02690    }
02691    return 0;
02692 }

int ast_rtp_get_qos ( struct ast_rtp rtp,
const char *  qos,
char *  buf,
unsigned int  buflen 
)

Get QOS stats on a RTP channel.

Since:
1.6.1

Definition at line 2820 of file rtp.c.

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02821 {
02822    double value;
02823    int found;
02824 
02825    value = __ast_rtp_get_qos(rtp, qos, &found);
02826 
02827    if (!found)
02828       return -1;
02829 
02830    snprintf(buf, buflen, "%.0lf", value);
02831 
02832    return 0;
02833 }

unsigned int ast_rtp_get_qosvalue ( struct ast_rtp rtp,
enum ast_rtp_qos_vars  value 
)

Return RTP and RTCP QoS values.

Get QoS values from RTP and RTCP data (used in "sip show channelstats")

Definition at line 2754 of file rtp.c.

References ast_log(), AST_RTP_RTT, AST_RTP_RXCOUNT, AST_RTP_RXJITTER, AST_RTP_RXPLOSS, AST_RTP_TXCOUNT, AST_RTP_TXJITTER, AST_RTP_TXPLOSS, ast_rtcp::expected_prior, LOG_DEBUG, option_debug, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, and ast_rtp::txcount.

Referenced by show_chanstats_cb().

02755 {
02756    if (rtp == NULL) {
02757       if (option_debug > 1)
02758          ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
02759       return 0;
02760    }
02761    if (option_debug > 1 && rtp->rtcp == NULL) {
02762       ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
02763    }
02764 
02765    switch (value) {
02766    case AST_RTP_TXCOUNT:
02767       return (unsigned int) rtp->txcount;
02768    case AST_RTP_RXCOUNT:
02769       return (unsigned int) rtp->rxcount;
02770    case AST_RTP_TXJITTER:
02771       return (unsigned int) (rtp->rxjitter * 1000.0);
02772    case AST_RTP_RXJITTER:
02773       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
02774    case AST_RTP_RXPLOSS:
02775       return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
02776    case AST_RTP_TXPLOSS:
02777       return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
02778    case AST_RTP_RTT:
02779       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
02780    }
02781    return 0;   /* To make the compiler happy */
02782 }

char* ast_rtp_get_quality ( struct ast_rtp rtp,
struct ast_rtp_quality qual,
enum ast_rtp_quality_type  qtype 
)

Return RTCP quality string.

Parameters:
rtp An rtp structure to get qos information about.
qual An (optional) rtp quality structure that will be filled with the quality information described in the ast_rtp_quality structure. This structure is not dependent on any qtype, so a call for any type of information would yield the same results because ast_rtp_quality is not a data type specific to any qos type.
qtype The quality type you'd like, default should be RTPQOS_SUMMARY which returns basic information about the call. The return from RTPQOS_SUMMARY is basically ast_rtp_quality in a string. The other types are RTPQOS_JITTER, RTPQOS_LOSS and RTPQOS_RTT which will return more specific statistics.
Version:
1.6.1 added qtype parameter

Definition at line 3027 of file rtp.c.

References __ast_rtp_get_quality(), __ast_rtp_get_quality_jitter(), __ast_rtp_get_quality_loss(), __ast_rtp_get_quality_rtt(), ast_rtcp::expected_prior, ast_rtp_quality::local_count, ast_rtp_quality::local_jitter, ast_rtp_quality::local_lostpackets, ast_rtp_quality::local_ssrc, ast_rtcp::received_prior, ast_rtp_quality::remote_count, ast_rtp_quality::remote_jitter, ast_rtp_quality::remote_lostpackets, ast_rtp_quality::remote_ssrc, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, RTPQOS_SUMMARY, ast_rtcp::rtt, ast_rtp_quality::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.

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

03028 {
03029    if (qual && rtp) {
03030       qual->local_ssrc   = rtp->ssrc;
03031       qual->local_jitter = rtp->rxjitter;
03032       qual->local_count  = rtp->rxcount;
03033       qual->remote_ssrc  = rtp->themssrc;
03034       qual->remote_count = rtp->txcount;
03035 
03036       if (rtp->rtcp) {
03037          qual->local_lostpackets  = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
03038          qual->remote_lostpackets = rtp->rtcp->reported_lost;
03039          qual->remote_jitter      = rtp->rtcp->reported_jitter / 65536.0;
03040          qual->rtt                = rtp->rtcp->rtt;
03041       }
03042    }
03043 
03044    switch (qtype) {
03045    case RTPQOS_SUMMARY:
03046       return __ast_rtp_get_quality(rtp);
03047    case RTPQOS_JITTER:
03048       return __ast_rtp_get_quality_jitter(rtp);
03049    case RTPQOS_LOSS:
03050       return __ast_rtp_get_quality_loss(rtp);
03051    case RTPQOS_RTT:
03052       return __ast_rtp_get_quality_rtt(rtp);
03053    }
03054 
03055    return NULL;
03056 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 778 of file rtp.c.

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

Referenced by check_rtp_timeout().

00779 {
00780    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00781       return 0;
00782    return rtp->rtpholdtimeout;
00783 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 786 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00787 {
00788    return rtp->rtpkeepalive;
00789 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 770 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

00771 {
00772    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00773       return 0;
00774    return rtp->rtptimeout;
00775 }

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

Definition at line 806 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00807 {
00808    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00809 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4817 of file rtp.c.

References __ast_rtp_reload(), and ast_cli_register_multiple().

Referenced by main().

04818 {
04819    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04820    __ast_rtp_reload(0);
04821 }

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

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by add_codec_to_answer(), add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), bridge_p2p_rtp_write(), and start_rtp().

02361 {
02362    int pt = 0;
02363 
02364    rtp_bridge_lock(rtp);
02365 
02366    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02367       code == rtp->rtp_lookup_code_cache_code) {
02368       /* Use our cached mapping, to avoid the overhead of the loop below */
02369       pt = rtp->rtp_lookup_code_cache_result;
02370       rtp_bridge_unlock(rtp);
02371       return pt;
02372    }
02373 
02374    /* Check the dynamic list first */
02375    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02376       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02377          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02378          rtp->rtp_lookup_code_cache_code = code;
02379          rtp->rtp_lookup_code_cache_result = pt;
02380          rtp_bridge_unlock(rtp);
02381          return pt;
02382       }
02383    }
02384 
02385    /* Then the static list */
02386    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02387       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02388          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02389          rtp->rtp_lookup_code_cache_code = code;
02390          rtp->rtp_lookup_code_cache_result = pt;
02391          rtp_bridge_unlock(rtp);
02392          return pt;
02393       }
02394    }
02395 
02396    rtp_bridge_unlock(rtp);
02397 
02398    return -1;
02399 }

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

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

Referenced by process_sdp().

02435 {
02436    int format;
02437    unsigned len;
02438    char *end = buf;
02439    char *start = buf;
02440 
02441    if (!buf || !size)
02442       return NULL;
02443 
02444    snprintf(end, size, "0x%x (", capability);
02445 
02446    len = strlen(end);
02447    end += len;
02448    size -= len;
02449    start = end;
02450 
02451    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02452       if (capability & format) {
02453          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02454 
02455          snprintf(end, size, "%s|", name);
02456          len = strlen(end);
02457          end += len;
02458          size -= len;
02459       }
02460    }
02461 
02462    if (start == end)
02463       ast_copy_string(start, "nothing)", size); 
02464    else if (size > 1)
02465       *(end -1) = ')';
02466    
02467    return buf;
02468 }

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

References ARRAY_LEN, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::isAstFormat, mimeTypes, mimeType::payloadType, and mimeType::subtype.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().

02403 {
02404    unsigned int i;
02405 
02406    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02407       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02408          if (isAstFormat &&
02409              (code == AST_FORMAT_G726_AAL2) &&
02410              (options & AST_RTP_OPT_G726_NONSTANDARD))
02411             return "G726-32";
02412          else
02413             return mimeTypes[i].subtype;
02414       }
02415    }
02416 
02417    return "";
02418 }

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

References rtpPayloadType::code, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().

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

02339 {
02340    struct rtpPayloadType result;
02341 
02342    result.isAstFormat = result.code = 0;
02343 
02344    if (pt < 0 || pt >= MAX_RTP_PT) 
02345       return result; /* bogus payload type */
02346 
02347    /* Start with negotiated codecs */
02348    rtp_bridge_lock(rtp);
02349    result = rtp->current_RTP_PT[pt];
02350    rtp_bridge_unlock(rtp);
02351 
02352    /* If it doesn't exist, check our static RTP type list, just in case */
02353    if (!result.code) 
02354       result = static_RTP_PT[pt];
02355 
02356    return result;
02357 }

unsigned int ast_rtp_lookup_sample_rate ( int  isAstFormat,
int  code 
)

Get the sample rate associated with known RTP payload types.

Parameters:
isAstFormat True if the value in the 'code' parameter is an AST_FORMAT value
code Format code, either from AST_FORMAT list or from AST_RTP list
Returns:
the sample rate if the format was found, zero if it was not found

Definition at line 2420 of file rtp.c.

References ARRAY_LEN, rtpPayloadType::isAstFormat, mimeTypes, mimeType::payloadType, and mimeType::sample_rate.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_tcodec_to_sdp(), and add_vcodec_to_sdp().

02421 {
02422    unsigned int i;
02423 
02424    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02425       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02426          return mimeTypes[i].sample_rate;
02427       }
02428    }
02429 
02430    return 0;
02431 }

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

Definition at line 2157 of file rtp.c.

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

Referenced by dial_exec_full(), and do_forward().

02158 {
02159    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02160    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02161    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02162    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02163    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
02164    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED; 
02165    int srccodec, destcodec;
02166 
02167    /* Lock channels */
02168    ast_channel_lock(dest);
02169    while (ast_channel_trylock(src)) {
02170       ast_channel_unlock(dest);
02171       usleep(1);
02172       ast_channel_lock(dest);
02173    }
02174 
02175    /* Find channel driver interfaces */
02176    if (!(destpr = get_proto(dest))) {
02177       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
02178       ast_channel_unlock(dest);
02179       ast_channel_unlock(src);
02180       return 0;
02181    }
02182    if (!(srcpr = get_proto(src))) {
02183       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
02184       ast_channel_unlock(dest);
02185       ast_channel_unlock(src);
02186       return 0;
02187    }
02188 
02189    /* Get audio and video interface (if native bridge is possible) */
02190    audio_dest_res = destpr->get_rtp_info(dest, &destp);
02191    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
02192    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
02193    audio_src_res = srcpr->get_rtp_info(src, &srcp);
02194    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
02195    text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
02196 
02197    /* Ensure we have at least one matching codec */
02198    if (srcpr->get_codec)
02199       srccodec = srcpr->get_codec(src);
02200    else
02201       srccodec = 0;
02202    if (destpr->get_codec)
02203       destcodec = destpr->get_codec(dest);
02204    else
02205       destcodec = 0;
02206 
02207    /* Check if bridge is still possible (In SIP directmedia=no stops this, like NAT) */
02208    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE) || audio_src_res != AST_RTP_TRY_NATIVE || (video_src_res != AST_RTP_GET_FAILED && video_src_res != AST_RTP_TRY_NATIVE) || !(srccodec & destcodec)) {
02209       /* Somebody doesn't want to play... */
02210       ast_channel_unlock(dest);
02211       ast_channel_unlock(src);
02212       return 0;
02213    }
02214    ast_rtp_pt_copy(destp, srcp);
02215    if (vdestp && vsrcp)
02216       ast_rtp_pt_copy(vdestp, vsrcp);
02217    if (tdestp && tsrcp)
02218       ast_rtp_pt_copy(tdestp, tsrcp);
02219    if (media) {
02220       /* Bridge early */
02221       if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02222          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
02223    }
02224    ast_channel_unlock(dest);
02225    ast_channel_unlock(src);
02226    ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
02227    return 1;
02228 }

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

References ast_rtp_new_with_bindaddr().

02629 {
02630    struct in_addr ia;
02631 
02632    memset(&ia, 0, sizeof(ia));
02633    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02634 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

Definition at line 2519 of file rtp.c.

References ast_mutex_init(), ast_random(), ast_set_flag, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, STRICT_RTP_LEARN, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, ast_rtp::them, and ast_rtp::us.

Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().

02520 {
02521 #ifdef P2P_INTENSE
02522    ast_mutex_init(&rtp->bridge_lock);
02523 #endif
02524 
02525    rtp->them.sin_family = AF_INET;
02526    rtp->us.sin_family = AF_INET;
02527    rtp->ssrc = ast_random();
02528    rtp->seqno = ast_random() & 0xffff;
02529    ast_set_flag(rtp, FLAG_HAS_DTMF);
02530    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02531 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2646 of file rtp.c.

References ast_random(), ast_rtp::constantssrc, ast_rtp::set_marker_bit, and ast_rtp::ssrc.

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

02647 {
02648    if (rtp) {
02649       rtp->set_marker_bit = 1;
02650       if (!rtp->constantssrc) {
02651          rtp->ssrc = ast_random();
02652       }
02653    }
02654 }

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

References ast_calloc, ast_free, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, errno, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::us, and ast_rtp::us.

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

02534 {
02535    struct ast_rtp *rtp;
02536    int x;
02537    int startplace;
02538    
02539    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
02540       return NULL;
02541 
02542    ast_rtp_new_init(rtp);
02543 
02544    rtp->s = rtp_socket("RTP");
02545    if (rtp->s < 0)
02546       goto fail;
02547    if (sched && rtcpenable) {
02548       rtp->sched = sched;
02549       rtp->rtcp = ast_rtcp_new();
02550    }
02551    
02552    /*
02553     * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
02554     * Start from a random (even, by RTP spec) port number, and
02555     * iterate until success or no ports are available.
02556     * Note that the requirement of RTP port being even, or RTCP being the
02557     * next one, cannot be enforced in presence of a NAT box because the
02558     * mapping is not under our control.
02559     */
02560    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
02561    x = x & ~1;    /* make it an even number */
02562    startplace = x;      /* remember the starting point */
02563    /* this is constant across the loop */
02564    rtp->us.sin_addr = addr;
02565    if (rtp->rtcp)
02566       rtp->rtcp->us.sin_addr = addr;
02567    for (;;) {
02568       rtp->us.sin_port = htons(x);
02569       if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
02570          /* bind succeeded, if no rtcp then we are done */
02571          if (!rtp->rtcp)
02572             break;
02573          /* have rtcp, try to bind it */
02574          rtp->rtcp->us.sin_port = htons(x + 1);
02575          if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
02576             break;   /* success again, we are really done */
02577          /*
02578           * RTCP bind failed, so close and recreate the
02579           * already bound RTP socket for the next round.
02580           */
02581          close(rtp->s);
02582          rtp->s = rtp_socket("RTP");
02583          if (rtp->s < 0)
02584             goto fail;
02585       }
02586       /*
02587        * If we get here, there was an error in one of the bind()
02588        * calls, so make sure it is nothing unexpected.
02589        */
02590       if (errno != EADDRINUSE) {
02591          /* We got an error that wasn't expected, abort! */
02592          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02593          goto fail;
02594       }
02595       /*
02596        * One of the ports is in use. For the next iteration,
02597        * increment by two and handle wraparound.
02598        * If we reach the starting point, then declare failure.
02599        */
02600       x += 2;
02601       if (x > rtpend)
02602          x = (rtpstart + 1) & ~1;
02603       if (x == startplace) {
02604          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02605          goto fail;
02606       }
02607    }
02608    rtp->sched = sched;
02609    rtp->io = io;
02610    if (callbackmode) {
02611       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02612       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02613    }
02614    ast_rtp_pt_default(rtp);
02615    return rtp;
02616 
02617 fail:
02618    if (rtp->s >= 0)
02619       close(rtp->s);
02620    if (rtp->rtcp) {
02621       close(rtp->rtcp->s);
02622       ast_free(rtp->rtcp);
02623    }
02624    ast_free(rtp);
02625    return NULL;
02626 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Register an RTP channel client.

Definition at line 3896 of file rtp.c.

References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_rtp_protocol::list, LOG_WARNING, and ast_rtp_protocol::type.

Referenced by load_module().

03897 {
03898    struct ast_rtp_protocol *cur;
03899 
03900    AST_RWLIST_WRLOCK(&protos);
03901    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03902       if (!strcmp(cur->type, proto->type)) {
03903          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03904          AST_RWLIST_UNLOCK(&protos);
03905          return -1;
03906       }
03907    }
03908    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03909    AST_RWLIST_UNLOCK(&protos);
03910    
03911    return 0;
03912 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Unregister an RTP channel client.

Definition at line 3888 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03889 {
03890    AST_RWLIST_WRLOCK(&protos);
03891    AST_RWLIST_REMOVE(&protos, proto, list);
03892    AST_RWLIST_UNLOCK(&protos);
03893 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1995 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by gtalk_alloc(), and process_sdp().

01996 {
01997    int i;
01998 
01999    if (!rtp)
02000       return;
02001 
02002    rtp_bridge_lock(rtp);
02003 
02004    for (i = 0; i < MAX_RTP_PT; ++i) {
02005       rtp->current_RTP_PT[i].isAstFormat = 0;
02006       rtp->current_RTP_PT[i].code = 0;
02007    }
02008 
02009    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02010    rtp->rtp_lookup_code_cache_code = 0;
02011    rtp->rtp_lookup_code_cache_result = 0;
02012 
02013    rtp_bridge_unlock(rtp);
02014 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

Definition at line 2035 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by ast_rtp_make_compatible(), and process_sdp().

02036 {
02037    unsigned int i;
02038 
02039    rtp_bridge_lock(dest);
02040    rtp_bridge_lock(src);
02041 
02042    for (i = 0; i < MAX_RTP_PT; ++i) {
02043       dest->current_RTP_PT[i].isAstFormat = 
02044          src->current_RTP_PT[i].isAstFormat;
02045       dest->current_RTP_PT[i].code = 
02046          src->current_RTP_PT[i].code; 
02047    }
02048    dest->rtp_lookup_code_cache_isAstFormat = 0;
02049    dest->rtp_lookup_code_cache_code = 0;
02050    dest->rtp_lookup_code_cache_result = 0;
02051 
02052    rtp_bridge_unlock(src);
02053    rtp_bridge_unlock(dest);
02054 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 2016 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by ast_rtp_new_with_bindaddr().

02017 {
02018    int i;
02019 
02020    rtp_bridge_lock(rtp);
02021 
02022    /* Initialize to default payload types */
02023    for (i = 0; i < MAX_RTP_PT; ++i) {
02024       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
02025       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
02026    }
02027 
02028    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02029    rtp->rtp_lookup_code_cache_code = 0;
02030    rtp->rtp_lookup_code_cache_result = 0;
02031 
02032    rtp_bridge_unlock(rtp);
02033 }

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

Write RTP packet with audio or video media frames into UDP packet.

Definition at line 3609 of file rtp.c.

References ast_debug, AST_FORMAT_G722, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, ast_inet_ntoa(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_tvzero(), ast_verbose, calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_frame::frametype, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, ast_frame::ptr, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::set_marker_bit, ast_rtp::ssrc, ast_frame::subclass, ast_rtcp::them, ast_rtp::them, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

03610 {
03611    unsigned char *rtpheader;
03612    int hdrlen = 12;
03613    int res;
03614    unsigned int ms;
03615    int pred;
03616    int mark = 0;
03617    int rate = rtp_get_rate(f->subclass) / 1000;
03618 
03619    if (f->subclass == AST_FORMAT_G722) {
03620       f->samples /= 2;
03621    }
03622 
03623    if (rtp->sending_digit) {
03624       return 0;
03625    }
03626 
03627    ms = calc_txstamp(rtp, &f->delivery);
03628    /* Default prediction */
03629    if (f->frametype == AST_FRAME_VOICE) {
03630       pred = rtp->lastts + f->samples;
03631 
03632       /* Re-calculate last TS */
03633       rtp->lastts = rtp->lastts + ms * rate;
03634       if (ast_tvzero(f->delivery)) {
03635          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
03636             and if so, go with our prediction */
03637          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
03638             rtp->lastts = pred;
03639          else {
03640             ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
03641             mark = 1;
03642          }
03643       }
03644    } else if (f->frametype == AST_FRAME_VIDEO) {
03645       mark = f->subclass & 0x1;
03646       pred = rtp->lastovidtimestamp + f->samples;
03647       /* Re-calculate last TS */
03648       rtp->lastts = rtp->lastts + ms * 90;
03649       /* If it's close to our prediction, go for it */
03650       if (ast_tvzero(f->delivery)) {
03651          if (abs(rtp->lastts - pred) < 7200) {
03652             rtp->lastts = pred;
03653             rtp->lastovidtimestamp += f->samples;
03654          } else {
03655             ast_debug(3, "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);
03656             rtp->lastovidtimestamp = rtp->lastts;
03657          }
03658       }
03659    } else {
03660       pred = rtp->lastotexttimestamp + f->samples;
03661       /* Re-calculate last TS */
03662       rtp->lastts = rtp->lastts + ms;
03663       /* If it's close to our prediction, go for it */
03664       if (ast_tvzero(f->delivery)) {
03665          if (abs(rtp->lastts - pred) < 7200) {
03666             rtp->lastts = pred;
03667             rtp->lastotexttimestamp += f->samples;
03668          } else {
03669             ast_debug(3, "Difference is %d, ms is %d, pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, rtp->lastts, pred, f->samples);
03670             rtp->lastotexttimestamp = rtp->lastts;
03671          }
03672       }
03673    }
03674 
03675    /* If we have been explicitly told to set the marker bit do so */
03676    if (rtp->set_marker_bit) {
03677       mark = 1;
03678       rtp->set_marker_bit = 0;
03679    }
03680 
03681    /* If the timestamp for non-digit packets has moved beyond the timestamp
03682       for digits, update the digit timestamp.
03683    */
03684    if (rtp->lastts > rtp->lastdigitts)
03685       rtp->lastdigitts = rtp->lastts;
03686 
03687    if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
03688       rtp->lastts = f->ts * rate;
03689 
03690    /* Get a pointer to the header */
03691    rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
03692 
03693    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
03694    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
03695    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
03696 
03697    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03698       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03699       if (res < 0) {
03700          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
03701             ast_debug(1, "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));
03702          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
03703             /* Only give this error message once if we are not RTP debugging */
03704             if (option_debug || rtpdebug)
03705                ast_debug(0, "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));
03706             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
03707          }
03708       } else {
03709          rtp->txcount++;
03710          rtp->txoctetcount +=(res - hdrlen);
03711          
03712          /* Do not schedule RR if RTCP isn't run */
03713          if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
03714             rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
03715          }
03716       }
03717             
03718       if (rtp_debug_test_addr(&rtp->them))
03719          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03720                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
03721    }
03722 
03723    rtp->seqno++;
03724 
03725    return 0;
03726 }

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

Definition at line 1562 of file rtp.c.

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

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

01563 {
01564    int res;
01565    struct sockaddr_in sock_in;
01566    socklen_t len;
01567    unsigned int seqno;
01568    int version;
01569    int payloadtype;
01570    int hdrlen = 12;
01571    int padding;
01572    int mark;
01573    int ext;
01574    int cc;
01575    unsigned int ssrc;
01576    unsigned int timestamp;
01577    unsigned int *rtpheader;
01578    struct rtpPayloadType rtpPT;
01579    struct ast_rtp *bridged = NULL;
01580    int prev_seqno;
01581    
01582    /* If time is up, kill it */
01583    if (rtp->sending_digit)
01584       ast_rtp_senddigit_continuation(rtp);
01585 
01586    len = sizeof(sock_in);
01587    
01588    /* Cache where the header will go */
01589    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
01590                0, (struct sockaddr *)&sock_in, &len);
01591 
01592    /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */
01593    if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
01594       /* Copy over address that this packet was received on */
01595       memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address));
01596       /* Now move over to actually protecting the RTP port */
01597       rtp->strict_rtp_state = STRICT_RTP_CLOSED;
01598       ast_debug(1, "Learned remote address is %s:%d for strict RTP purposes, now protecting the port.\n", ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01599    } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
01600       /* If the address we previously learned doesn't match the address this packet came in on simply drop it */
01601       if ((rtp->strict_rtp_address.sin_addr.s_addr != sock_in.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sock_in.sin_port)) {
01602          ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01603          return &ast_null_frame;
01604       }
01605    }
01606 
01607    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
01608    if (res < 0) {
01609       ast_assert(errno != EBADF);
01610       if (errno != EAGAIN) {
01611          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up.\n", strerror(errno));
01612          return NULL;
01613       }
01614       return &ast_null_frame;
01615    }
01616    
01617    if (res < hdrlen) {
01618       ast_log(LOG_WARNING, "RTP Read too short\n");
01619       return &ast_null_frame;
01620    }
01621 
01622    /* Get fields */
01623    seqno = ntohl(rtpheader[0]);
01624 
01625    /* Check RTP version */
01626    version = (seqno & 0xC0000000) >> 30;
01627    if (!version) {
01628       /* If the two high bits are 0, this might be a
01629        * STUN message, so process it. stun_handle_packet()
01630        * answers to requests, and it returns STUN_ACCEPT
01631        * if the request is valid.
01632        */
01633       if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) &&
01634          (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
01635          memcpy(&rtp->them, &sock_in, sizeof(rtp->them));
01636       }
01637       return &ast_null_frame;
01638    }
01639 
01640 #if 0 /* Allow to receive RTP stream with closed transmission path */
01641    /* If we don't have the other side's address, then ignore this */
01642    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
01643       return &ast_null_frame;
01644 #endif
01645 
01646    /* Send to whoever send to us if NAT is turned on */
01647    if (rtp->nat) {
01648       if (((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01649           (rtp->them.sin_port != sock_in.sin_port)) && 
01650           ((rtp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01651           (rtp->altthem.sin_port != sock_in.sin_port))) {
01652          rtp->them = sock_in;
01653          if (rtp->rtcp) {
01654             int h = 0;
01655             memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
01656             h = ntohs(rtp->them.sin_port);
01657             rtp->rtcp->them.sin_port = htons(h + 1);
01658          }
01659          rtp->rxseqno = 0;
01660          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01661          if (option_debug || rtpdebug)
01662             ast_debug(0, "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));
01663       }
01664    }
01665 
01666    /* If we are bridged to another RTP stream, send direct */
01667    if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
01668       return &ast_null_frame;
01669 
01670    if (version != 2)
01671       return &ast_null_frame;
01672 
01673    payloadtype = (seqno & 0x7f0000) >> 16;
01674    padding = seqno & (1 << 29);
01675    mark = seqno & (1 << 23);
01676    ext = seqno & (1 << 28);
01677    cc = (seqno & 0xF000000) >> 24;
01678    seqno &= 0xffff;
01679    timestamp = ntohl(rtpheader[1]);
01680    ssrc = ntohl(rtpheader[2]);
01681    
01682    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
01683       if (option_debug || rtpdebug)
01684          ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
01685       mark = 1;
01686    }
01687 
01688    rtp->rxssrc = ssrc;
01689    
01690    if (padding) {
01691       /* Remove padding bytes */
01692       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01693    }
01694    
01695    if (cc) {
01696       /* CSRC fields present */
01697       hdrlen += cc*4;
01698    }
01699 
01700    if (ext) {
01701       /* RTP Extension present */
01702       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
01703       hdrlen += 4;
01704       if (option_debug) {
01705          int profile;
01706          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
01707          if (profile == 0x505a)
01708             ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
01709          else
01710             ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
01711       }
01712    }
01713 
01714    if (res < hdrlen) {
01715       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
01716       return &ast_null_frame;
01717    }
01718 
01719    rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
01720 
01721    if (rtp->rxcount==1) {
01722       /* This is the first RTP packet successfully received from source */
01723       rtp->seedrxseqno = seqno;
01724    }
01725 
01726    /* Do not schedule RR if RTCP isn't run */
01727    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
01728       /* Schedule transmission of Receiver Report */
01729       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01730    }
01731    if ((int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
01732       rtp->cycles += RTP_SEQ_MOD;
01733    
01734    prev_seqno = rtp->lastrxseqno;
01735 
01736    rtp->lastrxseqno = seqno;
01737    
01738    if (!rtp->themssrc)
01739       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
01740    
01741    if (rtp_debug_test_addr(&sock_in))
01742       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01743          ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
01744 
01745    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
01746    if (!rtpPT.isAstFormat) {
01747       struct ast_frame *f = NULL;
01748 
01749       /* This is special in-band data that's not one of our codecs */
01750       if (rtpPT.code == AST_RTP_DTMF) {
01751          /* It's special -- rfc2833 process it */
01752          if (rtp_debug_test_addr(&sock_in)) {
01753             unsigned char *data;
01754             unsigned int event;
01755             unsigned int event_end;
01756             unsigned int duration;
01757             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
01758             event = ntohl(*((unsigned int *)(data)));
01759             event >>= 24;
01760             event_end = ntohl(*((unsigned int *)(data)));
01761             event_end <<= 8;
01762             event_end >>= 24;
01763             duration = ntohl(*((unsigned int *)(data)));
01764             duration &= 0xFFFF;
01765             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(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
01766          }
01767          f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
01768       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
01769          /* It's really special -- process it the Cisco way */
01770          if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
01771             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01772             rtp->lastevent = seqno;
01773          }
01774       } else if (rtpPT.code == AST_RTP_CN) {
01775          /* Comfort Noise */
01776          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01777       } else {
01778          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
01779       }
01780       return f ? f : &ast_null_frame;
01781    }
01782    rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
01783    rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
01784 
01785    rtp->rxseqno = seqno;
01786 
01787    if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
01788       rtp->dtmf_timeout = 0;
01789 
01790       if (rtp->resp) {
01791          struct ast_frame *f;
01792          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01793          f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
01794          rtp->resp = 0;
01795          rtp->dtmf_timeout = rtp->dtmf_duration = 0;
01796          return f;
01797       }
01798    }
01799 
01800    /* Record received timestamp as last received now */
01801    rtp->lastrxts = timestamp;
01802 
01803    rtp->f.mallocd = 0;
01804    rtp->f.datalen = res - hdrlen;
01805    rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
01806    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
01807    rtp->f.seqno = seqno;
01808 
01809    if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
01810         unsigned char *data = rtp->f.data.ptr;
01811         
01812         memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
01813         rtp->f.datalen +=3;
01814         *data++ = 0xEF;
01815         *data++ = 0xBF;
01816         *data = 0xBD;
01817    }
01818  
01819    if (rtp->f.subclass == AST_FORMAT_T140RED) {
01820       unsigned char *data = rtp->f.data.ptr;
01821       unsigned char *header_end;
01822       int num_generations;
01823       int header_length;
01824       int length;
01825       int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
01826       int x;
01827 
01828       rtp->f.subclass = AST_FORMAT_T140;
01829       header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
01830       if (header_end == NULL) {
01831          return &ast_null_frame;
01832       }
01833       header_end++;
01834       
01835       header_length = header_end - data;
01836       num_generations = header_length / 4;
01837       length = header_length;
01838 
01839       if (!diff) {
01840          for (x = 0; x < num_generations; x++)
01841             length += data[x * 4 + 3];
01842          
01843          if (!(rtp->f.datalen - length))
01844             return &ast_null_frame;
01845          
01846          rtp->f.data.ptr += length;
01847          rtp->f.datalen -= length;
01848       } else if (diff > num_generations && diff < 10) {
01849          length -= 3;
01850          rtp->f.data.ptr += length;
01851          rtp->f.datalen -= length;
01852          
01853          data = rtp->f.data.ptr;
01854          *data++ = 0xEF;
01855          *data++ = 0xBF;
01856          *data = 0xBD;
01857       } else   {
01858          for ( x = 0; x < num_generations - diff; x++) 
01859             length += data[x * 4 + 3];
01860          
01861          rtp->f.data.ptr += length;
01862          rtp->f.datalen -= length;
01863       }
01864    }
01865 
01866    if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
01867       rtp->f.samples = ast_codec_get_samples(&rtp->f);
01868       if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
01869          ast_frame_byteswap_be(&rtp->f);
01870       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
01871       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
01872       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
01873       rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000);
01874       rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass) / 1000));
01875    } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
01876       /* Video -- samples is # of samples vs. 90000 */
01877       if (!rtp->lastividtimestamp)
01878          rtp->lastividtimestamp = timestamp;
01879       rtp->f.samples = timestamp - rtp->lastividtimestamp;
01880       rtp->lastividtimestamp = timestamp;
01881       rtp->f.delivery.tv_sec = 0;
01882       rtp->f.delivery.tv_usec = 0;
01883       /* Pass the RTP marker bit as bit 0 in the subclass field.
01884        * This is ok because subclass is actually a bitmask, and
01885        * the low bits represent audio formats, that are not
01886        * involved here since we deal with video.
01887        */
01888       if (mark)
01889          rtp->f.subclass |= 0x1;
01890    } else {
01891       /* TEXT -- samples is # of samples vs. 1000 */
01892       if (!rtp->lastitexttimestamp)
01893          rtp->lastitexttimestamp = timestamp;
01894       rtp->f.samples = timestamp - rtp->lastitexttimestamp;
01895       rtp->lastitexttimestamp = timestamp;
01896       rtp->f.delivery.tv_sec = 0;
01897       rtp->f.delivery.tv_usec = 0;
01898    }
01899    rtp->f.src = "RTP";
01900    return &rtp->f;
01901 }

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4811 of file rtp.c.

References __ast_rtp_reload().

04812 {
04813    return __ast_rtp_reload(1);
04814 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2731 of file rtp.c.

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

02732 {
02733    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02734    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02735    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02736    rtp->lastts = 0;
02737    rtp->lastdigitts = 0;
02738    rtp->lastrxts = 0;
02739    rtp->lastividtimestamp = 0;
02740    rtp->lastovidtimestamp = 0;
02741    rtp->lastitexttimestamp = 0;
02742    rtp->lastotexttimestamp = 0;
02743    rtp->lasteventseqn = 0;
02744    rtp->lastevent = 0;
02745    rtp->lasttxformat = 0;
02746    rtp->lastrxformat = 0;
02747    rtp->dtmf_timeout = 0;
02748    rtp->dtmfsamples = 0;
02749    rtp->seqno = 0;
02750    rtp->rxseqno = 0;
02751 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 3574 of file rtp.c.

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

Referenced by check_rtp_timeout().

03575 {
03576    unsigned int *rtpheader;
03577    int hdrlen = 12;
03578    int res;
03579    int payload;
03580    char data[256];
03581    level = 127 - (level & 0x7f);
03582    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03583 
03584    /* If we have no peer, return immediately */ 
03585    if (!rtp->them.sin_addr.s_addr)
03586       return 0;
03587 
03588    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03589 
03590    /* Get a pointer to the header */
03591    rtpheader = (unsigned int *)data;
03592    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03593    rtpheader[1] = htonl(rtp->lastts);
03594    rtpheader[2] = htonl(rtp->ssrc); 
03595    data[12] = level;
03596    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03597       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03598       if (res <0) 
03599          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));
03600       if (rtp_debug_test_addr(&rtp->them))
03601          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03602                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03603          
03604    }
03605    return 0;
03606 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 3141 of file rtp.c.

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

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

03142 {
03143    unsigned int *rtpheader;
03144    int hdrlen = 12, res = 0, i = 0, payload = 0;
03145    char data[256];
03146 
03147    if ((digit <= '9') && (digit >= '0'))
03148       digit -= '0';
03149    else if (digit == '*')
03150       digit = 10;
03151    else if (digit == '#')
03152       digit = 11;
03153    else if ((digit >= 'A') && (digit <= 'D'))
03154       digit = digit - 'A' + 12;
03155    else if ((digit >= 'a') && (digit <= 'd'))
03156       digit = digit - 'a' + 12;
03157    else {
03158       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03159       return 0;
03160    }
03161 
03162    /* If we have no peer, return immediately */ 
03163    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03164       return 0;
03165 
03166    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
03167 
03168    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03169    rtp->send_duration = 160;
03170    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
03171    
03172    /* Get a pointer to the header */
03173    rtpheader = (unsigned int *)data;
03174    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
03175    rtpheader[1] = htonl(rtp->lastdigitts);
03176    rtpheader[2] = htonl(rtp->ssrc); 
03177 
03178    for (i = 0; i < 2; i++) {
03179       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03180       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03181       if (res < 0) 
03182          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
03183             ast_inet_ntoa(rtp->them.sin_addr),
03184             ntohs(rtp->them.sin_port), strerror(errno));
03185       if (rtp_debug_test_addr(&rtp->them))
03186          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03187                 ast_inet_ntoa(rtp->them.sin_addr),
03188                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03189       /* Increment sequence number */
03190       rtp->seqno++;
03191       /* Increment duration */
03192       rtp->send_duration += 160;
03193       /* Clear marker bit and set seqno */
03194       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
03195    }
03196 
03197    /* Since we received a begin, we can safely store the digit and disable any compensation */
03198    rtp->sending_digit = 1;
03199    rtp->send_digit = digit;
03200    rtp->send_payload = payload;
03201 
03202    return 0;
03203 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

Definition at line 3206 of file rtp.c.

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

Referenced by ast_rtp_read().

03207 {
03208    unsigned int *rtpheader;
03209    int hdrlen = 12, res = 0;
03210    char data[256];
03211 
03212    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03213       return 0;
03214 
03215    /* Setup packet to send */
03216    rtpheader = (unsigned int *)data;
03217    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
03218    rtpheader[1] = htonl(rtp->lastdigitts);
03219    rtpheader[2] = htonl(rtp->ssrc);
03220    rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
03221    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
03222    
03223    /* Transmit */
03224    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03225    if (res < 0)
03226       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
03227          ast_inet_ntoa(rtp->them.sin_addr),
03228          ntohs(rtp->them.sin_port), strerror(errno));
03229    if (rtp_debug_test_addr(&rtp->them))
03230       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03231              ast_inet_ntoa(rtp->them.sin_addr),
03232              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03233 
03234    /* Increment sequence number */
03235    rtp->seqno++;
03236    /* Increment duration */
03237    rtp->send_duration += 160;
03238 
03239    return 0;
03240 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 3243 of file rtp.c.

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

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

03244 {
03245    unsigned int *rtpheader;
03246    int hdrlen = 12, res = 0, i = 0;
03247    char data[256];
03248    
03249    /* If no address, then bail out */
03250    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03251       return 0;
03252    
03253    if ((digit <= '9') && (digit >= '0'))
03254       digit -= '0';
03255    else if (digit == '*')
03256       digit = 10;
03257    else if (digit == '#')
03258       digit = 11;
03259    else if ((digit >= 'A') && (digit <= 'D'))
03260       digit = digit - 'A' + 12;
03261    else if ((digit >= 'a') && (digit <= 'd'))
03262       digit = digit - 'a' + 12;
03263    else {
03264       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03265       return 0;
03266    }
03267 
03268    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03269 
03270    rtpheader = (unsigned int *)data;
03271    rtpheader[1] = htonl(rtp->lastdigitts);
03272    rtpheader[2] = htonl(rtp->ssrc);
03273    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03274    /* Set end bit */
03275    rtpheader[3] |= htonl((1 << 23));
03276 
03277    /* Send 3 termination packets */
03278    for (i = 0; i < 3; i++) {
03279       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
03280       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03281       rtp->seqno++;
03282       if (res < 0)
03283          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
03284             ast_inet_ntoa(rtp->them.sin_addr),
03285             ntohs(rtp->them.sin_port), strerror(errno));
03286       if (rtp_debug_test_addr(&rtp->them))
03287          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03288                 ast_inet_ntoa(rtp->them.sin_addr),
03289                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03290    }
03291    rtp->lastts += rtp->send_duration;
03292    rtp->sending_digit = 0;
03293    rtp->send_digit = 0;
03294 
03295    return res;
03296 }

void ast_rtp_set_alt_peer ( struct ast_rtp rtp,
struct sockaddr_in *  alt 
)

set potential alternate source for RTP media

Since:
1.4.26 This function may be used to give the RTP stack a hint that there is a potential second source of media. One case where this is used is when the SIP stack receives a REINVITE to which it will be replying with a 491. In such a scenario, the IP and port information in the SDP of that REINVITE lets us know that we may receive media from that source/those sources even though the SIP transaction was unable to be completed successfully
Parameters:
rtp The RTP structure we wish to set up an alternate host/port on
alt The address information for the alternate media source
Return values:
void 

Definition at line 2671 of file rtp.c.

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

Referenced by handle_request_invite().

02672 {
02673    rtp->altthem.sin_port = alt->sin_port;
02674    rtp->altthem.sin_addr = alt->sin_addr;
02675    if (rtp->rtcp) {
02676       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02677       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02678    }
02679 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 796 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00797 {
00798    rtp->callback = callback;
00799 }

void ast_rtp_set_constantssrc ( struct ast_rtp rtp  ) 

When changing sources, don't generate a new SSRC.

Definition at line 2641 of file rtp.c.

References ast_rtp::constantssrc.

Referenced by create_addr_from_peer(), and handle_request_invite().

02642 {
02643    rtp->constantssrc = 1;
02644 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 791 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00792 {
00793    rtp->data = data;
00794 }

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

Activate payload type.

Definition at line 2234 of file rtp.c.

References ast_rtp::current_RTP_PT, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().

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

02235 {
02236    if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02237       return; /* bogus payload type */
02238 
02239    rtp_bridge_lock(rtp);
02240    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02241    rtp_bridge_unlock(rtp);
02242 } 

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

Definition at line 2656 of file rtp.c.

References ast_rtp::rtcp, ast_rtp::rxseqno, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, ast_rtcp::them, and ast_rtp::them.

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

02657 {
02658    rtp->them.sin_port = them->sin_port;
02659    rtp->them.sin_addr = them->sin_addr;
02660    if (rtp->rtcp) {
02661       int h = ntohs(them->sin_port);
02662       rtp->rtcp->them.sin_port = htons(h + 1);
02663       rtp->rtcp->them.sin_addr = them->sin_addr;
02664    }
02665    rtp->rxseqno = 0;
02666    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02667    if (strictrtp)
02668       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02669 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 758 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00759 {
00760    rtp->rtpholdtimeout = timeout;
00761 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 764 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00765 {
00766    rtp->rtpkeepalive = period;
00767 }

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

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

Parameters:
rtp RTP structure to modify
pt Payload type entry to modify
mimeType top-level MIME type of media stream (typically "audio", "video", "text", etc.)
mimeSubtype MIME subtype of media stream (typically a codec name)
options Zero or more flags from the ast_rtp_options enum

This function 'fills in' an entry in the list of possible formats for a media stream associated with an RTP structure.

Return values:
0 on success
-1 if the payload type is out of range
-2 if the mimeType/mimeSubtype combination was not found

Definition at line 2310 of file rtp.c.

References ast_rtp_set_rtpmap_type_rate().

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

02313 {
02314    return ast_rtp_set_rtpmap_type_rate(rtp, pt, mimeType, mimeSubtype, options, 0);
02315 }

int ast_rtp_set_rtpmap_type_rate ( struct ast_rtp rtp,
int  pt,
char *  mimeType,
char *  mimeSubtype,
enum ast_rtp_options  options,
unsigned int  sample_rate 
)

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

Set payload type to a known MIME media type for a codec with a specific sample rate.

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

Definition at line 2261 of file rtp.c.

References ARRAY_LEN, AST_FORMAT_G726, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, mimeTypes, mimeType::payloadType, rtp_bridge_lock(), rtp_bridge_unlock(), mimeType::sample_rate, mimeType::subtype, and mimeType::type.

Referenced by ast_rtp_set_rtpmap_type(), process_sdp_a_audio(), and process_sdp_a_video().

02265 {
02266    unsigned int i;
02267    int found = 0;
02268 
02269    if (pt < 0 || pt >= MAX_RTP_PT)
02270       return -1; /* bogus payload type */
02271 
02272    rtp_bridge_lock(rtp);
02273 
02274    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02275       const struct mimeType *t = &mimeTypes[i];
02276 
02277       if (strcasecmp(mimeSubtype, t->subtype)) {
02278          continue;
02279       }
02280 
02281       if (strcasecmp(mimeType, t->type)) {
02282          continue;
02283       }
02284 
02285       /* if both sample rates have been supplied, and they don't match,
02286          then this not a match; if one has not been supplied, then the
02287          rates are not compared */
02288       if (sample_rate && t->sample_rate &&
02289           (sample_rate != t->sample_rate)) {
02290          continue;
02291       }
02292 
02293       found = 1;
02294       rtp->current_RTP_PT[pt] = t->payloadType;
02295 
02296       if ((t->payloadType.code == AST_FORMAT_G726) &&
02297           t->payloadType.isAstFormat &&
02298           (options & AST_RTP_OPT_G726_NONSTANDARD)) {
02299          rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02300       }
02301 
02302       break;
02303    }
02304 
02305    rtp_bridge_unlock(rtp);
02306 
02307    return (found ? 0 : -2);
02308 }

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 752 of file rtp.c.

References ast_rtp::rtptimeout.

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

00753 {
00754    rtp->rtptimeout = timeout;
00755 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 745 of file rtp.c.

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

Referenced by handle_response_invite().

00746 {
00747    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00748    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00749 }

void ast_rtp_set_vars ( struct ast_channel chan,
struct ast_rtp rtp 
)

Set RTPAUDIOQOS(...) variables on a channel when it is being hung up.

Since:
1.6.1

Definition at line 2835 of file rtp.c.

References ast_bridged_channel(), ast_rtp_get_quality(), ast_channel::bridge, pbx_builtin_setvar_helper(), RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, and RTPQOS_SUMMARY.

Referenced by handle_request_bye(), and sip_hangup().

02835                                                                      {
02836    char *audioqos;
02837    char *audioqos_jitter;
02838    char *audioqos_loss;
02839    char *audioqos_rtt;
02840    struct ast_channel *bridge;
02841 
02842    if (!rtp || !chan)
02843       return;
02844 
02845    bridge = ast_bridged_channel(chan);
02846 
02847    audioqos        = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
02848    audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
02849    audioqos_loss   = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
02850    audioqos_rtt    = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
02851 
02852    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
02853    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
02854    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
02855    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
02856 
02857    if (!bridge)
02858       return;
02859 
02860    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
02861    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
02862    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
02863    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
02864 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

Definition at line 811 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_DTMF.

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

00812 {
00813    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00814 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

Definition at line 816 of file rtp.c.

References ast_set2_flag, and FLAG_DTMF_COMPENSATE.

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

00817 {
00818    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00819 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 801 of file rtp.c.

References ast_rtp::nat.

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

00802 {
00803    rtp->nat = nat;
00804 }

int ast_rtp_setqos ( struct ast_rtp rtp,
int  type_of_service,
int  class_of_service,
char *  desc 
)

Definition at line 2636 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

02637 {
02638    return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
02639 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 821 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00822 {
00823    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00824 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

Definition at line 2710 of file rtp.c.

References ast_clear_flag, AST_SCHED_DEL, FLAG_P2P_SENT_MARK, free, ast_rtp::red, ast_rtp::rtcp, ast_rtp::sched, rtp_red::schedid, ast_rtcp::schedid, ast_rtcp::them, and ast_rtp::them.

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

02711 {
02712    if (rtp->rtcp) {
02713       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02714    }
02715    if (rtp->red) {
02716       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02717       free(rtp->red);
02718       rtp->red = NULL;
02719    }
02720 
02721    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02722    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02723    if (rtp->rtcp) {
02724       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02725       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02726    }
02727    
02728    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02729 }

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

send a STUN BIND request to the given destination. Optionally, add a username if specified.

Send STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().

Definition at line 700 of file rtp.c.

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00701 {
00702    ast_stun_request(rtp->s, suggestion, username, NULL);
00703 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

remove setting from payload type list if the rtpmap header indicates an unknown media type

clear payload type

Definition at line 2246 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by process_sdp_a_audio(), and process_sdp_a_video().

02247 {
02248    if (pt < 0 || pt >= MAX_RTP_PT)
02249       return; /* bogus payload type */
02250 
02251    rtp_bridge_lock(rtp);
02252    rtp->current_RTP_PT[pt].isAstFormat = 0;
02253    rtp->current_RTP_PT[pt].code = 0;
02254    rtp_bridge_unlock(rtp);
02255 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Bug:
XXX this might never be free'd. Why do we do this?

Definition at line 3790 of file rtp.c.

References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G723_1, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, AST_FORMAT_SPEEX, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_rtp::pref, ast_frame::ptr, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

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

03791 {
03792    struct ast_frame *f;
03793    int codec;
03794    int hdrlen = 12;
03795    int subclass;
03796    
03797 
03798    /* If we have no peer, return immediately */ 
03799    if (!rtp->them.sin_addr.s_addr)
03800       return 0;
03801 
03802    /* If there is no data length, return immediately */
03803    if (!_f->datalen && !rtp->red)
03804       return 0;
03805    
03806    /* Make sure we have enough space for RTP header */
03807    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
03808       ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
03809       return -1;
03810    }
03811 
03812    if (rtp->red) {
03813       /* return 0; */
03814       /* no primary data or generations to send */
03815       if ((_f = red_t140_to_red(rtp->red)) == NULL) 
03816          return 0;
03817    }
03818 
03819    /* The bottom bit of a video subclass contains the marker bit */
03820    subclass = _f->subclass;
03821    if (_f->frametype == AST_FRAME_VIDEO)
03822       subclass &= ~0x1;
03823 
03824    codec = ast_rtp_lookup_code(rtp, 1, subclass);
03825    if (codec < 0) {
03826       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
03827       return -1;
03828    }
03829 
03830    if (rtp->lasttxformat != subclass) {
03831       /* New format, reset the smoother */
03832       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
03833       rtp->lasttxformat = subclass;
03834       if (rtp->smoother)
03835          ast_smoother_free(rtp->smoother);
03836       rtp->smoother = NULL;
03837    }
03838 
03839    if (!rtp->smoother) {
03840       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
03841 
03842       switch (subclass) {
03843       case AST_FORMAT_SPEEX:
03844       case AST_FORMAT_G723_1:
03845       case AST_FORMAT_SIREN7:
03846       case AST_FORMAT_SIREN14:
03847          /* these are all frame-based codecs and cannot be safely run through
03848             a smoother */
03849          break;
03850       default:
03851          if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
03852             if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
03853                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));
03854                return -1;
03855             }
03856             if (fmt.flags)
03857                ast_smoother_set_flags(rtp->smoother, fmt.flags);
03858             ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
03859          }
03860       }
03861    }
03862    if (rtp->smoother) {
03863       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03864          ast_smoother_feed_be(rtp->smoother, _f);
03865       } else {
03866          ast_smoother_feed(rtp->smoother, _f);
03867       }
03868 
03869       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
03870          ast_rtp_raw_write(rtp, f, codec);
03871       }
03872    } else {
03873       /* Don't buffer outgoing frames; send them one-per-packet: */
03874       if (_f->offset < hdrlen) 
03875          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
03876       else
03877          f = _f;
03878       if (f->data.ptr)
03879          ast_rtp_raw_write(rtp, f, codec);
03880       if (f != _f)
03881          ast_frfree(f);
03882    }
03883       
03884    return 0;
03885 }

int ast_stun_request ( int  s,
struct sockaddr_in *  dst,
const char *  username,
struct sockaddr_in *  answer 
)

Generic STUN request Send a generic stun request to the server specified, possibly waiting for a reply and filling the 'reply' field with the externally visible address. Note that in this case the request will be blocking. (Note, the interface may change slightly in the future).

Generic STUN request send a generic stun request to the server specified.

Parameters:
s the socket used to send the request
dst the address of the STUN server
username if non null, add the username in the request
answer if non null, the function waits for a response and puts here the externally visible address.
Returns:
0 on success, other values on error.

Definition at line 634 of file rtp.c.

References append_attr_string(), ast_log(), ast_select(), stun_header::ies, LOG_WARNING, stun_header::msglen, stun_header::msgtype, STUN_BINDREQ, stun_get_mapped(), stun_handle_packet(), stun_req_id(), stun_send(), and STUN_USERNAME.

Referenced by ast_rtp_stun_request(), ast_sip_ouraddrfor(), and reload_config().

00636 {
00637    struct stun_header *req;
00638    unsigned char reqdata[1024];
00639    int reqlen, reqleft;
00640    struct stun_attr *attr;
00641    int res = 0;
00642    int retry;
00643    
00644    req = (struct stun_header *)reqdata;
00645    stun_req_id(req);
00646    reqlen = 0;
00647    reqleft = sizeof(reqdata) - sizeof(struct stun_header);
00648    req->msgtype = 0;
00649    req->msglen = 0;
00650    attr = (struct stun_attr *)req->ies;
00651    if (username)
00652       append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00653    req->msglen = htons(reqlen);
00654    req->msgtype = htons(STUN_BINDREQ);
00655    for (retry = 0; retry < 3; retry++) {  /* XXX make retries configurable */
00656       /* send request, possibly wait for reply */
00657       unsigned char reply_buf[1024];
00658       fd_set rfds;
00659       struct timeval to = { 3, 0 }; /* timeout, make it configurable */
00660       struct sockaddr_in src;
00661       socklen_t srclen;
00662 
00663       res = stun_send(s, dst, req);
00664       if (res < 0) {
00665          ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
00666             retry, res);
00667          continue;
00668       }
00669       if (answer == NULL)
00670          break;
00671       FD_ZERO(&rfds);
00672       FD_SET(s, &rfds);
00673       res = ast_select(s + 1, &rfds, NULL, NULL, &to);
00674       if (res <= 0)  /* timeout or error */
00675          continue;
00676       memset(&src, '\0', sizeof(src));
00677       srclen = sizeof(src);
00678       /* XXX pass -1 in the size, because stun_handle_packet might
00679        * write past the end of the buffer.
00680        */
00681       res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
00682          0, (struct sockaddr *)&src, &srclen);
00683       if (res < 0) {
00684          ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
00685             retry, res);
00686          continue;
00687       }
00688       memset(answer, '\0', sizeof(struct sockaddr_in));
00689       stun_handle_packet(s, &src, reply_buf, res,
00690          stun_get_mapped, answer);
00691       res = 0; /* signal regular exit */
00692       break;
00693    }
00694    return res;
00695 }

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 tp0,
struct ast_rtp tp1,
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 3915 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_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate_data(), ast_inet_ntoa(), ast_log(), ast_poll_channel_add(), ast_poll_channel_del(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), ast_channel::audiohooks, ast_frame::data, ast_frame::datalen, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, inaddrcmp(), LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, ast_channel::name, ast_frame::ptr, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

03916 {
03917    struct ast_frame *fr = NULL;
03918    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03919    int oldcodec0 = codec0, oldcodec1 = codec1;
03920    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
03921    struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
03922    
03923    /* Set it up so audio goes directly between the two endpoints */
03924 
03925    /* Test the first channel */
03926    if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
03927       ast_rtp_get_peer(p1, &ac1);
03928       if (vp1)
03929          ast_rtp_get_peer(vp1, &vac1);
03930       if (tp1)
03931          ast_rtp_get_peer(tp1, &tac1);
03932    } else
03933       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
03934    
03935    /* Test the second channel */
03936    if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
03937       ast_rtp_get_peer(p0, &ac0);
03938       if (vp0)
03939          ast_rtp_get_peer(vp0, &vac0);
03940       if (tp0)
03941          ast_rtp_get_peer(tp0, &tac0);
03942    } else
03943       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
03944 
03945    /* Now we can unlock and move into our loop */
03946    ast_channel_unlock(c0);
03947    ast_channel_unlock(c1);
03948 
03949    ast_poll_channel_add(c0, c1);
03950 
03951    /* Throw our channels into the structure and enter the loop */
03952    cs[0] = c0;
03953    cs[1] = c1;
03954    cs[2] = NULL;
03955    for (;;) {
03956       /* Check if anything changed */
03957       if ((c0->tech_pvt != pvt0) ||
03958           (c1->tech_pvt != pvt1) ||
03959           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03960           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03961          ast_debug(1, "Oooh, something is weird, backing out\n");
03962          if (c0->tech_pvt == pvt0)
03963             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
03964                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03965          if (c1->tech_pvt == pvt1)
03966             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
03967                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03968          ast_poll_channel_del(c0, c1);
03969          return AST_BRIDGE_RETRY;
03970       }
03971 
03972       /* Check if they have changed their address */
03973       ast_rtp_get_peer(p1, &t1);
03974       if (vp1)
03975          ast_rtp_get_peer(vp1, &vt1);
03976       if (tp1)
03977          ast_rtp_get_peer(tp1, &tt1);
03978       if (pr1->get_codec)
03979          codec1 = pr1->get_codec(c1);
03980       ast_rtp_get_peer(p0, &t0);
03981       if (vp0)
03982          ast_rtp_get_peer(vp0, &vt0);
03983       if (tp0)
03984          ast_rtp_get_peer(tp0, &tt0);
03985       if (pr0->get_codec)
03986          codec0 = pr0->get_codec(c0);
03987       if ((inaddrcmp(&t1, &ac1)) ||
03988           (vp1 && inaddrcmp(&vt1, &vac1)) ||
03989           (tp1 && inaddrcmp(&tt1, &tac1)) ||
03990           (codec1 != oldcodec1)) {
03991          ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03992             c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
03993          ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
03994             c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
03995          ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n",
03996             c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1);
03997          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03998             c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
03999          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
04000             c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
04001          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
04002             c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1);
04003          if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, tt1.sin_addr.s_addr ? tp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
04004             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
04005          memcpy(&ac1, &t1, sizeof(ac1));
04006          memcpy(&vac1, &vt1, sizeof(vac1));
04007          memcpy(&tac1, &tt1, sizeof(tac1));
04008          oldcodec1 = codec1;
04009       }
04010       if ((inaddrcmp(&t0, &ac0)) ||
04011           (vp0 && inaddrcmp(&vt0, &vac0)) ||
04012           (tp0 && inaddrcmp(&tt0, &tac0)) ||
04013           (codec0 != oldcodec0)) {
04014          ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
04015             c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
04016          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
04017             c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
04018          if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, tt0.sin_addr.s_addr ? tp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
04019             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
04020          memcpy(&ac0, &t0, sizeof(ac0));
04021          memcpy(&vac0, &vt0, sizeof(vac0));
04022          memcpy(&tac0, &tt0, sizeof(tac0));
04023          oldcodec0 = codec0;
04024       }
04025 
04026       /* Wait for frame to come in on the channels */
04027       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
04028          if (!timeoutms) {
04029             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
04030                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
04031             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
04032                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
04033             return AST_BRIDGE_RETRY;
04034          }
04035          ast_debug(1, "Ooh, empty read...\n");
04036          if (ast_check_hangup(c0) || ast_check_hangup(c1))
04037             break;
04038          continue;
04039       }
04040       fr = ast_read(who);
04041       other = (who == c0) ? c1 : c0;
04042       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
04043              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
04044               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
04045          /* Break out of bridge */
04046          *fo = fr;
04047          *rc = who;
04048          ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup");
04049          if (c0->tech_pvt == pvt0)
04050             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
04051                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
04052          if (c1->tech_pvt == pvt1)
04053             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
04054                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
04055          ast_poll_channel_del(c0, c1);
04056          return AST_BRIDGE_COMPLETE;
04057       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
04058          if ((fr->subclass == AST_CONTROL_HOLD) ||
04059              (fr->subclass == AST_CONTROL_UNHOLD) ||
04060              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
04061              (fr->subclass == AST_CONTROL_SRCUPDATE) ||
04062              (fr->subclass == AST_CONTROL_T38_PARAMETERS)) {
04063             if (fr->subclass == AST_CONTROL_HOLD) {
04064                /* If we someone went on hold we want the other side to reinvite back to us */
04065                if (who == c0)
04066                   pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0);
04067                else
04068                   pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0);
04069             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
04070                /* If they went off hold they should go back to being direct */
04071                if (who == c0)
04072                   pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
04073                else
04074                   pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
04075             }
04076             /* Update local address information */
04077             ast_rtp_get_peer(p0, &t0);
04078             memcpy(&ac0, &t0, sizeof(ac0));
04079             ast_rtp_get_peer(p1, &t1);
04080             memcpy(&ac1, &t1, sizeof(ac1));
04081             /* Update codec information */
04082             if (pr0->get_codec && c0->tech_pvt)
04083                oldcodec0 = codec0 = pr0->get_codec(c0);
04084             if (pr1->get_codec && c1->tech_pvt)
04085                oldcodec1 = codec1 = pr1->get_codec(c1);
04086             ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
04087             ast_frfree(fr);
04088          } else {
04089             *fo = fr;
04090             *rc = who;
04091             ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
04092             return AST_BRIDGE_COMPLETE;
04093          }
04094       } else {
04095          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
04096              (fr->frametype == AST_FRAME_DTMF_END) ||
04097              (fr->frametype == AST_FRAME_VOICE) ||
04098              (fr->frametype == AST_FRAME_VIDEO) ||
04099              (fr->frametype == AST_FRAME_IMAGE) ||
04100              (fr->frametype == AST_FRAME_HTML) ||
04101              (fr->frametype == AST_FRAME_MODEM) ||
04102              (fr->frametype == AST_FRAME_TEXT)) {
04103             ast_write(other, fr);
04104          }
04105          ast_frfree(fr);
04106       }
04107       /* Swap priority */
04108 #ifndef HAVE_EPOLL
04109       cs[2] = cs[0];
04110       cs[0] = cs[1];
04111       cs[1] = cs[2];
04112 #endif
04113    }
04114 
04115    ast_poll_channel_del(c0, c1);
04116 
04117    if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
04118       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
04119    if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
04120       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
04121 
04122    return AST_BRIDGE_FAILED;
04123 }

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

In p2p mode, Asterisk is a very basic RTP proxy, just forwarding whatever rtp/rtcp we get in to the channel.

Note:
this currently only works for Audio

Definition at line 4223 of file rtp.c.

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate_data(), ast_log(), ast_poll_channel_add(), ast_poll_channel_del(), ast_read(), ast_waitfor_n(), ast_write(), ast_channel::audiohooks, ast_frame::data, ast_frame::datalen, FLAG_P2P_SENT_MARK, ast_frame::frametype, LOG_NOTICE, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, ast_channel::name, option_debug, p2p_callback_disable(), p2p_callback_enable(), p2p_set_bridge(), ast_frame::ptr, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

04224 {
04225    struct ast_frame *fr = NULL;
04226    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
04227    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
04228    int p0_callback = 0, p1_callback = 0;
04229    enum ast_bridge_result res = AST_BRIDGE_FAILED;
04230 
04231    /* Okay, setup each RTP structure to do P2P forwarding */
04232    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
04233    p2p_set_bridge(p0, p1);
04234    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
04235    p2p_set_bridge(p1, p0);
04236 
04237    /* Activate callback modes if possible */
04238    p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
04239    p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
04240 
04241    /* Now let go of the channel locks and be on our way */
04242    ast_channel_unlock(c0);
04243    ast_channel_unlock(c1);
04244 
04245    ast_poll_channel_add(c0, c1);
04246 
04247    /* Go into a loop forwarding frames until we don't need to anymore */
04248    cs[0] = c0;
04249    cs[1] = c1;
04250    cs[2] = NULL;
04251    for (;;) {
04252       /* If the underlying formats have changed force this bridge to break */
04253       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
04254          ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n");
04255          res = AST_BRIDGE_FAILED_NOWARN;
04256          break;
04257       }
04258       /* Check if anything changed */
04259       if ((c0->tech_pvt != pvt0) ||
04260           (c1->tech_pvt != pvt1) ||
04261           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
04262           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
04263          ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n");
04264          /* If a masquerade needs to happen we have to try to read in a frame so that it actually happens. Without this we risk being called again and going into a loop */
04265          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
04266             ast_frfree(fr);
04267          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
04268             ast_frfree(fr);
04269          res = AST_BRIDGE_RETRY;
04270          break;
04271       }
04272       /* Wait on a channel to feed us a frame */
04273       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
04274          if (!timeoutms) {
04275             res = AST_BRIDGE_RETRY;
04276             break;
04277          }
04278          if (option_debug > 2)
04279             ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n");
04280          if (ast_check_hangup(c0) || ast_check_hangup(c1))
04281             break;
04282          continue;
04283       }
04284       /* Read in frame from channel */
04285       fr = ast_read(who);
04286       other = (who == c0) ? c1 : c0;
04287       /* Depending on the frame we may need to break out of our bridge */
04288       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
04289              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
04290              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
04291          /* Record received frame and who */
04292          *fo = fr;
04293          *rc = who;
04294          ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
04295          res = AST_BRIDGE_COMPLETE;
04296          break;
04297       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
04298          if ((fr->subclass == AST_CONTROL_HOLD) ||
04299              (fr->subclass == AST_CONTROL_UNHOLD) ||
04300              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
04301              (fr->subclass == AST_CONTROL_SRCUPDATE) ||
04302              (fr->subclass == AST_CONTROL_T38_PARAMETERS)) {
04303             /* If we are going on hold, then break callback mode and P2P bridging */
04304             if (fr->subclass == AST_CONTROL_HOLD) {
04305                if (p0_callback)
04306                   p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
04307                if (p1_callback)
04308                   p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
04309                p2p_set_bridge(p0, NULL);
04310                p2p_set_bridge(p1, NULL);
04311             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
04312                /* If we are off hold, then go back to callback mode and P2P bridging */
04313                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
04314                p2p_set_bridge(p0, p1);
04315                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
04316                p2p_set_bridge(p1, p0);
04317                p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
04318                p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
04319             }
04320             ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
04321             ast_frfree(fr);
04322          } else {
04323             *fo = fr;
04324             *rc = who;
04325             ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
04326             res = AST_BRIDGE_COMPLETE;
04327             break;
04328          }
04329       } else {
04330          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
04331              (fr->frametype == AST_FRAME_DTMF_END) ||
04332              (fr->frametype == AST_FRAME_VOICE) ||
04333              (fr->frametype == AST_FRAME_VIDEO) ||
04334              (fr->frametype == AST_FRAME_IMAGE) ||
04335              (fr->frametype == AST_FRAME_HTML) ||
04336              (fr->frametype == AST_FRAME_MODEM) ||
04337              (fr->frametype == AST_FRAME_TEXT)) {
04338             ast_write(other, fr);
04339          }
04340 
04341          ast_frfree(fr);
04342       }
04343       /* Swap priority */
04344 #ifndef HAVE_EPOLL
04345       cs[2] = cs[0];
04346       cs[0] = cs[1];
04347       cs[1] = cs[2];
04348 #endif
04349    }
04350 
04351    /* If we are totally avoiding the core, then restore our link to it */
04352    if (p0_callback)
04353       p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
04354    if (p1_callback)
04355       p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
04356 
04357    /* Break out of the direct bridge */
04358    p2p_set_bridge(p0, NULL);
04359    p2p_set_bridge(p1, NULL);
04360 
04361    ast_poll_channel_del(c0, c1);
04362 
04363    return res;
04364 }

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

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

Referenced by ast_rtp_read().

01509 {
01510    int res = 0, payload = 0, bridged_payload = 0, mark;
01511    struct rtpPayloadType rtpPT;
01512    int reconstruct = ntohl(rtpheader[0]);
01513 
01514    /* Get fields from packet */
01515    payload = (reconstruct & 0x7f0000) >> 16;
01516    mark = (((reconstruct & 0x800000) >> 23) != 0);
01517 
01518    /* Check what the payload value should be */
01519    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01520 
01521    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01522    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01523       return -1;
01524 
01525    /* Otherwise adjust bridged payload to match */
01526    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01527 
01528    /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
01529    if (!bridged->current_RTP_PT[bridged_payload].code)
01530       return -1;
01531 
01532 
01533    /* If the mark bit has not been sent yet... do it now */
01534    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01535       mark = 1;
01536       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01537    }
01538 
01539    /* Reconstruct part of the packet */
01540    reconstruct &= 0xFF80FFFF;
01541    reconstruct |= (bridged_payload << 16);
01542    reconstruct |= (mark << 23);
01543    rtpheader[0] = htonl(reconstruct);
01544 
01545    /* Send the packet back out */
01546    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01547    if (res < 0) {
01548       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01549          ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno));
01550       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01551          if (option_debug || rtpdebug)
01552             ast_debug(0, "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));
01553          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01554       }
01555       return 0;
01556    } else if (rtp_debug_test_addr(&bridged->them))
01557          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);
01558 
01559    return 0;
01560 }

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

Definition at line 1453 of file rtp.c.

References ast_samp2tv(), ast_tvadd(), ast_tvsub(), ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, normdev_compute(), ast_rtcp::normdev_rxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxtransit, ast_rtp::seedrxts, stddev_compute(), ast_rtcp::stdev_rxjitter, and ast_frame::subclass.

Referenced by ast_rtp_read().

01454 {
01455    struct timeval now;
01456    struct timeval tmp;
01457    double transit;
01458    double current_time;
01459    double d;
01460    double dtv;
01461    double prog;
01462    double normdev_rxjitter_current;
01463    int rate = rtp_get_rate(rtp->f.subclass);
01464 
01465    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01466       gettimeofday(&rtp->rxcore, NULL);
01467       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01468       /* map timestamp to a real time */
01469       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01470       tmp = ast_samp2tv(timestamp, rate);
01471       rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
01472       /* Round to 0.1ms for nice, pretty timestamps */
01473       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01474    }
01475 
01476    gettimeofday(&now,NULL);
01477    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01478    tmp = ast_samp2tv(timestamp, rate);
01479    *when = ast_tvadd(rtp->rxcore, tmp);
01480 
01481    prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
01482    dtv = (double)rtp->drxcore + (double)(prog);
01483    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01484    transit = current_time - dtv;
01485    d = transit - rtp->rxtransit;
01486    rtp->rxtransit = transit;
01487    if (d<0)
01488       d=-d;
01489    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01490 
01491    if (rtp->rtcp) {
01492       if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
01493          rtp->rtcp->maxrxjitter = rtp->rxjitter;
01494       if (rtp->rtcp->rxjitter_count == 1) 
01495          rtp->rtcp->minrxjitter = rtp->rxjitter;
01496       if (rtp->rxjitter < rtp->rtcp->minrxjitter)
01497          rtp->rtcp->minrxjitter = rtp->rxjitter;
01498          
01499       normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
01500       rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
01501 
01502       rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
01503       rtp->rtcp->rxjitter_count++;
01504    }
01505 }

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

Definition at line 3121 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

03122 {
03123    struct timeval t;
03124    long ms;
03125    if (ast_tvzero(rtp->txcore)) {
03126       rtp->txcore = ast_tvnow();
03127       /* Round to 20ms for nice, pretty timestamps */
03128       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
03129    }
03130    /* Use previous txcore if available */
03131    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
03132    ms = ast_tvdiff_ms(t, rtp->txcore);
03133    if (ms < 0)
03134       ms = 0;
03135    /* Use what we just got for next time */
03136    rtp->txcore = t;
03137    return (unsigned int) ms;
03138 }

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

Get channel driver interface structure.

Definition at line 2057 of file rtp.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_rtp_protocol::list, ast_channel::tech, ast_channel_tech::type, and ast_rtp_protocol::type.

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

02058 {
02059    struct ast_rtp_protocol *cur = NULL;
02060 
02061    AST_RWLIST_RDLOCK(&protos);
02062    AST_RWLIST_TRAVERSE(&protos, cur, list) {
02063       if (cur->type == chan->tech->type)
02064          break;
02065    }
02066    AST_RWLIST_UNLOCK(&protos);
02067 
02068    return cur;
02069 }

static char* handle_cli_rtcp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4644 of file rtp.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcp_do_debug_ip(), rtcpdebugaddr, and ast_cli_entry::usage.

04645 {
04646    switch (cmd) {
04647    case CLI_INIT:
04648       e->command = "rtcp set debug {on|off|ip}";
04649       e->usage =
04650          "Usage: rtcp set debug {on|off|ip host[:port]}\n"
04651          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
04652          "       specified, limit the dumped packets to those to and from\n"
04653          "       the specified 'host' with optional port.\n";
04654       return NULL;
04655    case CLI_GENERATE:
04656       return NULL;
04657    }
04658 
04659    if (a->argc == e->args) { /* set on or off */
04660       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
04661          rtcpdebug = 1;
04662          memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
04663          ast_cli(a->fd, "RTCP Debugging Enabled\n");
04664          return CLI_SUCCESS;
04665       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
04666          rtcpdebug = 0;
04667          ast_cli(a->fd, "RTCP Debugging Disabled\n");
04668          return CLI_SUCCESS;
04669       }
04670    } else if (a->argc == e->args +1) { /* ip */
04671       return rtcp_do_debug_ip(a);
04672    }
04673 
04674    return CLI_SHOWUSAGE;   /* default, failure */
04675 }

static char* handle_cli_rtcp_set_stats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4677 of file rtp.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

04678 {
04679    switch (cmd) {
04680    case CLI_INIT:
04681       e->command = "rtcp set stats {on|off}";
04682       e->usage =
04683          "Usage: rtcp set stats {on|off}\n"
04684          "       Enable/Disable dumping of RTCP stats.\n";
04685       return NULL;
04686    case CLI_GENERATE:
04687       return NULL;
04688    }
04689 
04690    if (a->argc != e->args)
04691       return CLI_SHOWUSAGE;
04692 
04693    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04694       rtcpstats = 1;
04695    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04696       rtcpstats = 0;
04697    else
04698       return CLI_SHOWUSAGE;
04699 
04700    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04701    return CLI_SUCCESS;
04702 }

static char* handle_cli_rtp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4611 of file rtp.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtp_do_debug_ip(), rtpdebugaddr, and ast_cli_entry::usage.

04612 {
04613    switch (cmd) {
04614    case CLI_INIT:
04615       e->command = "rtp set debug {on|off|ip}";
04616       e->usage =
04617          "Usage: rtp set debug {on|off|ip host[:port]}\n"
04618          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
04619          "       specified, limit the dumped packets to those to and from\n"
04620          "       the specified 'host' with optional port.\n";
04621       return NULL;
04622    case CLI_GENERATE:
04623       return NULL;
04624    }
04625 
04626    if (a->argc == e->args) { /* set on or off */
04627       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
04628          rtpdebug = 1;
04629          memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
04630          ast_cli(a->fd, "RTP Debugging Enabled\n");
04631          return CLI_SUCCESS;
04632       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
04633          rtpdebug = 0;
04634          ast_cli(a->fd, "RTP Debugging Disabled\n");
04635          return CLI_SUCCESS;
04636       }
04637    } else if (a->argc == e->args +1) { /* ip */
04638       return rtp_do_debug_ip(a);
04639    }
04640 
04641    return CLI_SHOWUSAGE;   /* default, failure */
04642 }

static char* handle_cli_stun_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4704 of file rtp.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

04705 {
04706    switch (cmd) {
04707    case CLI_INIT:
04708       e->command = "stun set debug {on|off}";
04709       e->usage =
04710          "Usage: stun set debug {on|off}\n"
04711          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04712          "       debugging\n";
04713       return NULL;
04714    case CLI_GENERATE:
04715       return NULL;
04716    }
04717 
04718    if (a->argc != e->args)
04719       return CLI_SHOWUSAGE;
04720 
04721    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04722       stundebug = 1;
04723    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04724       stundebug = 0;
04725    else
04726       return CLI_SHOWUSAGE;
04727 
04728    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04729    return CLI_SUCCESS;
04730 }

static double normdev_compute ( double  normdev,
double  sample,
unsigned int  sample_count 
) [static]

Calculate normal deviation.

Definition at line 843 of file rtp.c.

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

00844 {
00845    normdev = normdev * sample_count + sample;
00846    sample_count++;
00847 
00848    return normdev / sample_count;
00849 }

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

Helper function to switch a channel and RTP stream out of callback mode.

Definition at line 4191 of file rtp.c.

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

Referenced by bridge_p2p_loop().

04192 {
04193    ast_channel_lock(chan);
04194 
04195    /* Remove the callback from the IO context */
04196    ast_io_remove(rtp->io, iod[0]);
04197 
04198    /* Restore file descriptors */
04199    chan->fds[0] = ast_rtp_fd(rtp);
04200    ast_channel_unlock(chan);
04201 
04202    /* Restore callback mode if previously used */
04203    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
04204       rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp);
04205 
04206    return 0;
04207 }

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

P2P RTP Callback.

Definition at line 4184 of file rtp.c.

Referenced by bridge_p2p_loop().

04185 {
04186    return 0;
04187 }

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

References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by bridge_p2p_loop().

04211 {
04212    rtp_bridge_lock(rtp0);
04213    rtp0->bridged = rtp1;
04214    rtp_bridge_unlock(rtp0);
04215 }

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

Definition at line 923 of file rtp.c.

References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_test_flag, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, FLAG_DTMF_COMPENSATE, ast_frame::flags, option_debug, ast_rtp::resp, rtp_get_rate(), ast_frame::samples, send_dtmf(), seq, and ast_frame::subclass.

Referenced by ast_rtp_read().

00924 {
00925    unsigned int event;
00926    char resp = 0;
00927    struct ast_frame *f = NULL;
00928    unsigned char seq;
00929    unsigned int flags;
00930    unsigned int power;
00931 
00932    /* We should have at least 4 bytes in RTP data */
00933    if (len < 4)
00934       return f;
00935 
00936    /* The format of Cisco RTP DTMF packet looks like next:
00937       +0          - sequence number of DTMF RTP packet (begins from 1,
00938                     wrapped to 0)
00939       +1          - set of flags
00940       +1 (bit 0)     - flaps by different DTMF digits delimited by audio
00941                     or repeated digit without audio???
00942       +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
00943                     then falls to 0 at its end)
00944       +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
00945       Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
00946       by each new packet and thus provides some redudancy.
00947       
00948       Sample of Cisco RTP DTMF packet is (all data in hex):
00949          19 07 00 02 12 02 20 02
00950       showing end of DTMF digit '2'.
00951 
00952       The packets
00953          27 07 00 02 0A 02 20 02
00954          28 06 20 02 00 02 0A 02
00955       shows begin of new digit '2' with very short pause (20 ms) after
00956       previous digit '2'. Bit +1.0 flips at begin of new digit.
00957       
00958       Cisco RTP DTMF packets comes as replacement of audio RTP packets
00959       so its uses the same sequencing and timestamping rules as replaced
00960       audio packets. Repeat interval of DTMF packets is 20 ms and not rely
00961       on audio framing parameters. Marker bit isn't used within stream of
00962       DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
00963       are not sequential at borders between DTMF and audio streams,
00964    */
00965 
00966    seq = data[0];
00967    flags = data[1];
00968    power = data[2];
00969    event = data[3] & 0x1f;
00970 
00971    if (option_debug > 2 || rtpdebug)
00972       ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
00973    if (event < 10) {
00974       resp = '0' + event;
00975    } else if (event < 11) {
00976       resp = '*';
00977    } else if (event < 12) {
00978       resp = '#';
00979    } else if (event < 16) {
00980       resp = 'A' + (event - 12);
00981    } else if (event < 17) {
00982       resp = 'X';
00983    }
00984    if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
00985       rtp->resp = resp;
00986       /* Why we should care on DTMF compensation at reception? */
00987       if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
00988          f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
00989          rtp->dtmfsamples = 0;
00990       }
00991    } else if ((rtp->resp == resp) && !power) {
00992       f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00993       f->samples = rtp->dtmfsamples * (rtp_get_rate(f->subclass) / 1000);
00994       rtp->resp = 0;
00995    } else if (rtp->resp == resp)
00996       rtp->dtmfsamples += 20 * (rtp_get_rate(f->subclass) / 1000);
00997    rtp->dtmf_timeout = dtmftimeout;
00998    return f;
00999 }

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 
timestamp 
Returns:

Definition at line 1013 of file rtp.c.

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

Referenced by ast_rtp_read().

01014 {
01015    unsigned int event;
01016    unsigned int event_end;
01017    unsigned int samples;
01018    char resp = 0;
01019    struct ast_frame *f = NULL;
01020 
01021    /* Figure out event, event end, and samples */
01022    event = ntohl(*((unsigned int *)(data)));
01023    event >>= 24;
01024    event_end = ntohl(*((unsigned int *)(data)));
01025    event_end <<= 8;
01026    event_end >>= 24;
01027    samples = ntohl(*((unsigned int *)(data)));
01028    samples &= 0xFFFF;
01029 
01030    /* Print out debug if turned on */
01031    if (rtpdebug || option_debug > 2)
01032       ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
01033 
01034    /* Figure out what digit was pressed */
01035    if (event < 10) {
01036       resp = '0' + event;
01037    } else if (event < 11) {
01038       resp = '*';
01039    } else if (event < 12) {
01040       resp = '#';
01041    } else if (event < 16) {
01042       resp = 'A' + (event - 12);
01043    } else if (event < 17) {   /* Event 16: Hook flash */
01044       resp = 'X'; 
01045    } else {
01046       /* Not a supported event */
01047       ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
01048       return &ast_null_frame;
01049    }
01050 
01051    if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
01052       if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
01053          rtp->resp = resp;
01054          rtp->dtmf_timeout = 0;
01055          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01056          f->len = 0;
01057          rtp->lastevent = timestamp;
01058       }
01059    } else {
01060       /*  The duration parameter measures the complete
01061           duration of the event (from the beginning) - RFC2833.
01062           Account for the fact that duration is only 16 bits long
01063           (about 8 seconds at 8000 Hz) and can wrap is digit
01064           is hold for too long. */
01065       unsigned int new_duration = rtp->dtmf_duration;
01066       unsigned int last_duration = new_duration & 0xFFFF;
01067 
01068       if (last_duration > 64000 && samples < last_duration)
01069          new_duration += 0xFFFF + 1;
01070       new_duration = (new_duration & ~0xFFFF) | samples;
01071 
01072       if (event_end & 0x80) {
01073          /* End event */
01074          if ((rtp->lastevent != seqno) && rtp->resp) {
01075             rtp->dtmf_duration = new_duration;
01076             f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01077             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
01078             rtp->resp = 0;
01079             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01080          }
01081       } else {
01082          /* Begin/continuation */
01083 
01084          if (rtp->resp && rtp->resp != resp) {
01085             /* Another digit already began. End it */
01086             f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01087             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
01088             rtp->resp = 0;
01089             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01090          }
01091 
01092 
01093          if (rtp->resp) {
01094             /* Digit continues */
01095             rtp->dtmf_duration = new_duration;
01096          } else {
01097             /* New digit began */
01098             rtp->resp = resp;
01099             f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
01100             rtp->dtmf_duration = samples;
01101          }
01102 
01103          rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
01104       }
01105 
01106       rtp->lastevent = seqno;
01107    }
01108 
01109    rtp->dtmfsamples = samples;
01110 
01111    return f;
01112 }

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

References ast_debug, 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_NOTICE, ast_frame::offset, ast_frame::ptr, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_read().

01121 {
01122    struct ast_frame *f = NULL;
01123    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
01124       totally help us out becuase we don't have an engine to keep it going and we are not
01125       guaranteed to have it every 20ms or anything */
01126    if (rtpdebug)
01127       ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
01128 
01129    if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
01130       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
01131          ast_inet_ntoa(rtp->them.sin_addr));
01132       ast_set_flag(rtp, FLAG_3389_WARNING);
01133    }
01134    
01135    /* Must have at least one byte */
01136    if (!len)
01137       return NULL;
01138    if (len < 24) {
01139       rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
01140       rtp->f.datalen = len - 1;
01141       rtp->f.offset = AST_FRIENDLY_OFFSET;
01142       memcpy(rtp->f.data.ptr, data + 1, len - 1);
01143    } else {
01144       rtp->f.data.ptr = NULL;
01145       rtp->f.offset = 0;
01146       rtp->f.datalen = 0;
01147    }
01148    rtp->f.frametype = AST_FRAME_CNG;
01149    rtp->f.subclass = data[0] & 0x7f;
01150    rtp->f.samples = 0;
01151    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
01152    f = &rtp->f;
01153    return f;
01154 }

void red_buffer_t140 ( struct ast_rtp rtp,
struct ast_frame f 
)

Buffer t140 from chan_sip.

Buffer t.140 data.

Parameters:
rtp 
f frame

Definition at line 4921 of file rtp.c.

References rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::ptr, ast_rtp::red, rtp_red::t140, and ast_frame::ts.

Referenced by sip_write().

04922 {
04923    if (f->datalen > -1) {
04924       struct rtp_red *red = rtp->red;
04925       memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen);
04926       red->t140.datalen += f->datalen;
04927       red->t140.ts = f->ts;
04928    }
04929 }

static struct ast_frame * red_t140_to_red ( struct rtp_red red  )  [static, read]

Construct a redundant frame.

Parameters:
red redundant data structure

Definition at line 4838 of file rtp.c.

References ast_frame::data, ast_frame::datalen, rtp_red::hdrlen, rtp_red::len, rtp_red::num_gen, ast_frame::ptr, rtp_red::t140, and rtp_red::t140red.

Referenced by ast_rtp_write().

04838                                                               {
04839    unsigned char *data = red->t140red.data.ptr;
04840    int len = 0;
04841    int i;
04842 
04843    /* replace most aged generation */
04844    if (red->len[0]) {
04845       for (i = 1; i < red->num_gen+1; i++)
04846          len += red->len[i];
04847 
04848       memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 
04849    }
04850    
04851    /* Store length of each generation and primary data length*/
04852    for (i = 0; i < red->num_gen; i++)
04853       red->len[i] = red->len[i+1];
04854    red->len[i] = red->t140.datalen;
04855    
04856    /* write each generation length in red header */
04857    len = red->hdrlen;
04858    for (i = 0; i < red->num_gen; i++)
04859       len += data[i*4+3] = red->len[i];
04860    
04861    /* add primary data to buffer */
04862    memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 
04863    red->t140red.datalen = len + red->t140.datalen;
04864    
04865    /* no primary data and no generations to send */
04866    if (len == red->hdrlen && !red->t140.datalen)
04867       return NULL;
04868 
04869    /* reset t.140 buffer */
04870    red->t140.datalen = 0; 
04871    
04872    return &red->t140red;
04873 }

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

Definition at line 4826 of file rtp.c.

References ast_rtp_write(), ast_rtp::red, and rtp_red::t140.

Referenced by rtp_red_init().

04827 {
04828    struct ast_rtp *rtp = (struct ast_rtp*) data;
04829    
04830    ast_rtp_write(rtp, &rtp->red->t140); 
04831 
04832    return 1;   
04833 }

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

Definition at line 909 of file rtp.c.

References rtcpdebugaddr.

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

00910 {
00911    if (rtcpdebug == 0)
00912       return 0;
00913    if (rtcpdebugaddr.sin_addr.s_addr) {
00914       if (((ntohs(rtcpdebugaddr.sin_port) != 0)
00915            && (rtcpdebugaddr.sin_port != addr->sin_port))
00916           || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00917          return 0;
00918    }
00919    return 1;
00920 }

static char* rtcp_do_debug_ip ( struct ast_cli_args a  )  [static]

Definition at line 4581 of file rtp.c.

References ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, hp, and rtcpdebugaddr.

Referenced by handle_cli_rtcp_set_debug().

04582 {
04583    struct hostent *hp;
04584    struct ast_hostent ahp;
04585    int port = 0;
04586    char *p, *arg;
04587 
04588    arg = a->argv[3];
04589    p = strstr(arg, ":");
04590    if (p) {
04591       *p = '\0';
04592       p++;
04593       port = atoi(p);
04594    }
04595    hp = ast_gethostbyname(arg, &ahp);
04596    if (hp == NULL) {
04597       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04598       return CLI_FAILURE;
04599    }
04600    rtcpdebugaddr.sin_family = AF_INET;
04601    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
04602    rtcpdebugaddr.sin_port = htons(port);
04603    if (port == 0)
04604       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
04605    else
04606       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
04607    rtcpdebug = 1;
04608    return CLI_SUCCESS;
04609 }

static void rtp_bridge_lock ( struct ast_rtp rtp  )  [static]
static void rtp_bridge_unlock ( struct ast_rtp rtp  )  [static]
static int rtp_debug_test_addr ( struct sockaddr_in *  addr  )  [inline, static]

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

00897 {
00898    if (rtpdebug == 0)
00899       return 0;
00900    if (rtpdebugaddr.sin_addr.s_addr) {
00901       if (((ntohs(rtpdebugaddr.sin_port) != 0)
00902            && (rtpdebugaddr.sin_port != addr->sin_port))
00903           || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00904          return 0;
00905    }
00906    return 1;
00907 }

static char* rtp_do_debug_ip ( struct ast_cli_args a  )  [static]

Definition at line 4551 of file rtp.c.

References ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, hp, and rtpdebugaddr.

Referenced by handle_cli_rtp_set_debug().

04552 {
04553    struct hostent *hp;
04554    struct ast_hostent ahp;
04555    int port = 0;
04556    char *p, *arg;
04557 
04558    arg = a->argv[3];
04559    p = strstr(arg, ":");
04560    if (p) {
04561       *p = '\0';
04562       p++;
04563       port = atoi(p);
04564    }
04565    hp = ast_gethostbyname(arg, &ahp);
04566    if (hp == NULL) {
04567       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04568       return CLI_FAILURE;
04569    }
04570    rtpdebugaddr.sin_family = AF_INET;
04571    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
04572    rtpdebugaddr.sin_port = htons(port);
04573    if (port == 0)
04574       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
04575    else
04576       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
04577    rtpdebug = 1;
04578    return CLI_SUCCESS;
04579 }

static int rtp_get_rate ( int  subclass  )  [static]

Definition at line 730 of file rtp.c.

References AST_FORMAT_G722, and ast_format_rate().

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

00731 {
00732    return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
00733 }

int rtp_red_init ( struct ast_rtp rtp,
int  ti,
int *  red_data_pt,
int  num_gen 
)

Initialize t140 redundancy.

Initalize t.140 redudancy.

Parameters:
rtp 
ti buffer t140 for ti (msecs) before sending redundant frame
red_data_pt Payloadtypes for primary- and generation-data
num_gen numbers of generations (primary generation not encounted)

Definition at line 4882 of file rtp.c.

References ast_calloc, AST_FORMAT_T140RED, AST_FRAME_TEXT, ast_sched_add(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::frametype, rtp_red::hdrlen, rtp_red::num_gen, rtp_red::prev_ts, rtp_red::pt, ast_frame::ptr, ast_rtp::red, red_write(), ast_rtp::sched, rtp_red::schedid, ast_frame::subclass, rtp_red::t140, rtp_red::t140red, rtp_red::t140red_data, rtp_red::ti, and ast_frame::ts.

Referenced by process_sdp().

04883 {
04884    struct rtp_red *r;
04885    int x;
04886    
04887    if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
04888       return -1;
04889 
04890    r->t140.frametype = AST_FRAME_TEXT;
04891    r->t140.subclass = AST_FORMAT_T140RED;
04892    r->t140.data.ptr = &r->buf_data; 
04893 
04894    r->t140.ts = 0;
04895    r->t140red = r->t140;
04896    r->t140red.data.ptr = &r->t140red_data;
04897    r->t140red.datalen = 0;
04898    r->ti = ti;
04899    r->num_gen = num_gen;
04900    r->hdrlen = num_gen * 4 + 1;
04901    r->prev_ts = 0;
04902 
04903    for (x = 0; x < num_gen; x++) {
04904       r->pt[x] = red_data_pt[x];
04905       r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 
04906       r->t140red_data[x*4] = r->pt[x];
04907    }
04908    r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
04909    r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
04910    rtp->red = r;
04911 
04912    r->t140.datalen = 0;
04913    
04914    return 0;
04915 }

static int rtp_socket ( const char *  type  )  [static]

Open RTP or RTCP socket for a session. Print a message on failure.

Definition at line 2473 of file rtp.c.

References ast_log(), errno, LOG_WARNING, and s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

02474 {
02475    int s = socket(AF_INET, SOCK_DGRAM, 0);
02476    if (s < 0) {
02477       if (type == NULL)
02478          type = "RTP/RTCP";
02479       ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
02480    } else {
02481       long flags = fcntl(s, F_GETFL);
02482       fcntl(s, F_SETFL, flags | O_NONBLOCK);
02483 #ifdef SO_NO_CHECK
02484       if (nochecksums)
02485          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
02486 #endif
02487    }
02488    return s;
02489 }

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

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

01157 {
01158    struct ast_rtp *rtp = cbdata;
01159    struct ast_frame *f;
01160    f = ast_rtp_read(rtp);
01161    if (f) {
01162       if (rtp->callback)
01163          rtp->callback(rtp, f, rtp->data);
01164    }
01165    return 1;
01166 }

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

Definition at line 871 of file rtp.c.

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

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

00872 {
00873    if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
00874         (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
00875       ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
00876       rtp->resp = 0;
00877       rtp->dtmfsamples = 0;
00878       return &ast_null_frame;
00879    }
00880    ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
00881    if (rtp->resp == 'X') {
00882       rtp->f.frametype = AST_FRAME_CONTROL;
00883       rtp->f.subclass = AST_CONTROL_FLASH;
00884    } else {
00885       rtp->f.frametype = type;
00886       rtp->f.subclass = rtp->resp;
00887    }
00888    rtp->f.datalen = 0;
00889    rtp->f.samples = 0;
00890    rtp->f.mallocd = 0;
00891    rtp->f.src = "RTP";
00892    return &rtp->f;
00893    
00894 }

static double stddev_compute ( double  stddev,
double  sample,
double  normdev,
double  normdev_curent,
unsigned int  sample_count 
) [static]

Definition at line 851 of file rtp.c.

References SQUARE.

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

00852 {
00853 /*
00854       for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
00855       return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
00856       we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
00857       optimized formula
00858 */
00859 #define SQUARE(x) ((x) * (x))
00860 
00861    stddev = sample_count * stddev;
00862    sample_count++;
00863 
00864    return stddev + 
00865           ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) + 
00866           ( SQUARE(sample - normdev_curent) / sample_count );
00867 
00868 #undef SQUARE
00869 }

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

helper function to print attribute names

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

00392 {
00393    switch (msg) {
00394    case STUN_MAPPED_ADDRESS:
00395       return "Mapped Address";
00396    case STUN_RESPONSE_ADDRESS:
00397       return "Response Address";
00398    case STUN_CHANGE_REQUEST:
00399       return "Change Request";
00400    case STUN_SOURCE_ADDRESS:
00401       return "Source Address";
00402    case STUN_CHANGED_ADDRESS:
00403       return "Changed Address";
00404    case STUN_USERNAME:
00405       return "Username";
00406    case STUN_PASSWORD:
00407       return "Password";
00408    case STUN_MESSAGE_INTEGRITY:
00409       return "Message Integrity";
00410    case STUN_ERROR_CODE:
00411       return "Error Code";
00412    case STUN_UNKNOWN_ATTRIBUTES:
00413       return "Unknown Attributes";
00414    case STUN_REFLECTED_FROM:
00415       return "Reflected From";
00416    }
00417    return "Non-RFC3489 Attribute";
00418 }

static int stun_get_mapped ( struct stun_attr attr,
void *  arg 
) [static]

Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_response when called from ast_stun_request.

Definition at line 608 of file rtp.c.

References stun_addr::addr, stun_attr::attr, stun_attr::len, stun_addr::port, and STUN_MAPPED_ADDRESS.

Referenced by ast_stun_request().

00609 {
00610    struct stun_addr *addr = (struct stun_addr *)(attr + 1);
00611    struct sockaddr_in *sa = (struct sockaddr_in *)arg;
00612 
00613    if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
00614       return 1;   /* not us. */
00615    sa->sin_port = addr->port;
00616    sa->sin_addr.s_addr = addr->addr;
00617    return 0;
00618 }

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

handle an incoming STUN message.

Do some basic sanity checks on packet size and content, try to extract a bit of information, and possibly reply. At the moment this only processes BIND requests, and returns the externally visible address of the request. If a callback is specified, invoke it with the attribute.

Definition at line 510 of file rtp.c.

References append_attr_address(), append_attr_string(), ast_debug, ast_verbose, stun_attr::attr, stun_header::id, stun_header::ies, stun_attr::len, stun_header::msglen, stun_header::msgtype, 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(), and ast_stun_request().

00512 {
00513    struct stun_header *hdr = (struct stun_header *)data;
00514    struct stun_attr *attr;
00515    struct stun_state st;
00516    int ret = STUN_IGNORE;  
00517    int x;
00518 
00519    /* On entry, 'len' is the length of the udp payload. After the
00520     * initial checks it becomes the size of unprocessed options,
00521     * while 'data' is advanced accordingly.
00522     */
00523    if (len < sizeof(struct stun_header)) {
00524       ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
00525       return -1;
00526    }
00527    len -= sizeof(struct stun_header);
00528    data += sizeof(struct stun_header);
00529    x = ntohs(hdr->msglen); /* len as advertised in the message */
00530    if (stundebug)
00531       ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
00532    if (x > len) {
00533       ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
00534    } else
00535       len = x;
00536    memset(&st, 0, sizeof(st));
00537    while (len) {
00538       if (len < sizeof(struct stun_attr)) {
00539          ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
00540          break;
00541       }
00542       attr = (struct stun_attr *)data;
00543       /* compute total attribute length */
00544       x = ntohs(attr->len) + sizeof(struct stun_attr);
00545       if (x > len) {
00546          ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
00547          break;
00548       }
00549       if (stun_cb)
00550          stun_cb(attr, arg);
00551       if (stun_process_attr(&st, attr)) {
00552          ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
00553          break;
00554       }
00555       /* Clear attribute id: in case previous entry was a string,
00556        * this will act as the terminator for the string.
00557        */
00558       attr->attr = 0;
00559       data += x;
00560       len -= x;
00561    }
00562    /* Null terminate any string.
00563     * XXX NOTE, we write past the size of the buffer passed by the
00564     * caller, so this is potentially dangerous. The only thing that
00565     * saves us is that usually we read the incoming message in a
00566     * much larger buffer in the struct ast_rtp
00567     */
00568    *data = '\0';
00569 
00570    /* Now prepare to generate a reply, which at the moment is done
00571     * only for properly formed (len == 0) STUN_BINDREQ messages.
00572     */
00573    if (len == 0) {
00574       unsigned char respdata[1024];
00575       struct stun_header *resp = (struct stun_header *)respdata;
00576       int resplen = 0;  /* len excluding header */
00577       int respleft = sizeof(respdata) - sizeof(struct stun_header);
00578 
00579       resp->id = hdr->id;
00580       resp->msgtype = 0;
00581       resp->msglen = 0;
00582       attr = (struct stun_attr *)resp->ies;
00583       switch (ntohs(hdr->msgtype)) {
00584       case STUN_BINDREQ:
00585          if (stundebug)
00586             ast_verbose("STUN Bind Request, username: %s\n", 
00587                    st.username ? st.username : "<none>");
00588          if (st.username)
00589             append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
00590          append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
00591          resp->msglen = htons(resplen);
00592          resp->msgtype = htons(STUN_BINDRESP);
00593          stun_send(s, src, resp);
00594          ret = STUN_ACCEPT;
00595          break;
00596       default:
00597          if (stundebug)
00598             ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
00599       }
00600    }
00601    return ret;
00602 }

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

helper function to print message names

Definition at line 371 of file rtp.c.

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

Referenced by stun_handle_packet().

00372 {
00373    switch (msg) {
00374    case STUN_BINDREQ:
00375       return "Binding Request";
00376    case STUN_BINDRESP:
00377       return "Binding Response";
00378    case STUN_BINDERR:
00379       return "Binding Error Response";
00380    case STUN_SECREQ:
00381       return "Shared Secret Request";
00382    case STUN_SECRESP:
00383       return "Shared Secret Response";
00384    case STUN_SECERR:
00385       return "Shared Secret Error Response";
00386    }
00387    return "Non-RFC3489 Message";
00388 }

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

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

00427 {
00428    if (stundebug)
00429       ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
00430              stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00431    switch (ntohs(attr->attr)) {
00432    case STUN_USERNAME:
00433       state->username = (const char *) (attr->value);
00434       break;
00435    case STUN_PASSWORD:
00436       state->password = (const char *) (attr->value);
00437       break;
00438    default:
00439       if (stundebug)
00440          ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 
00441                 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00442    }
00443    return 0;
00444 }

static void stun_req_id ( struct stun_header req  )  [static]

helper function to generate a random request id

Definition at line 487 of file rtp.c.

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

Referenced by ast_stun_request().

00488 {
00489    int x;
00490    for (x = 0; x < 4; x++)
00491       req->id.id[x] = ast_random();
00492 }

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

wrapper to send an STUN message

Definition at line 480 of file rtp.c.

References stun_header::msglen.

Referenced by ast_stun_request(), and stun_handle_packet().

00481 {
00482    return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00483             (struct sockaddr *)dst, sizeof(*dst));
00484 }

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

Definition at line 708 of file rtp.c.

References sec.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

00709 {
00710    unsigned int sec, usec, frac;
00711    sec = when.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
00712    usec = when.tv_usec;
00713    frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
00714    *msw = sec;
00715    *lsw = frac;
00716 }


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 4732 of file rtp.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 69 of file rtp.c.

struct mimeType mimeTypes[] [static]
int rtcpdebug [static]

Are we debugging RTCP?

Definition at line 74 of file rtp.c.

struct sockaddr_in rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 79 of file rtp.c.

Referenced by handle_cli_rtcp_set_debug(), rtcp_debug_test_addr(), and rtcp_do_debug_ip().

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 76 of file rtp.c.

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 75 of file rtp.c.

int rtpdebug [static]

Are we debugging?

Definition at line 73 of file rtp.c.

struct sockaddr_in rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 78 of file rtp.c.

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

int rtpend = 31000 [static]

Last port for RTP sessions (set in rtp.conf)

Definition at line 72 of file rtp.c.

int rtpstart = 5000 [static]

First port for RTP sessions (set in rtp.conf)

Definition at line 71 of file rtp.c.

struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static]

Mapping between Asterisk codecs and rtp payload types.

Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s: also, our own choices for dynamic payload types. This is our master table for transmission

See http://www.iana.org/assignments/rtp-parameters for a list of assigned values

Definition at line 1957 of file rtp.c.

int strictrtp [static]

Definition at line 83 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 77 of file rtp.c.


Generated by  doxygen 1.6.2