Thu Apr 8 01:23:33 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 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 2743 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().

02744 {
02745    *found = 1;
02746 
02747    if (!strcasecmp(qos, "remote_maxjitter"))
02748       return rtp->rtcp->reported_maxjitter * 1000.0;
02749    if (!strcasecmp(qos, "remote_minjitter"))
02750       return rtp->rtcp->reported_minjitter * 1000.0;
02751    if (!strcasecmp(qos, "remote_normdevjitter"))
02752       return rtp->rtcp->reported_normdev_jitter * 1000.0;
02753    if (!strcasecmp(qos, "remote_stdevjitter"))
02754       return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0;
02755 
02756    if (!strcasecmp(qos, "local_maxjitter"))
02757       return rtp->rtcp->maxrxjitter * 1000.0;
02758    if (!strcasecmp(qos, "local_minjitter"))
02759       return rtp->rtcp->minrxjitter * 1000.0;
02760    if (!strcasecmp(qos, "local_normdevjitter"))
02761       return rtp->rtcp->normdev_rxjitter * 1000.0;
02762    if (!strcasecmp(qos, "local_stdevjitter"))
02763       return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0;
02764 
02765    if (!strcasecmp(qos, "maxrtt"))
02766       return rtp->rtcp->maxrtt * 1000.0;
02767    if (!strcasecmp(qos, "minrtt"))
02768       return rtp->rtcp->minrtt * 1000.0;
02769    if (!strcasecmp(qos, "normdevrtt"))
02770       return rtp->rtcp->normdevrtt * 1000.0;
02771    if (!strcasecmp(qos, "stdevrtt"))
02772       return sqrt(rtp->rtcp->stdevrtt) * 1000.0;
02773 
02774    *found = 0;
02775 
02776    return 0.0;
02777 }

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

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

02947 {
02948    /*
02949    *ssrc          our ssrc
02950    *themssrc      their ssrc
02951    *lp            lost packets
02952    *rxjitter      our calculated jitter(rx)
02953    *rxcount       no. received packets
02954    *txjitter      reported jitter of the other end
02955    *txcount       transmitted packets
02956    *rlp           remote lost packets
02957    *rtt           round trip time
02958    */ 
02959 
02960    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02961       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02962          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02963          rtp->ssrc,
02964          rtp->themssrc,
02965          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02966          rtp->rxjitter,
02967          rtp->rxcount,
02968          (double)rtp->rtcp->reported_jitter / 65536.0,
02969          rtp->txcount,
02970          rtp->rtcp->reported_lost,
02971          rtp->rtcp->rtt
02972       );
02973    } else {
02974       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;",
02975          rtp->ssrc,
02976          rtp->themssrc,
02977          rtp->rxjitter,
02978          rtp->rxcount,
02979          rtp->txcount
02980       );
02981    }
02982 
02983    return rtp->rtcp->quality;
02984 }

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

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

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

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

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

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

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

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

02931 {
02932    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02933       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
02934          rtp->rtcp->minrtt,
02935          rtp->rtcp->maxrtt,
02936          rtp->rtcp->normdevrtt,
02937          sqrt(rtp->rtcp->stdevrtt)
02938       );
02939    } else {
02940       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available");
02941    }
02942 
02943    return rtp->rtcp->quality_rtt;
02944 }

static int __ast_rtp_reload ( int  reload  )  [static]

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

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

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

02456 {
02457    struct ast_rtcp *rtcp;
02458 
02459    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
02460       return NULL;
02461    rtcp->s = rtp_socket("RTCP");
02462    rtcp->us.sin_family = AF_INET;
02463    rtcp->them.sin_family = AF_INET;
02464    rtcp->schedid = -1;
02465 
02466    if (rtcp->s < 0) {
02467       ast_free(rtcp);
02468       return NULL;
02469    }
02470 
02471    return rtcp;
02472 }

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

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

03259 {
03260    struct ast_rtp *rtp = data;
03261    int res;
03262 
03263    rtp->rtcp->sendfur = 1;
03264    res = ast_rtcp_write(data);
03265    
03266    return res;
03267 }

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

03517 {
03518    struct ast_rtp *rtp = (struct ast_rtp *)data;
03519    int res;
03520    
03521    if (!rtp || !rtp->rtcp)
03522       return 0;
03523 
03524    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
03525       res = ast_rtcp_write_sr(data);
03526    else
03527       res = ast_rtcp_write_rr(data);
03528    
03529    return res;
03530 }

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

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

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

Send RTCP sender's report.

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

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

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

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

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3738 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp_a_audio().

03739 {
03740    if (pt < 0 || pt >= MAX_RTP_PT)
03741       return 0; /* bogus payload type */
03742 
03743    if (static_RTP_PT[pt].isAstFormat)
03744       return static_RTP_PT[pt].code;
03745    else
03746       return 0;
03747 }

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

Get codec preference.

Definition at line 3733 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

03734 {
03735    return &rtp->pref;
03736 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

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

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

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

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

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

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

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

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

02659 {
02660    struct ast_rtp *bridged = NULL;
02661 
02662    rtp_bridge_lock(rtp);
02663    bridged = rtp->bridged;
02664    rtp_bridge_unlock(rtp);
02665 
02666    return bridged;
02667 }

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

02293 {
02294    int pt;
02295    
02296    rtp_bridge_lock(rtp);
02297    
02298    *astFormats = *nonAstFormats = 0;
02299    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02300       if (rtp->current_RTP_PT[pt].isAstFormat) {
02301          *astFormats |= rtp->current_RTP_PT[pt].code;
02302       } else {
02303          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02304       }
02305    }
02306 
02307    rtp_bridge_unlock(rtp);
02308 }

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

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

02641 {
02642    if ((them->sin_family != AF_INET) ||
02643       (them->sin_port != rtp->them.sin_port) ||
02644       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02645       them->sin_family = AF_INET;
02646       them->sin_port = rtp->them.sin_port;
02647       them->sin_addr = rtp->them.sin_addr;
02648       return 1;
02649    }
02650    return 0;
02651 }

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

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02780 {
02781    double value;
02782    int found;
02783 
02784    value = __ast_rtp_get_qos(rtp, qos, &found);
02785 
02786    if (!found)
02787       return -1;
02788 
02789    snprintf(buf, buflen, "%.0lf", value);
02790 
02791    return 0;
02792 }

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

02714 {
02715    if (rtp == NULL) {
02716       if (option_debug > 1)
02717          ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
02718       return 0;
02719    }
02720    if (option_debug > 1 && rtp->rtcp == NULL) {
02721       ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
02722    }
02723 
02724    switch (value) {
02725    case AST_RTP_TXCOUNT:
02726       return (unsigned int) rtp->txcount;
02727    case AST_RTP_RXCOUNT:
02728       return (unsigned int) rtp->rxcount;
02729    case AST_RTP_TXJITTER:
02730       return (unsigned int) (rtp->rxjitter * 100.0);
02731    case AST_RTP_RXJITTER:
02732       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
02733    case AST_RTP_RXPLOSS:
02734       return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
02735    case AST_RTP_TXPLOSS:
02736       return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
02737    case AST_RTP_RTT:
02738       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
02739    }
02740    return 0;   /* To make the compiler happy */
02741 }

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

02987 {
02988    if (qual && rtp) {
02989       qual->local_ssrc   = rtp->ssrc;
02990       qual->local_jitter = rtp->rxjitter;
02991       qual->local_count  = rtp->rxcount;
02992       qual->remote_ssrc  = rtp->themssrc;
02993       qual->remote_count = rtp->txcount;
02994 
02995       if (rtp->rtcp) {
02996          qual->local_lostpackets  = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02997          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02998          qual->remote_jitter      = rtp->rtcp->reported_jitter / 65536.0;
02999          qual->rtt                = rtp->rtcp->rtt;
03000       }
03001    }
03002 
03003    switch (qtype) {
03004    case RTPQOS_SUMMARY:
03005       return __ast_rtp_get_quality(rtp);
03006    case RTPQOS_JITTER:
03007       return __ast_rtp_get_quality_jitter(rtp);
03008    case RTPQOS_LOSS:
03009       return __ast_rtp_get_quality_loss(rtp);
03010    case RTPQOS_RTT:
03011       return __ast_rtp_get_quality_rtt(rtp);
03012    }
03013 
03014    return NULL;
03015 }

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

References __ast_rtp_reload(), and ast_cli_register_multiple().

Referenced by main().

04890 {
04891    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04892    __ast_rtp_reload(0);
04893 }

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

02333 {
02334    int pt = 0;
02335 
02336    rtp_bridge_lock(rtp);
02337 
02338    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02339       code == rtp->rtp_lookup_code_cache_code) {
02340       /* Use our cached mapping, to avoid the overhead of the loop below */
02341       pt = rtp->rtp_lookup_code_cache_result;
02342       rtp_bridge_unlock(rtp);
02343       return pt;
02344    }
02345 
02346    /* Check the dynamic list first */
02347    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02348       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02349          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02350          rtp->rtp_lookup_code_cache_code = code;
02351          rtp->rtp_lookup_code_cache_result = pt;
02352          rtp_bridge_unlock(rtp);
02353          return pt;
02354       }
02355    }
02356 
02357    /* Then the static list */
02358    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02359       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02360          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02361          rtp->rtp_lookup_code_cache_code = code;
02362          rtp->rtp_lookup_code_cache_result = pt;
02363          rtp_bridge_unlock(rtp);
02364          return pt;
02365       }
02366    }
02367 
02368    rtp_bridge_unlock(rtp);
02369 
02370    return -1;
02371 }

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

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

Referenced by process_sdp().

02394 {
02395    int format;
02396    unsigned len;
02397    char *end = buf;
02398    char *start = buf;
02399 
02400    if (!buf || !size)
02401       return NULL;
02402 
02403    snprintf(end, size, "0x%x (", capability);
02404 
02405    len = strlen(end);
02406    end += len;
02407    size -= len;
02408    start = end;
02409 
02410    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02411       if (capability & format) {
02412          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02413 
02414          snprintf(end, size, "%s|", name);
02415          len = strlen(end);
02416          end += len;
02417          size -= len;
02418       }
02419    }
02420 
02421    if (start == end)
02422       ast_copy_string(start, "nothing)", size); 
02423    else if (size > 1)
02424       *(end -1) = ')';
02425    
02426    return buf;
02427 }

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

02375 {
02376    unsigned int i;
02377 
02378    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02379       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02380          if (isAstFormat &&
02381              (code == AST_FORMAT_G726_AAL2) &&
02382              (options & AST_RTP_OPT_G726_NONSTANDARD))
02383             return "G726-32";
02384          else
02385             return mimeTypes[i].subtype;
02386       }
02387    }
02388 
02389    return "";
02390 }

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

02311 {
02312    struct rtpPayloadType result;
02313 
02314    result.isAstFormat = result.code = 0;
02315 
02316    if (pt < 0 || pt >= MAX_RTP_PT) 
02317       return result; /* bogus payload type */
02318 
02319    /* Start with negotiated codecs */
02320    rtp_bridge_lock(rtp);
02321    result = rtp->current_RTP_PT[pt];
02322    rtp_bridge_unlock(rtp);
02323 
02324    /* If it doesn't exist, check our static RTP type list, just in case */
02325    if (!result.code) 
02326       result = static_RTP_PT[pt];
02327 
02328    return result;
02329 }

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

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

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

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

References ast_rtp_new_with_bindaddr().

02588 {
02589    struct in_addr ia;
02590 
02591    memset(&ia, 0, sizeof(ia));
02592    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02593 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

02479 {
02480 #ifdef P2P_INTENSE
02481    ast_mutex_init(&rtp->bridge_lock);
02482 #endif
02483 
02484    rtp->them.sin_family = AF_INET;
02485    rtp->us.sin_family = AF_INET;
02486    rtp->ssrc = ast_random();
02487    rtp->seqno = ast_random() & 0xffff;
02488    ast_set_flag(rtp, FLAG_HAS_DTMF);
02489    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02490 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

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

02606 {
02607    if (rtp) {
02608       rtp->set_marker_bit = 1;
02609       if (!rtp->constantssrc) {
02610          rtp->ssrc = ast_random();
02611       }
02612    }
02613 }

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Register an RTP channel client.

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

03845 {
03846    struct ast_rtp_protocol *cur;
03847 
03848    AST_RWLIST_WRLOCK(&protos);
03849    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03850       if (!strcmp(cur->type, proto->type)) {
03851          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03852          AST_RWLIST_UNLOCK(&protos);
03853          return -1;
03854       }
03855    }
03856    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03857    AST_RWLIST_UNLOCK(&protos);
03858    
03859    return 0;
03860 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Unregister an RTP channel client.

Definition at line 3836 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03837 {
03838    AST_RWLIST_WRLOCK(&protos);
03839    AST_RWLIST_REMOVE(&protos, proto, list);
03840    AST_RWLIST_UNLOCK(&protos);
03841 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

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

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

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

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

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

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

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

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

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

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

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4883 of file rtp.c.

References __ast_rtp_reload().

04884 {
04885    return __ast_rtp_reload(1);
04886 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

02691 {
02692    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02693    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02694    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02695    rtp->lastts = 0;
02696    rtp->lastdigitts = 0;
02697    rtp->lastrxts = 0;
02698    rtp->lastividtimestamp = 0;
02699    rtp->lastovidtimestamp = 0;
02700    rtp->lastitexttimestamp = 0;
02701    rtp->lastotexttimestamp = 0;
02702    rtp->lasteventseqn = 0;
02703    rtp->lastevent = 0;
02704    rtp->lasttxformat = 0;
02705    rtp->lastrxformat = 0;
02706    rtp->dtmf_timeout = 0;
02707    rtp->dtmfsamples = 0;
02708    rtp->seqno = 0;
02709    rtp->rxseqno = 0;
02710 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

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

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

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

Referenced by handle_request_invite().

02631 {
02632    rtp->altthem.sin_port = alt->sin_port;
02633    rtp->altthem.sin_addr = alt->sin_addr;
02634    if (rtp->rtcp) {
02635       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02636       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02637    }
02638 }

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

References ast_rtp::constantssrc.

Referenced by create_addr_from_peer(), and handle_request_invite().

02601 {
02602    rtp->constantssrc = 1;
02603 }

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

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

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

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

02616 {
02617    rtp->them.sin_port = them->sin_port;
02618    rtp->them.sin_addr = them->sin_addr;
02619    if (rtp->rtcp) {
02620       int h = ntohs(them->sin_port);
02621       rtp->rtcp->them.sin_port = htons(h + 1);
02622       rtp->rtcp->them.sin_addr = them->sin_addr;
02623    }
02624    rtp->rxseqno = 0;
02625    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02626    if (strictrtp)
02627       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02628 }

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

02262 {
02263    unsigned int i;
02264    int found = 0;
02265 
02266    if (pt < 0 || pt >= MAX_RTP_PT) 
02267       return -1; /* bogus payload type */
02268    
02269    rtp_bridge_lock(rtp);
02270 
02271    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02272       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02273           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02274          found = 1;
02275          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02276          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02277              mimeTypes[i].payloadType.isAstFormat &&
02278              (options & AST_RTP_OPT_G726_NONSTANDARD))
02279             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02280          break;
02281       }
02282    }
02283 
02284    rtp_bridge_unlock(rtp);
02285 
02286    return (found ? 0 : -1);
02287 } 

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

02794                                                                      {
02795    char *audioqos;
02796    char *audioqos_jitter;
02797    char *audioqos_loss;
02798    char *audioqos_rtt;
02799    struct ast_channel *bridge;
02800 
02801    if (!rtp || !chan)
02802       return;
02803 
02804    bridge = ast_bridged_channel(chan);
02805 
02806    audioqos        = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
02807    audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
02808    audioqos_loss   = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
02809    audioqos_rtt    = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
02810 
02811    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
02812    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
02813    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
02814    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
02815 
02816    if (!bridge)
02817       return;
02818 
02819    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
02820    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
02821    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
02822    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
02823 }

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

References ast_netsock_set_qos(), and ast_rtp::s.

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

02596 {
02597    return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
02598 }

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

02670 {
02671    if (rtp->rtcp) {
02672       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02673    }
02674    if (rtp->red) {
02675       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02676       free(rtp->red);
02677       rtp->red = NULL;
02678    }
02679 
02680    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02681    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02682    if (rtp->rtcp) {
02683       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02684       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02685    }
02686    
02687    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02688 }

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

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

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

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

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

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

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

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

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

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

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

Definition at line 1459 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

Definition at line 3080 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

03081 {
03082    struct timeval t;
03083    long ms;
03084    if (ast_tvzero(rtp->txcore)) {
03085       rtp->txcore = ast_tvnow();
03086       /* Round to 20ms for nice, pretty timestamps */
03087       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
03088    }
03089    /* Use previous txcore if available */
03090    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
03091    ms = ast_tvdiff_ms(t, rtp->txcore);
03092    if (ms < 0)
03093       ms = 0;
03094    /* Use what we just got for next time */
03095    rtp->txcore = t;
03096    return (unsigned int) ms;
03097 }

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

Get channel driver interface structure.

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

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

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

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

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

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

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

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

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

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

04723 {
04724    switch (cmd) {
04725    case CLI_INIT:
04726       e->command = "rtcp set stats {on|off}";
04727       e->usage =
04728          "Usage: rtcp set stats {on|off}\n"
04729          "       Enable/Disable dumping of RTCP stats.\n";
04730       return NULL;
04731    case CLI_GENERATE:
04732       return NULL;
04733    }
04734 
04735    if (a->argc != e->args)
04736       return CLI_SHOWUSAGE;
04737 
04738    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04739       rtcpstats = 1;
04740    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04741       rtcpstats = 0;
04742    else
04743       return CLI_SHOWUSAGE;
04744 
04745    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04746    return CLI_SUCCESS;
04747 }

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

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

04700 {
04701    switch (cmd) {
04702    case CLI_INIT:
04703       e->command = "rtcp stats [off]";
04704       e->usage =
04705          "Usage: rtcp stats [off]\n"
04706          "       Enable/Disable dumping of RTCP stats.\n";
04707       return NULL;
04708    case CLI_GENERATE:
04709       return NULL;
04710    }
04711 
04712    if (a->argc < 2 || a->argc > 3)
04713       return CLI_SHOWUSAGE;
04714    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04715       return CLI_SHOWUSAGE;
04716 
04717    rtcpstats = (a->argc == 3) ? 0 : 1;
04718    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04719    return CLI_SUCCESS;
04720 }

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

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

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

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

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

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

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

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

04750 {
04751    switch (cmd) {
04752    case CLI_INIT:
04753       e->command = "stun debug [off]";
04754       e->usage =
04755          "Usage: stun debug [off]\n"
04756          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04757          "       debugging\n";
04758       return NULL;
04759    case CLI_GENERATE:
04760       return NULL;
04761    }
04762 
04763    if (a->argc < 2 || a->argc > 3)
04764       return CLI_SHOWUSAGE;
04765    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04766       return CLI_SHOWUSAGE;
04767 
04768    stundebug = (a->argc == 3) ? 0 : 1;
04769    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04770    return CLI_SUCCESS;
04771 }

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

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

04774 {
04775    switch (cmd) {
04776    case CLI_INIT:
04777       e->command = "stun set debug {on|off}";
04778       e->usage =
04779          "Usage: stun set debug {on|off}\n"
04780          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04781          "       debugging\n";
04782       return NULL;
04783    case CLI_GENERATE:
04784       return NULL;
04785    }
04786 
04787    if (a->argc != e->args)
04788       return CLI_SHOWUSAGE;
04789 
04790    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04791       stundebug = 1;
04792    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04793       stundebug = 0;
04794    else
04795       return CLI_SHOWUSAGE;
04796 
04797    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04798    return CLI_SUCCESS;
04799 }

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

04140 {
04141    ast_channel_lock(chan);
04142 
04143    /* Remove the callback from the IO context */
04144    ast_io_remove(rtp->io, iod[0]);
04145 
04146    /* Restore file descriptors */
04147    chan->fds[0] = ast_rtp_fd(rtp);
04148    ast_channel_unlock(chan);
04149 
04150    /* Restore callback mode if previously used */
04151    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
04152       rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp);
04153 
04154    return 0;
04155 }

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

P2P RTP Callback.

Definition at line 4132 of file rtp.c.

Referenced by bridge_p2p_loop().

04133 {
04134    return 0;
04135 }

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

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

Referenced by bridge_p2p_loop().

04159 {
04160    rtp_bridge_lock(rtp0);
04161    rtp0->bridged = rtp1;
04162    rtp_bridge_unlock(rtp0);
04163 }

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

04994 {
04995    if (f->datalen > -1) {
04996       struct rtp_red *red = rtp->red;
04997       memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen); 
04998       red->t140.datalen += f->datalen;
04999       red->t140.ts = f->ts;
05000    }
05001 }

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

04910                                                               {
04911    unsigned char *data = red->t140red.data.ptr;
04912    int len = 0;
04913    int i;
04914 
04915    /* replace most aged generation */
04916    if (red->len[0]) {
04917       for (i = 1; i < red->num_gen+1; i++)
04918          len += red->len[i];
04919 
04920       memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 
04921    }
04922    
04923    /* Store length of each generation and primary data length*/
04924    for (i = 0; i < red->num_gen; i++)
04925       red->len[i] = red->len[i+1];
04926    red->len[i] = red->t140.datalen;
04927    
04928    /* write each generation length in red header */
04929    len = red->hdrlen;
04930    for (i = 0; i < red->num_gen; i++)
04931       len += data[i*4+3] = red->len[i];
04932    
04933    /* add primary data to buffer */
04934    memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 
04935    red->t140red.datalen = len + red->t140.datalen;
04936    
04937    /* no primary data and no generations to send */
04938    if (len == red->hdrlen && !red->t140.datalen)
04939       return NULL;
04940 
04941    /* reset t.140 buffer */
04942    red->t140.datalen = 0; 
04943    
04944    return &red->t140red;
04945 }

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

Definition at line 4898 of file rtp.c.

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

Referenced by rtp_red_init().

04899 {
04900    struct ast_rtp *rtp = (struct ast_rtp*) data;
04901    
04902    ast_rtp_write(rtp, &rtp->red->t140); 
04903 
04904    return 1;   
04905 }

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

04534 {
04535    struct hostent *hp;
04536    struct ast_hostent ahp;
04537    int port = 0;
04538    char *p, *arg;
04539 
04540    arg = a->argv[3];
04541    p = strstr(arg, ":");
04542    if (p) {
04543       *p = '\0';
04544       p++;
04545       port = atoi(p);
04546    }
04547    hp = ast_gethostbyname(arg, &ahp);
04548    if (hp == NULL) {
04549       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04550       return CLI_FAILURE;
04551    }
04552    rtcpdebugaddr.sin_family = AF_INET;
04553    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
04554    rtcpdebugaddr.sin_port = htons(port);
04555    if (port == 0)
04556       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
04557    else
04558       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
04559    rtcpdebug = 1;
04560    return CLI_SUCCESS;
04561 }

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

04500 {
04501    struct hostent *hp;
04502    struct ast_hostent ahp;
04503    int port = 0;
04504    char *p, *arg;
04505 
04506    if (deprecated == 1) {
04507       arg = a->argv[3];
04508    } else {
04509       arg = a->argv[4];
04510    }
04511    p = strstr(arg, ":");
04512    if (p) {
04513       *p = '\0';
04514       p++;
04515       port = atoi(p);
04516    }
04517    hp = ast_gethostbyname(arg, &ahp);
04518    if (hp == NULL) {
04519       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04520       return CLI_FAILURE;
04521    }
04522    rtpdebugaddr.sin_family = AF_INET;
04523    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
04524    rtpdebugaddr.sin_port = htons(port);
04525    if (port == 0)
04526       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
04527    else
04528       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
04529    rtpdebug = 1;
04530    return CLI_SUCCESS;
04531 }

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

04955 {
04956    struct rtp_red *r;
04957    int x;
04958    
04959    if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
04960       return -1;
04961 
04962    r->t140.frametype = AST_FRAME_TEXT;
04963    r->t140.subclass = AST_FORMAT_T140RED;
04964    r->t140.data.ptr = &r->buf_data; 
04965 
04966    r->t140.ts = 0;
04967    r->t140red = r->t140;
04968    r->t140red.data.ptr = &r->t140red_data;
04969    r->t140red.datalen = 0;
04970    r->ti = ti;
04971    r->num_gen = num_gen;
04972    r->hdrlen = num_gen * 4 + 1;
04973    r->prev_ts = 0;
04974 
04975    for (x = 0; x < num_gen; x++) {
04976       r->pt[x] = red_data_pt[x];
04977       r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 
04978       r->t140red_data[x*4] = r->pt[x];
04979    }
04980    r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
04981    r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
04982    rtp->red = r;
04983 
04984    r->t140.datalen = 0;
04985    
04986    return 0;
04987 }

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

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

Definition at line 2432 of file rtp.c.

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

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

02433 {
02434    int s = socket(AF_INET, SOCK_DGRAM, 0);
02435    if (s < 0) {
02436       if (type == NULL)
02437          type = "RTP/RTCP";
02438       ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
02439    } else {
02440       long flags = fcntl(s, F_GETFL);
02441       fcntl(s, F_SETFL, flags | O_NONBLOCK);
02442 #ifdef SO_NO_CHECK
02443       if (nochecksums)
02444          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
02445 #endif
02446    }
02447    return s;
02448 }

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

struct ast_cli_entry cli_rtp[] [static]

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

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 69 of file rtp.c.

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

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

int strictrtp [static]

Definition at line 83 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 77 of file rtp.c.

char* subtype

Definition at line 1914 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Generated on 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1