Tue Mar 2 17:34:26 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
 RTP session description. More...
struct  rtp_red
struct  rtpPayloadType
 Structure representing a RTP session. More...
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:.
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)
 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)
static AST_RWLIST_HEAD_STATIC (protos, ast_rtp_protocol)
 List of current sessions.
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_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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_rtcp_stats_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtp_debug_deprecated (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_debug_deprecated (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, int deprecated)
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 void sanitize_tv (struct timeval *tv)
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_rtcp_debug_deprecated = AST_CLI_DEFINE(handle_cli_rtcp_debug_deprecated, "Enable/Disable RTCP debugging")
static struct ast_cli_entry cli_rtcp_stats_deprecated = AST_CLI_DEFINE(handle_cli_rtcp_stats_deprecated, "Enable/Disable RTCP stats")
static struct ast_cli_entry cli_rtp []
static struct ast_cli_entry cli_rtp_debug_deprecated = AST_CLI_DEFINE(handle_cli_rtp_debug_deprecated, "Enable/Disable RTP debugging")
static struct ast_cli_entry cli_stun_debug_deprecated = AST_CLI_DEFINE(handle_cli_stun_debug_deprecated, "Enable/Disable STUN debugging")
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
struct {
   struct rtpPayloadType   payloadType
   char *   subtype
   char *   type
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 215 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 222 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 223 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 219 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 224 of file rtp.c.

Referenced by ast_rtp_setstun().

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

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

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

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

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

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

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

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

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

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

#define STUN_BINDRESP   0x0101

Definition at line 355 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 366 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 368 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 372 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

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

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

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 371 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 370 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 374 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 365 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 359 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 357 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 358 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 367 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 373 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 369 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 506 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 2755 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().

02756 {
02757    *found = 1;
02758 
02759    if (!strcasecmp(qos, "remote_maxjitter"))
02760       return rtp->rtcp->reported_maxjitter * 1000.0;
02761    if (!strcasecmp(qos, "remote_minjitter"))
02762       return rtp->rtcp->reported_minjitter * 1000.0;
02763    if (!strcasecmp(qos, "remote_normdevjitter"))
02764       return rtp->rtcp->reported_normdev_jitter * 1000.0;
02765    if (!strcasecmp(qos, "remote_stdevjitter"))
02766       return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0;
02767 
02768    if (!strcasecmp(qos, "local_maxjitter"))
02769       return rtp->rtcp->maxrxjitter * 1000.0;
02770    if (!strcasecmp(qos, "local_minjitter"))
02771       return rtp->rtcp->minrxjitter * 1000.0;
02772    if (!strcasecmp(qos, "local_normdevjitter"))
02773       return rtp->rtcp->normdev_rxjitter * 1000.0;
02774    if (!strcasecmp(qos, "local_stdevjitter"))
02775       return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0;
02776 
02777    if (!strcasecmp(qos, "maxrtt"))
02778       return rtp->rtcp->maxrtt * 1000.0;
02779    if (!strcasecmp(qos, "minrtt"))
02780       return rtp->rtcp->minrtt * 1000.0;
02781    if (!strcasecmp(qos, "normdevrtt"))
02782       return rtp->rtcp->normdevrtt * 1000.0;
02783    if (!strcasecmp(qos, "stdevrtt"))
02784       return sqrt(rtp->rtcp->stdevrtt) * 1000.0;
02785 
02786    *found = 0;
02787 
02788    return 0.0;
02789 }

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

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

02959 {
02960    /*
02961    *ssrc          our ssrc
02962    *themssrc      their ssrc
02963    *lp            lost packets
02964    *rxjitter      our calculated jitter(rx)
02965    *rxcount       no. received packets
02966    *txjitter      reported jitter of the other end
02967    *txcount       transmitted packets
02968    *rlp           remote lost packets
02969    *rtt           round trip time
02970    */ 
02971 
02972    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02973       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02974          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02975          rtp->ssrc,
02976          rtp->themssrc,
02977          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02978          rtp->rxjitter,
02979          rtp->rxcount,
02980          (double)rtp->rtcp->reported_jitter / 65536.0,
02981          rtp->txcount,
02982          rtp->rtcp->reported_lost,
02983          rtp->rtcp->rtt
02984       );
02985    } else {
02986       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;",
02987          rtp->ssrc,
02988          rtp->themssrc,
02989          rtp->rxjitter,
02990          rtp->rxcount,
02991          rtp->txcount
02992       );
02993    }
02994 
02995    return rtp->rtcp->quality;
02996 }

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

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

02838 {
02839    /*
02840    *ssrc          our ssrc
02841    *themssrc      their ssrc
02842    *lp            lost packets
02843    *rxjitter      our calculated jitter(rx)
02844    *rxcount       no. received packets
02845    *txjitter      reported jitter of the other end
02846    *txcount       transmitted packets
02847    *rlp           remote lost packets
02848    *rtt           round trip time
02849    */
02850 #define RTCP_JITTER_FORMAT1 \
02851    "minrxjitter=%f;" \
02852    "maxrxjitter=%f;" \
02853    "avgrxjitter=%f;" \
02854    "stdevrxjitter=%f;" \
02855    "reported_minjitter=%f;" \
02856    "reported_maxjitter=%f;" \
02857    "reported_avgjitter=%f;" \
02858    "reported_stdevjitter=%f;"
02859 
02860 #define RTCP_JITTER_FORMAT2 \
02861    "rxjitter=%f;"
02862 
02863    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02864       snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1,
02865          rtp->rtcp->minrxjitter,
02866          rtp->rtcp->maxrxjitter,
02867          rtp->rtcp->normdev_rxjitter,
02868          sqrt(rtp->rtcp->stdev_rxjitter),
02869          rtp->rtcp->reported_minjitter,
02870          rtp->rtcp->reported_maxjitter,
02871          rtp->rtcp->reported_normdev_jitter,
02872          sqrt(rtp->rtcp->reported_stdev_jitter)
02873       );
02874    } else {
02875       snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2,
02876          rtp->rxjitter
02877       );
02878    }
02879 
02880    return rtp->rtcp->quality_jitter;
02881 
02882 #undef RTCP_JITTER_FORMAT1
02883 #undef RTCP_JITTER_FORMAT2
02884 }

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

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

02887 {
02888    unsigned int lost;
02889    unsigned int extended;
02890    unsigned int expected;
02891    int fraction;
02892 
02893 #define RTCP_LOSS_FORMAT1 \
02894    "minrxlost=%f;" \
02895    "maxrxlost=%f;" \
02896    "avgrxlostr=%f;" \
02897    "stdevrxlost=%f;" \
02898    "reported_minlost=%f;" \
02899    "reported_maxlost=%f;" \
02900    "reported_avglost=%f;" \
02901    "reported_stdevlost=%f;"
02902 
02903 #define RTCP_LOSS_FORMAT2 \
02904    "lost=%d;" \
02905    "expected=%d;"
02906    
02907    if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) {
02908       snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1,
02909          rtp->rtcp->minrxlost,
02910          rtp->rtcp->maxrxlost,
02911          rtp->rtcp->normdev_rxlost,
02912          sqrt(rtp->rtcp->stdev_rxlost),
02913          rtp->rtcp->reported_minlost,
02914          rtp->rtcp->reported_maxlost,
02915          rtp->rtcp->reported_normdev_lost,
02916          sqrt(rtp->rtcp->reported_stdev_lost)
02917       );
02918    } else {
02919       extended = rtp->cycles + rtp->lastrxseqno;
02920       expected = extended - rtp->seedrxseqno + 1;
02921       if (rtp->rxcount > expected) 
02922          expected += rtp->rxcount - expected;
02923       lost = expected - rtp->rxcount;
02924 
02925       if (!expected || lost <= 0)
02926          fraction = 0;
02927       else
02928          fraction = (lost << 8) / expected;
02929 
02930       snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2,
02931          lost,
02932          expected
02933       );
02934    }
02935 
02936    return rtp->rtcp->quality_loss;
02937 
02938 #undef RTCP_LOSS_FORMAT1
02939 #undef RTCP_LOSS_FORMAT2
02940 }

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

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

02943 {
02944    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02945       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
02946          rtp->rtcp->minrtt,
02947          rtp->rtcp->maxrtt,
02948          rtp->rtcp->normdevrtt,
02949          sqrt(rtp->rtcp->stdevrtt)
02950       );
02951    } else {
02952       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available");
02953    }
02954 
02955    return rtp->rtcp->quality_rtt;
02956 }

static int __ast_rtp_reload ( int  reload  )  [static]

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

04826 {
04827    struct ast_config *cfg;
04828    const char *s;
04829    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04830 
04831    if ((cfg = ast_config_load2("rtp.conf", "rtp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
04832       return 0;
04833 
04834    rtpstart = 5000;
04835    rtpend = 31000;
04836    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04837    strictrtp = STRICT_RTP_OPEN;
04838    if (cfg) {
04839       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
04840          rtpstart = atoi(s);
04841          if (rtpstart < 1024)
04842             rtpstart = 1024;
04843          if (rtpstart > 65535)
04844             rtpstart = 65535;
04845       }
04846       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
04847          rtpend = atoi(s);
04848          if (rtpend < 1024)
04849             rtpend = 1024;
04850          if (rtpend > 65535)
04851             rtpend = 65535;
04852       }
04853       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
04854          rtcpinterval = atoi(s);
04855          if (rtcpinterval == 0)
04856             rtcpinterval = 0; /* Just so we're clear... it's zero */
04857          if (rtcpinterval < RTCP_MIN_INTERVALMS)
04858             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
04859          if (rtcpinterval > RTCP_MAX_INTERVALMS)
04860             rtcpinterval = RTCP_MAX_INTERVALMS;
04861       }
04862       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
04863 #ifdef SO_NO_CHECK
04864          if (ast_false(s))
04865             nochecksums = 1;
04866          else
04867             nochecksums = 0;
04868 #else
04869          if (ast_false(s))
04870             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
04871 #endif
04872       }
04873       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
04874          dtmftimeout = atoi(s);
04875          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
04876             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
04877                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
04878             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04879          };
04880       }
04881       if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
04882          strictrtp = ast_true(s);
04883       }
04884       ast_config_destroy(cfg);
04885    }
04886    if (rtpstart >= rtpend) {
04887       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
04888       rtpstart = 5000;
04889       rtpend = 31000;
04890    }
04891    ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
04892    return 0;
04893 }

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

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

Referenced by stun_handle_packet().

00468 {
00469    int size = sizeof(**attr) + 8;
00470    struct stun_addr *addr;
00471    if (*left > size) {
00472       (*attr)->attr = htons(attrval);
00473       (*attr)->len = htons(8);
00474       addr = (struct stun_addr *)((*attr)->value);
00475       addr->unused = 0;
00476       addr->family = 0x01;
00477       addr->port = sock_in->sin_port;
00478       addr->addr = sock_in->sin_addr.s_addr;
00479       (*attr) = (struct stun_attr *)((*attr)->value + 8);
00480       *len += size;
00481       *left -= size;
00482    }
00483 }

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

Referenced by ast_stun_request(), and stun_handle_packet().

00454 {
00455    int size = sizeof(**attr) + strlen(s);
00456    if (*left > size) {
00457       (*attr)->attr = htons(attrval);
00458       (*attr)->len = htons(strlen(s));
00459       memcpy((*attr)->value, s, strlen(s));
00460       (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
00461       *len += size;
00462       *left -= size;
00463    }
00464 }

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

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00742 {
00743    unsigned int interval;
00744    /*! \todo XXX Do a more reasonable calculation on this one
00745     * Look in RFC 3550 Section A.7 for an example*/
00746    interval = rtcpinterval;
00747    return interval;
00748 }

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

00730 {
00731    if (rtp->rtcp)
00732       return rtp->rtcp->s;
00733    return -1;
00734 }

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

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

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

02468 {
02469    struct ast_rtcp *rtcp;
02470 
02471    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
02472       return NULL;
02473    rtcp->s = rtp_socket("RTCP");
02474    rtcp->us.sin_family = AF_INET;
02475    rtcp->them.sin_family = AF_INET;
02476    rtcp->schedid = -1;
02477 
02478    if (rtcp->s < 0) {
02479       ast_free(rtcp);
02480       return NULL;
02481    }
02482 
02483    return rtcp;
02484 }

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

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

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

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

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

03271 {
03272    struct ast_rtp *rtp = data;
03273    int res;
03274 
03275    rtp->rtcp->sendfur = 1;
03276    res = ast_rtcp_write(data);
03277    
03278    return res;
03279 }

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

03529 {
03530    struct ast_rtp *rtp = (struct ast_rtp *)data;
03531    int res;
03532    
03533    if (!rtp || !rtp->rtcp)
03534       return 0;
03535 
03536    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
03537       res = ast_rtcp_write_sr(data);
03538    else
03539       res = ast_rtcp_write_rr(data);
03540    
03541    return res;
03542 }

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

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

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

Send RTCP sender's report.

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

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

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

Referenced by process_sdp().

00501 {
00502    return sizeof(struct ast_rtp);
00503 }

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 4358 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_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, and ast_channel::tech_pvt.

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

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3750 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp_a_audio().

03751 {
03752    if (pt < 0 || pt >= MAX_RTP_PT)
03753       return 0; /* bogus payload type */
03754 
03755    if (static_RTP_PT[pt].isAstFormat)
03756       return static_RTP_PT[pt].code;
03757    else
03758       return 0;
03759 }

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

Get codec preference.

Definition at line 3745 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

03746 {
03747    return &rtp->pref;
03748 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

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

03700 {
03701    struct ast_format_list current_format_old, current_format_new;
03702 
03703    /* if no packets have been sent through this session yet, then
03704     *  changing preferences does not require any extra work
03705     */
03706    if (rtp->lasttxformat == 0) {
03707       rtp->pref = *prefs;
03708       return;
03709    }
03710 
03711    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03712 
03713    rtp->pref = *prefs;
03714 
03715    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03716 
03717    /* if the framing desired for the current format has changed, we may have to create
03718     * or adjust the smoother for this session
03719     */
03720    if ((current_format_new.inc_ms != 0) &&
03721        (current_format_new.cur_ms != current_format_old.cur_ms)) {
03722       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
03723 
03724       if (rtp->smoother) {
03725          ast_smoother_reconfigure(rtp->smoother, new_size);
03726          if (option_debug) {
03727             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
03728          }
03729       } else {
03730          if (!(rtp->smoother = ast_smoother_new(new_size))) {
03731             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03732             return;
03733          }
03734          if (current_format_new.flags) {
03735             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
03736          }
03737          if (option_debug) {
03738             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03739          }
03740       }
03741    }
03742 
03743 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

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

03030 {
03031    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
03032       /*Print some info on the call here */
03033       ast_verbose("  RTP-stats\n");
03034       ast_verbose("* Our Receiver:\n");
03035       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
03036       ast_verbose("  Received packets: %u\n", rtp->rxcount);
03037       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
03038       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
03039       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
03040       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
03041       ast_verbose("* Our Sender:\n");
03042       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
03043       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
03044       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
03045       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
03046       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
03047       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
03048    }
03049 
03050    manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
03051                    "ReceivedPackets: %u\r\n"
03052                    "LostPackets: %u\r\n"
03053                    "Jitter: %.4f\r\n"
03054                    "Transit: %.4f\r\n"
03055                    "RRCount: %u\r\n",
03056                    rtp->themssrc,
03057                    rtp->rxcount,
03058                    rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
03059                    rtp->rxjitter,
03060                    rtp->rxtransit,
03061                    rtp->rtcp ? rtp->rtcp->rr_count : 0);
03062    manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
03063                    "SentPackets: %u\r\n"
03064                    "LostPackets: %u\r\n"
03065                    "Jitter: %u\r\n"
03066                    "SRCount: %u\r\n"
03067                    "RTT: %f\r\n",
03068                    rtp->ssrc,
03069                    rtp->txcount,
03070                    rtp->rtcp ? rtp->rtcp->reported_lost : 0,
03071                    rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
03072                    rtp->rtcp ? rtp->rtcp->sr_count : 0,
03073                    rtp->rtcp ? rtp->rtcp->rtt : 0);
03074    if (rtp->smoother)
03075       ast_smoother_free(rtp->smoother);
03076    if (rtp->ioid)
03077       ast_io_remove(rtp->io, rtp->ioid);
03078    if (rtp->s > -1)
03079       close(rtp->s);
03080    if (rtp->rtcp) {
03081       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03082       close(rtp->rtcp->s);
03083       ast_free(rtp->rtcp);
03084       rtp->rtcp=NULL;
03085    }
03086 #ifdef P2P_INTENSE
03087    ast_mutex_destroy(&rtp->bridge_lock);
03088 #endif
03089    ast_free(rtp);
03090 }

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 2081 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, and ast_rtp_protocol::set_rtp_peer.

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00725 {
00726    return rtp->s;
00727 }

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

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

02671 {
02672    struct ast_rtp *bridged = NULL;
02673 
02674    rtp_bridge_lock(rtp);
02675    bridged = rtp->bridged;
02676    rtp_bridge_unlock(rtp);
02677 
02678    return bridged;
02679 }

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

02305 {
02306    int pt;
02307    
02308    rtp_bridge_lock(rtp);
02309    
02310    *astFormats = *nonAstFormats = 0;
02311    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02312       if (rtp->current_RTP_PT[pt].isAstFormat) {
02313          *astFormats |= rtp->current_RTP_PT[pt].code;
02314       } else {
02315          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02316       }
02317    }
02318 
02319    rtp_bridge_unlock(rtp);
02320 }

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

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

02653 {
02654    if ((them->sin_family != AF_INET) ||
02655       (them->sin_port != rtp->them.sin_port) ||
02656       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02657       them->sin_family = AF_INET;
02658       them->sin_port = rtp->them.sin_port;
02659       them->sin_addr = rtp->them.sin_addr;
02660       return 1;
02661    }
02662    return 0;
02663 }

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

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02792 {
02793    double value;
02794    int found;
02795 
02796    value = __ast_rtp_get_qos(rtp, qos, &found);
02797 
02798    if (!found)
02799       return -1;
02800 
02801    snprintf(buf, buflen, "%.0lf", value);
02802 
02803    return 0;
02804 }

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

02726 {
02727    if (rtp == NULL) {
02728       if (option_debug > 1)
02729          ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
02730       return 0;
02731    }
02732    if (option_debug > 1 && rtp->rtcp == NULL) {
02733       ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
02734    }
02735 
02736    switch (value) {
02737    case AST_RTP_TXCOUNT:
02738       return (unsigned int) rtp->txcount;
02739    case AST_RTP_RXCOUNT:
02740       return (unsigned int) rtp->rxcount;
02741    case AST_RTP_TXJITTER:
02742       return (unsigned int) (rtp->rxjitter * 100.0);
02743    case AST_RTP_RXJITTER:
02744       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
02745    case AST_RTP_RXPLOSS:
02746       return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
02747    case AST_RTP_TXPLOSS:
02748       return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
02749    case AST_RTP_RTT:
02750       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
02751    }
02752    return 0;   /* To make the compiler happy */
02753 }

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

02999 {
03000    if (qual && rtp) {
03001       qual->local_ssrc   = rtp->ssrc;
03002       qual->local_jitter = rtp->rxjitter;
03003       qual->local_count  = rtp->rxcount;
03004       qual->remote_ssrc  = rtp->themssrc;
03005       qual->remote_count = rtp->txcount;
03006 
03007       if (rtp->rtcp) {
03008          qual->local_lostpackets  = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
03009          qual->remote_lostpackets = rtp->rtcp->reported_lost;
03010          qual->remote_jitter      = rtp->rtcp->reported_jitter / 65536.0;
03011          qual->rtt                = rtp->rtcp->rtt;
03012       }
03013    }
03014 
03015    switch (qtype) {
03016    case RTPQOS_SUMMARY:
03017       return __ast_rtp_get_quality(rtp);
03018    case RTPQOS_JITTER:
03019       return __ast_rtp_get_quality_jitter(rtp);
03020    case RTPQOS_LOSS:
03021       return __ast_rtp_get_quality_loss(rtp);
03022    case RTPQOS_RTT:
03023       return __ast_rtp_get_quality_rtt(rtp);
03024    }
03025 
03026    return NULL;
03027 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 784 of file rtp.c.

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

Referenced by check_rtp_timeout().

00785 {
00786    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00787       return 0;
00788    return rtp->rtpholdtimeout;
00789 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 792 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00793 {
00794    return rtp->rtpkeepalive;
00795 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 776 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

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

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

Definition at line 812 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00813 {
00814    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00815 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4901 of file rtp.c.

References __ast_rtp_reload(), and ast_cli_register_multiple().

Referenced by main().

04902 {
04903    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04904    __ast_rtp_reload(0);
04905 }

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

02345 {
02346    int pt = 0;
02347 
02348    rtp_bridge_lock(rtp);
02349 
02350    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02351       code == rtp->rtp_lookup_code_cache_code) {
02352       /* Use our cached mapping, to avoid the overhead of the loop below */
02353       pt = rtp->rtp_lookup_code_cache_result;
02354       rtp_bridge_unlock(rtp);
02355       return pt;
02356    }
02357 
02358    /* Check the dynamic list first */
02359    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02360       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02361          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02362          rtp->rtp_lookup_code_cache_code = code;
02363          rtp->rtp_lookup_code_cache_result = pt;
02364          rtp_bridge_unlock(rtp);
02365          return pt;
02366       }
02367    }
02368 
02369    /* Then the static list */
02370    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02371       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02372          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02373          rtp->rtp_lookup_code_cache_code = code;
02374          rtp->rtp_lookup_code_cache_result = pt;
02375          rtp_bridge_unlock(rtp);
02376          return pt;
02377       }
02378    }
02379 
02380    rtp_bridge_unlock(rtp);
02381 
02382    return -1;
02383 }

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

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

Referenced by process_sdp().

02406 {
02407    int format;
02408    unsigned len;
02409    char *end = buf;
02410    char *start = buf;
02411 
02412    if (!buf || !size)
02413       return NULL;
02414 
02415    snprintf(end, size, "0x%x (", capability);
02416 
02417    len = strlen(end);
02418    end += len;
02419    size -= len;
02420    start = end;
02421 
02422    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02423       if (capability & format) {
02424          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02425 
02426          snprintf(end, size, "%s|", name);
02427          len = strlen(end);
02428          end += len;
02429          size -= len;
02430       }
02431    }
02432 
02433    if (start == end)
02434       ast_copy_string(start, "nothing)", size); 
02435    else if (size > 1)
02436       *(end -1) = ')';
02437    
02438    return buf;
02439 }

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

References ARRAY_LEN, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, mimeTypes, and payloadType.

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

02387 {
02388    unsigned int i;
02389 
02390    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02391       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02392          if (isAstFormat &&
02393              (code == AST_FORMAT_G726_AAL2) &&
02394              (options & AST_RTP_OPT_G726_NONSTANDARD))
02395             return "G726-32";
02396          else
02397             return mimeTypes[i].subtype;
02398       }
02399    }
02400 
02401    return "";
02402 }

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 2322 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(), and setup_rtp_connection().

02323 {
02324    struct rtpPayloadType result;
02325 
02326    result.isAstFormat = result.code = 0;
02327 
02328    if (pt < 0 || pt >= MAX_RTP_PT) 
02329       return result; /* bogus payload type */
02330 
02331    /* Start with negotiated codecs */
02332    rtp_bridge_lock(rtp);
02333    result = rtp->current_RTP_PT[pt];
02334    rtp_bridge_unlock(rtp);
02335 
02336    /* If it doesn't exist, check our static RTP type list, just in case */
02337    if (!result.code) 
02338       result = static_RTP_PT[pt];
02339 
02340    return result;
02341 }

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

Definition at line 2167 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, and ast_rtp_protocol::set_rtp_peer.

Referenced by dial_exec_full(), and do_forward().

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

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

References ast_rtp_new_with_bindaddr().

02600 {
02601    struct in_addr ia;
02602 
02603    memset(&ia, 0, sizeof(ia));
02604    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02605 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

02491 {
02492 #ifdef P2P_INTENSE
02493    ast_mutex_init(&rtp->bridge_lock);
02494 #endif
02495 
02496    rtp->them.sin_family = AF_INET;
02497    rtp->us.sin_family = AF_INET;
02498    rtp->ssrc = ast_random();
02499    rtp->seqno = ast_random() & 0xffff;
02500    ast_set_flag(rtp, FLAG_HAS_DTMF);
02501    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02502 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

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

02618 {
02619    if (rtp) {
02620       rtp->set_marker_bit = 1;
02621       if (!rtp->constantssrc) {
02622          rtp->ssrc = ast_random();
02623       }
02624    }
02625 }

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Register an RTP channel client.

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

03857 {
03858    struct ast_rtp_protocol *cur;
03859 
03860    AST_RWLIST_WRLOCK(&protos);
03861    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03862       if (!strcmp(cur->type, proto->type)) {
03863          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03864          AST_RWLIST_UNLOCK(&protos);
03865          return -1;
03866       }
03867    }
03868    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03869    AST_RWLIST_UNLOCK(&protos);
03870    
03871    return 0;
03872 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Unregister an RTP channel client.

Definition at line 3848 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03849 {
03850    AST_RWLIST_WRLOCK(&protos);
03851    AST_RWLIST_REMOVE(&protos, proto, list);
03852    AST_RWLIST_UNLOCK(&protos);
03853 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

02006 {
02007    int i;
02008 
02009    if (!rtp)
02010       return;
02011 
02012    rtp_bridge_lock(rtp);
02013 
02014    for (i = 0; i < MAX_RTP_PT; ++i) {
02015       rtp->current_RTP_PT[i].isAstFormat = 0;
02016       rtp->current_RTP_PT[i].code = 0;
02017    }
02018 
02019    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02020    rtp->rtp_lookup_code_cache_code = 0;
02021    rtp->rtp_lookup_code_cache_result = 0;
02022 
02023    rtp_bridge_unlock(rtp);
02024 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

02046 {
02047    unsigned int i;
02048 
02049    rtp_bridge_lock(dest);
02050    rtp_bridge_lock(src);
02051 
02052    for (i = 0; i < MAX_RTP_PT; ++i) {
02053       dest->current_RTP_PT[i].isAstFormat = 
02054          src->current_RTP_PT[i].isAstFormat;
02055       dest->current_RTP_PT[i].code = 
02056          src->current_RTP_PT[i].code; 
02057    }
02058    dest->rtp_lookup_code_cache_isAstFormat = 0;
02059    dest->rtp_lookup_code_cache_code = 0;
02060    dest->rtp_lookup_code_cache_result = 0;
02061 
02062    rtp_bridge_unlock(src);
02063    rtp_bridge_unlock(dest);
02064 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

02027 {
02028    int i;
02029 
02030    rtp_bridge_lock(rtp);
02031 
02032    /* Initialize to default payload types */
02033    for (i = 0; i < MAX_RTP_PT; ++i) {
02034       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
02035       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
02036    }
02037 
02038    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02039    rtp->rtp_lookup_code_cache_code = 0;
02040    rtp->rtp_lookup_code_cache_result = 0;
02041 
02042    rtp_bridge_unlock(rtp);
02043 }

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

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

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

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

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

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4895 of file rtp.c.

References __ast_rtp_reload().

04896 {
04897    return __ast_rtp_reload(1);
04898 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

02703 {
02704    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02705    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02706    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02707    rtp->lastts = 0;
02708    rtp->lastdigitts = 0;
02709    rtp->lastrxts = 0;
02710    rtp->lastividtimestamp = 0;
02711    rtp->lastovidtimestamp = 0;
02712    rtp->lastitexttimestamp = 0;
02713    rtp->lastotexttimestamp = 0;
02714    rtp->lasteventseqn = 0;
02715    rtp->lastevent = 0;
02716    rtp->lasttxformat = 0;
02717    rtp->lastrxformat = 0;
02718    rtp->dtmf_timeout = 0;
02719    rtp->dtmfsamples = 0;
02720    rtp->seqno = 0;
02721    rtp->rxseqno = 0;
02722 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

03546 {
03547    unsigned int *rtpheader;
03548    int hdrlen = 12;
03549    int res;
03550    int payload;
03551    char data[256];
03552    level = 127 - (level & 0x7f);
03553    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03554 
03555    /* If we have no peer, return immediately */ 
03556    if (!rtp->them.sin_addr.s_addr)
03557       return 0;
03558 
03559    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03560 
03561    /* Get a pointer to the header */
03562    rtpheader = (unsigned int *)data;
03563    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03564    rtpheader[1] = htonl(rtp->lastts);
03565    rtpheader[2] = htonl(rtp->ssrc); 
03566    data[12] = level;
03567    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03568       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03569       if (res <0) 
03570          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));
03571       if (rtp_debug_test_addr(&rtp->them))
03572          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03573                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03574          
03575    }
03576    return 0;
03577 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

03113 {
03114    unsigned int *rtpheader;
03115    int hdrlen = 12, res = 0, i = 0, payload = 0;
03116    char data[256];
03117 
03118    if ((digit <= '9') && (digit >= '0'))
03119       digit -= '0';
03120    else if (digit == '*')
03121       digit = 10;
03122    else if (digit == '#')
03123       digit = 11;
03124    else if ((digit >= 'A') && (digit <= 'D'))
03125       digit = digit - 'A' + 12;
03126    else if ((digit >= 'a') && (digit <= 'd'))
03127       digit = digit - 'a' + 12;
03128    else {
03129       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03130       return 0;
03131    }
03132 
03133    /* If we have no peer, return immediately */ 
03134    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03135       return 0;
03136 
03137    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
03138 
03139    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03140    rtp->send_duration = 160;
03141    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
03142    
03143    /* Get a pointer to the header */
03144    rtpheader = (unsigned int *)data;
03145    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
03146    rtpheader[1] = htonl(rtp->lastdigitts);
03147    rtpheader[2] = htonl(rtp->ssrc); 
03148 
03149    for (i = 0; i < 2; i++) {
03150       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03151       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03152       if (res < 0) 
03153          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
03154             ast_inet_ntoa(rtp->them.sin_addr),
03155             ntohs(rtp->them.sin_port), strerror(errno));
03156       if (rtp_debug_test_addr(&rtp->them))
03157          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03158                 ast_inet_ntoa(rtp->them.sin_addr),
03159                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03160       /* Increment sequence number */
03161       rtp->seqno++;
03162       /* Increment duration */
03163       rtp->send_duration += 160;
03164       /* Clear marker bit and set seqno */
03165       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
03166    }
03167 
03168    /* Since we received a begin, we can safely store the digit and disable any compensation */
03169    rtp->sending_digit = 1;
03170    rtp->send_digit = digit;
03171    rtp->send_payload = payload;
03172 
03173    return 0;
03174 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

03178 {
03179    unsigned int *rtpheader;
03180    int hdrlen = 12, res = 0;
03181    char data[256];
03182 
03183    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03184       return 0;
03185 
03186    /* Setup packet to send */
03187    rtpheader = (unsigned int *)data;
03188    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
03189    rtpheader[1] = htonl(rtp->lastdigitts);
03190    rtpheader[2] = htonl(rtp->ssrc);
03191    rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
03192    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
03193    
03194    /* Transmit */
03195    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03196    if (res < 0)
03197       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
03198          ast_inet_ntoa(rtp->them.sin_addr),
03199          ntohs(rtp->them.sin_port), strerror(errno));
03200    if (rtp_debug_test_addr(&rtp->them))
03201       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03202              ast_inet_ntoa(rtp->them.sin_addr),
03203              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03204 
03205    /* Increment sequence number */
03206    rtp->seqno++;
03207    /* Increment duration */
03208    rtp->send_duration += 160;
03209 
03210    return 0;
03211 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

03215 {
03216    unsigned int *rtpheader;
03217    int hdrlen = 12, res = 0, i = 0;
03218    char data[256];
03219    
03220    /* If no address, then bail out */
03221    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03222       return 0;
03223    
03224    if ((digit <= '9') && (digit >= '0'))
03225       digit -= '0';
03226    else if (digit == '*')
03227       digit = 10;
03228    else if (digit == '#')
03229       digit = 11;
03230    else if ((digit >= 'A') && (digit <= 'D'))
03231       digit = digit - 'A' + 12;
03232    else if ((digit >= 'a') && (digit <= 'd'))
03233       digit = digit - 'a' + 12;
03234    else {
03235       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03236       return 0;
03237    }
03238 
03239    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03240 
03241    rtpheader = (unsigned int *)data;
03242    rtpheader[1] = htonl(rtp->lastdigitts);
03243    rtpheader[2] = htonl(rtp->ssrc);
03244    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03245    /* Set end bit */
03246    rtpheader[3] |= htonl((1 << 23));
03247 
03248    /* Send 3 termination packets */
03249    for (i = 0; i < 3; i++) {
03250       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
03251       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03252       rtp->seqno++;
03253       if (res < 0)
03254          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
03255             ast_inet_ntoa(rtp->them.sin_addr),
03256             ntohs(rtp->them.sin_port), strerror(errno));
03257       if (rtp_debug_test_addr(&rtp->them))
03258          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03259                 ast_inet_ntoa(rtp->them.sin_addr),
03260                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03261    }
03262    rtp->lastts += rtp->send_duration;
03263    rtp->sending_digit = 0;
03264    rtp->send_digit = 0;
03265 
03266    return res;
03267 }

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

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

Referenced by handle_request_invite().

02643 {
02644    rtp->altthem.sin_port = alt->sin_port;
02645    rtp->altthem.sin_addr = alt->sin_addr;
02646    if (rtp->rtcp) {
02647       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02648       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02649    }
02650 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 802 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00803 {
00804    rtp->callback = callback;
00805 }

void ast_rtp_set_constantssrc ( struct ast_rtp rtp  ) 

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

Definition at line 2612 of file rtp.c.

References ast_rtp::constantssrc.

Referenced by create_addr_from_peer(), and handle_request_invite().

02613 {
02614    rtp->constantssrc = 1;
02615 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 797 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00798 {
00799    rtp->data = data;
00800 }

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

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

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

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

02628 {
02629    rtp->them.sin_port = them->sin_port;
02630    rtp->them.sin_addr = them->sin_addr;
02631    if (rtp->rtcp) {
02632       int h = ntohs(them->sin_port);
02633       rtp->rtcp->them.sin_port = htons(h + 1);
02634       rtp->rtcp->them.sin_addr = them->sin_addr;
02635    }
02636    rtp->rxseqno = 0;
02637    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02638    if (strictrtp)
02639       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02640 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 764 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00765 {
00766    rtp->rtpholdtimeout = timeout;
00767 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 770 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00771 {
00772    rtp->rtpkeepalive = period;
00773 }

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

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

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

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

Definition at line 2271 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, MAX_RTP_PT, mimeTypes, payloadType, rtp_bridge_lock(), rtp_bridge_unlock(), subtype, and type.

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

02274 {
02275    unsigned int i;
02276    int found = 0;
02277 
02278    if (pt < 0 || pt >= MAX_RTP_PT) 
02279       return -1; /* bogus payload type */
02280    
02281    rtp_bridge_lock(rtp);
02282 
02283    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02284       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02285           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02286          found = 1;
02287          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02288          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02289              mimeTypes[i].payloadType.isAstFormat &&
02290              (options & AST_RTP_OPT_G726_NONSTANDARD))
02291             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02292          break;
02293       }
02294    }
02295 
02296    rtp_bridge_unlock(rtp);
02297 
02298    return (found ? 0 : -1);
02299 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 758 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 751 of file rtp.c.

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

Referenced by handle_response_invite().

00752 {
00753    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00754    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00755 }

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

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

Referenced by handle_request_bye(), and sip_hangup().

02806                                                                      {
02807    char *audioqos;
02808    char *audioqos_jitter;
02809    char *audioqos_loss;
02810    char *audioqos_rtt;
02811    struct ast_channel *bridge;
02812 
02813    if (!rtp || !chan)
02814       return;
02815 
02816    bridge = ast_bridged_channel(chan);
02817 
02818    audioqos        = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
02819    audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
02820    audioqos_loss   = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
02821    audioqos_rtt    = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
02822 
02823    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
02824    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
02825    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
02826    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
02827 
02828    if (!bridge)
02829       return;
02830 
02831    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
02832    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
02833    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
02834    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
02835 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00818 {
00819    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00820 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00823 {
00824    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00825 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 807 of file rtp.c.

References ast_rtp::nat.

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

00808 {
00809    rtp->nat = nat;
00810 }

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

Definition at line 2607 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

02608 {
02609    return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
02610 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 827 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00828 {
00829    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00830 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

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

02682 {
02683    if (rtp->rtcp) {
02684       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02685    }
02686    if (rtp->red) {
02687       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02688       free(rtp->red);
02689       rtp->red = NULL;
02690    }
02691 
02692    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02693    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02694    if (rtp->rtcp) {
02695       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02696       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02697    }
02698    
02699    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02700 }

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

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00707 {
00708    ast_stun_request(rtp->s, suggestion, username, NULL);
00709 }

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

02257 {
02258    if (pt < 0 || pt >= MAX_RTP_PT)
02259       return; /* bogus payload type */
02260 
02261    rtp_bridge_lock(rtp);
02262    rtp->current_RTP_PT[pt].isAstFormat = 0;
02263    rtp->current_RTP_PT[pt].code = 0;
02264    rtp_bridge_unlock(rtp);
02265 }

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

References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G723_1, 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().

03762 {
03763    struct ast_frame *f;
03764    int codec;
03765    int hdrlen = 12;
03766    int subclass;
03767    
03768 
03769    /* If we have no peer, return immediately */ 
03770    if (!rtp->them.sin_addr.s_addr)
03771       return 0;
03772 
03773    /* If there is no data length, return immediately */
03774    if (!_f->datalen && !rtp->red)
03775       return 0;
03776    
03777    /* Make sure we have enough space for RTP header */
03778    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
03779       ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
03780       return -1;
03781    }
03782 
03783    if (rtp->red) {
03784       /* return 0; */
03785       /* no primary data or generations to send */
03786       if ((_f = red_t140_to_red(rtp->red)) == NULL) 
03787          return 0;
03788    }
03789 
03790    /* The bottom bit of a video subclass contains the marker bit */
03791    subclass = _f->subclass;
03792    if (_f->frametype == AST_FRAME_VIDEO)
03793       subclass &= ~0x1;
03794 
03795    codec = ast_rtp_lookup_code(rtp, 1, subclass);
03796    if (codec < 0) {
03797       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
03798       return -1;
03799    }
03800 
03801    if (rtp->lasttxformat != subclass) {
03802       /* New format, reset the smoother */
03803       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
03804       rtp->lasttxformat = subclass;
03805       if (rtp->smoother)
03806          ast_smoother_free(rtp->smoother);
03807       rtp->smoother = NULL;
03808    }
03809 
03810    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
03811       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
03812       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
03813          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
03814             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));
03815             return -1;
03816          }
03817          if (fmt.flags)
03818             ast_smoother_set_flags(rtp->smoother, fmt.flags);
03819          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));
03820       }
03821    }
03822    if (rtp->smoother) {
03823       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03824          ast_smoother_feed_be(rtp->smoother, _f);
03825       } else {
03826          ast_smoother_feed(rtp->smoother, _f);
03827       }
03828 
03829       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
03830          ast_rtp_raw_write(rtp, f, codec);
03831       }
03832    } else {
03833       /* Don't buffer outgoing frames; send them one-per-packet: */
03834       if (_f->offset < hdrlen) 
03835          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
03836       else
03837          f = _f;
03838       if (f->data.ptr)
03839          ast_rtp_raw_write(rtp, f, codec);
03840       if (f != _f)
03841          ast_frfree(f);
03842    }
03843       
03844    return 0;
03845 }

static AST_RWLIST_HEAD_STATIC ( protos  ,
ast_rtp_protocol   
) [static]

List of current sessions.

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

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

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 3875 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_frame::ptr, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

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

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

04184 {
04185    struct ast_frame *fr = NULL;
04186    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
04187    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
04188    int p0_callback = 0, p1_callback = 0;
04189    enum ast_bridge_result res = AST_BRIDGE_FAILED;
04190 
04191    /* Okay, setup each RTP structure to do P2P forwarding */
04192    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
04193    p2p_set_bridge(p0, p1);
04194    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
04195    p2p_set_bridge(p1, p0);
04196 
04197    /* Activate callback modes if possible */
04198    p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
04199    p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
04200 
04201    /* Now let go of the channel locks and be on our way */
04202    ast_channel_unlock(c0);
04203    ast_channel_unlock(c1);
04204 
04205    ast_poll_channel_add(c0, c1);
04206 
04207    /* Go into a loop forwarding frames until we don't need to anymore */
04208    cs[0] = c0;
04209    cs[1] = c1;
04210    cs[2] = NULL;
04211    for (;;) {
04212       /* If the underlying formats have changed force this bridge to break */
04213       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
04214          ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n");
04215          res = AST_BRIDGE_FAILED_NOWARN;
04216          break;
04217       }
04218       /* Check if anything changed */
04219       if ((c0->tech_pvt != pvt0) ||
04220           (c1->tech_pvt != pvt1) ||
04221           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
04222           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
04223          ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n");
04224          /* 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 */
04225          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
04226             ast_frfree(fr);
04227          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
04228             ast_frfree(fr);
04229          res = AST_BRIDGE_RETRY;
04230          break;
04231       }
04232       /* Wait on a channel to feed us a frame */
04233       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
04234          if (!timeoutms) {
04235             res = AST_BRIDGE_RETRY;
04236             break;
04237          }
04238          if (option_debug > 2)
04239             ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n");
04240          if (ast_check_hangup(c0) || ast_check_hangup(c1))
04241             break;
04242          continue;
04243       }
04244       /* Read in frame from channel */
04245       fr = ast_read(who);
04246       other = (who == c0) ? c1 : c0;
04247       /* Depending on the frame we may need to break out of our bridge */
04248       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
04249              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
04250              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
04251          /* Record received frame and who */
04252          *fo = fr;
04253          *rc = who;
04254          ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
04255          res = AST_BRIDGE_COMPLETE;
04256          break;
04257       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
04258          if ((fr->subclass == AST_CONTROL_HOLD) ||
04259              (fr->subclass == AST_CONTROL_UNHOLD) ||
04260              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
04261              (fr->subclass == AST_CONTROL_SRCUPDATE) ||
04262              (fr->subclass == AST_CONTROL_T38_PARAMETERS)) {
04263             /* If we are going on hold, then break callback mode and P2P bridging */
04264             if (fr->subclass == AST_CONTROL_HOLD) {
04265                if (p0_callback)
04266                   p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
04267                if (p1_callback)
04268                   p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
04269                p2p_set_bridge(p0, NULL);
04270                p2p_set_bridge(p1, NULL);
04271             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
04272                /* If we are off hold, then go back to callback mode and P2P bridging */
04273                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
04274                p2p_set_bridge(p0, p1);
04275                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
04276                p2p_set_bridge(p1, p0);
04277                p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
04278                p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
04279             }
04280             ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
04281             ast_frfree(fr);
04282          } else {
04283             *fo = fr;
04284             *rc = who;
04285             ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
04286             res = AST_BRIDGE_COMPLETE;
04287             break;
04288          }
04289       } else {
04290          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
04291              (fr->frametype == AST_FRAME_DTMF_END) ||
04292              (fr->frametype == AST_FRAME_VOICE) ||
04293              (fr->frametype == AST_FRAME_VIDEO) ||
04294              (fr->frametype == AST_FRAME_IMAGE) ||
04295              (fr->frametype == AST_FRAME_HTML) ||
04296              (fr->frametype == AST_FRAME_MODEM) ||
04297              (fr->frametype == AST_FRAME_TEXT)) {
04298             ast_write(other, fr);
04299          }
04300 
04301          ast_frfree(fr);
04302       }
04303       /* Swap priority */
04304 #ifndef HAVE_EPOLL
04305       cs[2] = cs[0];
04306       cs[0] = cs[1];
04307       cs[1] = cs[2];
04308 #endif
04309    }
04310 
04311    /* If we are totally avoiding the core, then restore our link to it */
04312    if (p0_callback)
04313       p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
04314    if (p1_callback)
04315       p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
04316 
04317    /* Break out of the direct bridge */
04318    p2p_set_bridge(p0, NULL);
04319    p2p_set_bridge(p1, NULL);
04320 
04321    ast_poll_channel_del(c0, c1);
04322 
04323    return res;
04324 }

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

01527 {
01528    int res = 0, payload = 0, bridged_payload = 0, mark;
01529    struct rtpPayloadType rtpPT;
01530    int reconstruct = ntohl(rtpheader[0]);
01531 
01532    /* Get fields from packet */
01533    payload = (reconstruct & 0x7f0000) >> 16;
01534    mark = (((reconstruct & 0x800000) >> 23) != 0);
01535 
01536    /* Check what the payload value should be */
01537    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01538 
01539    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01540    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01541       return -1;
01542 
01543    /* Otherwise adjust bridged payload to match */
01544    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01545 
01546    /* 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 */
01547    if (!bridged->current_RTP_PT[bridged_payload].code)
01548       return -1;
01549 
01550 
01551    /* If the mark bit has not been sent yet... do it now */
01552    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01553       mark = 1;
01554       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01555    }
01556 
01557    /* Reconstruct part of the packet */
01558    reconstruct &= 0xFF80FFFF;
01559    reconstruct |= (bridged_payload << 16);
01560    reconstruct |= (mark << 23);
01561    rtpheader[0] = htonl(reconstruct);
01562 
01563    /* Send the packet back out */
01564    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01565    if (res < 0) {
01566       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01567          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));
01568       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01569          if (option_debug || rtpdebug)
01570             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));
01571          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01572       }
01573       return 0;
01574    } else if (rtp_debug_test_addr(&bridged->them))
01575          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);
01576 
01577    return 0;
01578 }

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

Definition at line 1471 of file rtp.c.

References 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, sanitize_tv(), ast_rtp::seedrxts, stddev_compute(), ast_rtcp::stdev_rxjitter, and ast_frame::subclass.

Referenced by ast_rtp_read().

01472 {
01473    struct timeval now;
01474    double transit;
01475    double current_time;
01476    double d;
01477    double dtv;
01478    double prog;
01479    double normdev_rxjitter_current;
01480    int rate = rtp_get_rate(rtp->f.subclass);
01481 
01482    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01483       gettimeofday(&rtp->rxcore, NULL);
01484       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01485       /* map timestamp to a real time */
01486       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01487       rtp->rxcore.tv_sec -= timestamp / rate;
01488       rtp->rxcore.tv_usec -= (timestamp % rate) * 125;
01489       /* Round to 0.1ms for nice, pretty timestamps */
01490       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01491       sanitize_tv(&rtp->rxcore);
01492    }
01493 
01494    gettimeofday(&now,NULL);
01495    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01496    when->tv_sec = rtp->rxcore.tv_sec + timestamp / rate;
01497    when->tv_usec = rtp->rxcore.tv_usec + (timestamp % rate) * 125;
01498    sanitize_tv(when);
01499    prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
01500    dtv = (double)rtp->drxcore + (double)(prog);
01501    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01502    transit = current_time - dtv;
01503    d = transit - rtp->rxtransit;
01504    rtp->rxtransit = transit;
01505    if (d<0)
01506       d=-d;
01507    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01508 
01509    if (rtp->rtcp) {
01510       if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
01511          rtp->rtcp->maxrxjitter = rtp->rxjitter;
01512       if (rtp->rtcp->rxjitter_count == 1) 
01513          rtp->rtcp->minrxjitter = rtp->rxjitter;
01514       if (rtp->rxjitter < rtp->rtcp->minrxjitter)
01515          rtp->rtcp->minrxjitter = rtp->rxjitter;
01516          
01517       normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
01518       rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
01519 
01520       rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
01521       rtp->rtcp->rxjitter_count++;
01522    }
01523 }

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

Definition at line 3092 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

03093 {
03094    struct timeval t;
03095    long ms;
03096    if (ast_tvzero(rtp->txcore)) {
03097       rtp->txcore = ast_tvnow();
03098       /* Round to 20ms for nice, pretty timestamps */
03099       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
03100    }
03101    /* Use previous txcore if available */
03102    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
03103    ms = ast_tvdiff_ms(t, rtp->txcore);
03104    if (ms < 0)
03105       ms = 0;
03106    /* Use what we just got for next time */
03107    rtp->txcore = t;
03108    return (unsigned int) ms;
03109 }

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

Get channel driver interface structure.

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

02068 {
02069    struct ast_rtp_protocol *cur = NULL;
02070 
02071    AST_RWLIST_RDLOCK(&protos);
02072    AST_RWLIST_TRAVERSE(&protos, cur, list) {
02073       if (cur->type == chan->tech->type)
02074          break;
02075    }
02076    AST_RWLIST_UNLOCK(&protos);
02077 
02078    return cur;
02079 }

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

Definition at line 4643 of file rtp.c.

References ast_cli_args::argc, 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.

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

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

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

04679 {
04680    switch (cmd) {
04681    case CLI_INIT:
04682       e->command = "rtcp set debug {on|off|ip}";
04683       e->usage =
04684          "Usage: rtcp set debug {on|off|ip host[:port]}\n"
04685          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
04686          "       specified, limit the dumped packets to those to and from\n"
04687          "       the specified 'host' with optional port.\n";
04688       return NULL;
04689    case CLI_GENERATE:
04690       return NULL;
04691    }
04692 
04693    if (a->argc == e->args) { /* set on or off */
04694       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
04695          rtcpdebug = 1;
04696          memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
04697          ast_cli(a->fd, "RTCP Debugging Enabled\n");
04698          return CLI_SUCCESS;
04699       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
04700          rtcpdebug = 0;
04701          ast_cli(a->fd, "RTCP Debugging Disabled\n");
04702          return CLI_SUCCESS;
04703       }
04704    } else if (a->argc == e->args +1) { /* ip */
04705       return rtcp_do_debug_ip(a);
04706    }
04707 
04708    return CLI_SHOWUSAGE;   /* default, failure */
04709 }

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

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

04735 {
04736    switch (cmd) {
04737    case CLI_INIT:
04738       e->command = "rtcp set stats {on|off}";
04739       e->usage =
04740          "Usage: rtcp set stats {on|off}\n"
04741          "       Enable/Disable dumping of RTCP stats.\n";
04742       return NULL;
04743    case CLI_GENERATE:
04744       return NULL;
04745    }
04746 
04747    if (a->argc != e->args)
04748       return CLI_SHOWUSAGE;
04749 
04750    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04751       rtcpstats = 1;
04752    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04753       rtcpstats = 0;
04754    else
04755       return CLI_SHOWUSAGE;
04756 
04757    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04758    return CLI_SUCCESS;
04759 }

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

Definition at line 4711 of file rtp.c.

References ast_cli_args::argc, 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.

04712 {
04713    switch (cmd) {
04714    case CLI_INIT:
04715       e->command = "rtcp stats [off]";
04716       e->usage =
04717          "Usage: rtcp stats [off]\n"
04718          "       Enable/Disable dumping of RTCP stats.\n";
04719       return NULL;
04720    case CLI_GENERATE:
04721       return NULL;
04722    }
04723 
04724    if (a->argc < 2 || a->argc > 3)
04725       return CLI_SHOWUSAGE;
04726    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04727       return CLI_SHOWUSAGE;
04728 
04729    rtcpstats = (a->argc == 3) ? 0 : 1;
04730    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04731    return CLI_SUCCESS;
04732 }

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

Definition at line 4575 of file rtp.c.

References ast_cli_args::argc, 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.

04576 {
04577    switch (cmd) {
04578    case CLI_INIT:
04579       e->command = "rtp debug [off|ip]";
04580       e->usage =
04581          "Usage: rtp debug [off]|[ip host[:port]]\n"
04582          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
04583          "       specified, limit the dumped packets to those to and from\n"
04584          "       the specified 'host' with optional port.\n";
04585       return NULL;
04586    case CLI_GENERATE:
04587       return NULL;
04588    }
04589 
04590    if (a->argc < 2 || a->argc > 4)
04591       return CLI_SHOWUSAGE;
04592    if (a->argc == 2) {
04593       rtpdebug = 1;
04594       memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
04595       ast_cli(a->fd, "RTP Debugging Enabled\n");
04596    } else if (a->argc == 3) {
04597       if (strncasecmp(a->argv[2], "off", 3))
04598          return CLI_SHOWUSAGE;
04599       rtpdebug = 0;
04600       ast_cli(a->fd, "RTP Debugging Disabled\n");
04601    } else {
04602       if (strncasecmp(a->argv[2], "ip", 2))
04603          return CLI_SHOWUSAGE;
04604       return rtp_do_debug_ip(a, 1);
04605    }
04606 
04607    return CLI_SUCCESS;
04608 }

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

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

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

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

Definition at line 4761 of file rtp.c.

References ast_cli_args::argc, 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.

04762 {
04763    switch (cmd) {
04764    case CLI_INIT:
04765       e->command = "stun debug [off]";
04766       e->usage =
04767          "Usage: stun debug [off]\n"
04768          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04769          "       debugging\n";
04770       return NULL;
04771    case CLI_GENERATE:
04772       return NULL;
04773    }
04774 
04775    if (a->argc < 2 || a->argc > 3)
04776       return CLI_SHOWUSAGE;
04777    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04778       return CLI_SHOWUSAGE;
04779 
04780    stundebug = (a->argc == 3) ? 0 : 1;
04781    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04782    return CLI_SUCCESS;
04783 }

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

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

04786 {
04787    switch (cmd) {
04788    case CLI_INIT:
04789       e->command = "stun set debug {on|off}";
04790       e->usage =
04791          "Usage: stun set debug {on|off}\n"
04792          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04793          "       debugging\n";
04794       return NULL;
04795    case CLI_GENERATE:
04796       return NULL;
04797    }
04798 
04799    if (a->argc != e->args)
04800       return CLI_SHOWUSAGE;
04801 
04802    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04803       stundebug = 1;
04804    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04805       stundebug = 0;
04806    else
04807       return CLI_SHOWUSAGE;
04808 
04809    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04810    return CLI_SUCCESS;
04811 }

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

Calculate normal deviation.

Definition at line 849 of file rtp.c.

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

00850 {
00851    normdev = normdev * sample_count + sample;
00852    sample_count++;
00853 
00854    return normdev / sample_count;
00855 }

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

04152 {
04153    ast_channel_lock(chan);
04154 
04155    /* Remove the callback from the IO context */
04156    ast_io_remove(rtp->io, iod[0]);
04157 
04158    /* Restore file descriptors */
04159    chan->fds[0] = ast_rtp_fd(rtp);
04160    ast_channel_unlock(chan);
04161 
04162    /* Restore callback mode if previously used */
04163    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
04164       rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp);
04165 
04166    return 0;
04167 }

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

P2P RTP Callback.

Definition at line 4144 of file rtp.c.

Referenced by bridge_p2p_loop().

04145 {
04146    return 0;
04147 }

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

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

Referenced by bridge_p2p_loop().

04171 {
04172    rtp_bridge_lock(rtp0);
04173    rtp0->bridged = rtp1;
04174    rtp_bridge_unlock(rtp0);
04175 }

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

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

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

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

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

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

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

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

05006 {
05007    if (f->datalen > -1) {
05008       struct rtp_red *red = rtp->red;
05009       memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen); 
05010       red->t140.datalen += f->datalen;
05011       red->t140.ts = f->ts;
05012    }
05013 }

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

04922                                                               {
04923    unsigned char *data = red->t140red.data.ptr;
04924    int len = 0;
04925    int i;
04926 
04927    /* replace most aged generation */
04928    if (red->len[0]) {
04929       for (i = 1; i < red->num_gen+1; i++)
04930          len += red->len[i];
04931 
04932       memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 
04933    }
04934    
04935    /* Store length of each generation and primary data length*/
04936    for (i = 0; i < red->num_gen; i++)
04937       red->len[i] = red->len[i+1];
04938    red->len[i] = red->t140.datalen;
04939    
04940    /* write each generation length in red header */
04941    len = red->hdrlen;
04942    for (i = 0; i < red->num_gen; i++)
04943       len += data[i*4+3] = red->len[i];
04944    
04945    /* add primary data to buffer */
04946    memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 
04947    red->t140red.datalen = len + red->t140.datalen;
04948    
04949    /* no primary data and no generations to send */
04950    if (len == red->hdrlen && !red->t140.datalen)
04951       return NULL;
04952 
04953    /* reset t.140 buffer */
04954    red->t140.datalen = 0; 
04955    
04956    return &red->t140red;
04957 }

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

Definition at line 4910 of file rtp.c.

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

Referenced by rtp_red_init().

04911 {
04912    struct ast_rtp *rtp = (struct ast_rtp*) data;
04913    
04914    ast_rtp_write(rtp, &rtp->red->t140); 
04915 
04916    return 1;   
04917 }

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

Definition at line 915 of file rtp.c.

References rtcpdebugaddr.

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

00916 {
00917    if (rtcpdebug == 0)
00918       return 0;
00919    if (rtcpdebugaddr.sin_addr.s_addr) {
00920       if (((ntohs(rtcpdebugaddr.sin_port) != 0)
00921            && (rtcpdebugaddr.sin_port != addr->sin_port))
00922           || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00923          return 0;
00924    }
00925    return 1;
00926 }

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

Definition at line 4545 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_debug_deprecated(), and handle_cli_rtcp_set_debug().

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

static void rtp_bridge_lock ( struct ast_rtp rtp  )  [static]

Definition at line 832 of file rtp.c.

References ast_mutex_lock().

Referenced by ast_rtp_get_bridged(), ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_pt_default(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_rtp_unset_m_type(), and p2p_set_bridge().

00833 {
00834 #ifdef P2P_INTENSE
00835    ast_mutex_lock(&rtp->bridge_lock);
00836 #endif
00837    return;
00838 }

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

00903 {
00904    if (rtpdebug == 0)
00905       return 0;
00906    if (rtpdebugaddr.sin_addr.s_addr) {
00907       if (((ntohs(rtpdebugaddr.sin_port) != 0)
00908            && (rtpdebugaddr.sin_port != addr->sin_port))
00909           || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00910          return 0;
00911    }
00912    return 1;
00913 }

static char* rtp_do_debug_ip ( struct ast_cli_args a,
int  deprecated 
) [static]

Definition at line 4511 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_debug_deprecated(), and handle_cli_rtp_set_debug().

04512 {
04513    struct hostent *hp;
04514    struct ast_hostent ahp;
04515    int port = 0;
04516    char *p, *arg;
04517 
04518    if (deprecated == 1) {
04519       arg = a->argv[3];
04520    } else {
04521       arg = a->argv[4];
04522    }
04523    p = strstr(arg, ":");
04524    if (p) {
04525       *p = '\0';
04526       p++;
04527       port = atoi(p);
04528    }
04529    hp = ast_gethostbyname(arg, &ahp);
04530    if (hp == NULL) {
04531       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04532       return CLI_FAILURE;
04533    }
04534    rtpdebugaddr.sin_family = AF_INET;
04535    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
04536    rtpdebugaddr.sin_port = htons(port);
04537    if (port == 0)
04538       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
04539    else
04540       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
04541    rtpdebug = 1;
04542    return CLI_SUCCESS;
04543 }

static int rtp_get_rate ( int  subclass  )  [static]

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

00737 {
00738    return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
00739 }

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

04967 {
04968    struct rtp_red *r;
04969    int x;
04970    
04971    if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
04972       return -1;
04973 
04974    r->t140.frametype = AST_FRAME_TEXT;
04975    r->t140.subclass = AST_FORMAT_T140RED;
04976    r->t140.data.ptr = &r->buf_data; 
04977 
04978    r->t140.ts = 0;
04979    r->t140red = r->t140;
04980    r->t140red.data.ptr = &r->t140red_data;
04981    r->t140red.datalen = 0;
04982    r->ti = ti;
04983    r->num_gen = num_gen;
04984    r->hdrlen = num_gen * 4 + 1;
04985    r->prev_ts = 0;
04986 
04987    for (x = 0; x < num_gen; x++) {
04988       r->pt[x] = red_data_pt[x];
04989       r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 
04990       r->t140red_data[x*4] = r->pt[x];
04991    }
04992    r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
04993    r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
04994    rtp->red = r;
04995 
04996    r->t140.datalen = 0;
04997    
04998    return 0;
04999 }

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

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

Definition at line 2444 of file rtp.c.

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

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

02445 {
02446    int s = socket(AF_INET, SOCK_DGRAM, 0);
02447    if (s < 0) {
02448       if (type == NULL)
02449          type = "RTP/RTCP";
02450       ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
02451    } else {
02452       long flags = fcntl(s, F_GETFL);
02453       fcntl(s, F_SETFL, flags | O_NONBLOCK);
02454 #ifdef SO_NO_CHECK
02455       if (nochecksums)
02456          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
02457 #endif
02458    }
02459    return s;
02460 }

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

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

01163 {
01164    struct ast_rtp *rtp = cbdata;
01165    struct ast_frame *f;
01166    f = ast_rtp_read(rtp);
01167    if (f) {
01168       if (rtp->callback)
01169          rtp->callback(rtp, f, rtp->data);
01170    }
01171    return 1;
01172 }

static void sanitize_tv ( struct timeval *  tv  )  [static]

Definition at line 1459 of file rtp.c.

Referenced by calc_rxstamp().

01460 {
01461    while (tv->tv_usec < 0) {
01462       tv->tv_usec += 1000000;
01463       tv->tv_sec -= 1;
01464    }
01465    while (tv->tv_usec >= 1000000) {
01466       tv->tv_usec -= 1000000;
01467       tv->tv_sec += 1;
01468    }
01469 }

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

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

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

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

Definition at line 857 of file rtp.c.

References SQUARE.

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

00858 {
00859 /*
00860       for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
00861       return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
00862       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
00863       optimized formula
00864 */
00865 #define SQUARE(x) ((x) * (x))
00866 
00867    stddev = sample_count * stddev;
00868    sample_count++;
00869 
00870    return stddev + 
00871           ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) + 
00872           ( SQUARE(sample - normdev_curent) / sample_count );
00873 
00874 #undef SQUARE
00875 }

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

helper function to print attribute names

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

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

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

00615 {
00616    struct stun_addr *addr = (struct stun_addr *)(attr + 1);
00617    struct sockaddr_in *sa = (struct sockaddr_in *)arg;
00618 
00619    if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
00620       return 1;   /* not us. */
00621    sa->sin_port = addr->port;
00622    sa->sin_addr.s_addr = addr->addr;
00623    return 0;
00624 }

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

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

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

helper function to print message names

Definition at line 377 of file rtp.c.

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

Referenced by stun_handle_packet().

00378 {
00379    switch (msg) {
00380    case STUN_BINDREQ:
00381       return "Binding Request";
00382    case STUN_BINDRESP:
00383       return "Binding Response";
00384    case STUN_BINDERR:
00385       return "Binding Error Response";
00386    case STUN_SECREQ:
00387       return "Shared Secret Request";
00388    case STUN_SECRESP:
00389       return "Shared Secret Response";
00390    case STUN_SECERR:
00391       return "Shared Secret Error Response";
00392    }
00393    return "Non-RFC3489 Message";
00394 }

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

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

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

static void stun_req_id ( struct stun_header req  )  [static]

helper function to generate a random request id

Definition at line 493 of file rtp.c.

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

Referenced by ast_stun_request().

00494 {
00495    int x;
00496    for (x = 0; x < 4; x++)
00497       req->id.id[x] = ast_random();
00498 }

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

wrapper to send an STUN message

Definition at line 486 of file rtp.c.

References stun_header::msglen.

Referenced by ast_stun_request(), and stun_handle_packet().

00487 {
00488    return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00489             (struct sockaddr *)dst, sizeof(*dst));
00490 }

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

Definition at line 714 of file rtp.c.

References sec.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

00715 {
00716    unsigned int sec, usec, frac;
00717    sec = when.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
00718    usec = when.tv_usec;
00719    frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
00720    *msw = sec;
00721    *lsw = frac;
00722 }


Variable Documentation

struct ast_cli_entry cli_rtcp_debug_deprecated = AST_CLI_DEFINE(handle_cli_rtcp_debug_deprecated, "Enable/Disable RTCP debugging") [static]

Definition at line 4814 of file rtp.c.

struct ast_cli_entry cli_rtcp_stats_deprecated = AST_CLI_DEFINE(handle_cli_rtcp_stats_deprecated, "Enable/Disable RTCP stats") [static]

Definition at line 4815 of file rtp.c.

struct ast_cli_entry cli_rtp[] [static]

Definition at line 4818 of file rtp.c.

struct ast_cli_entry cli_rtp_debug_deprecated = AST_CLI_DEFINE(handle_cli_rtp_debug_deprecated, "Enable/Disable RTP debugging") [static]

Definition at line 4813 of file rtp.c.

struct ast_cli_entry cli_stun_debug_deprecated = AST_CLI_DEFINE(handle_cli_stun_debug_deprecated, "Enable/Disable STUN debugging") [static]

Definition at line 4816 of file rtp.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 69 of file rtp.c.

struct { ... } mimeTypes[] [static]

Definition at line 1924 of file rtp.c.

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

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

char* subtype

Definition at line 1926 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1