Wed Oct 28 11:53:11 2009

Asterisk developer's documentation


rtp.c File Reference

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

#include "asterisk.h"
#include <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  protos
 List of current sessions. 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 __fini_protos (void)
static void __init_protos (void)
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)
int ast_stun_request (int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
 Generic STUN request Send a generic stun request to the server specified, possibly waiting for a reply and filling the 'reply' field with the externally visible address. Note that in this case the request will be blocking. (Note, the interface may change slightly in the future).
static enum ast_bridge_result bridge_native_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp *tp0, struct ast_rtp *tp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for true native bridge (reinvite).
static enum ast_bridge_result bridge_p2p_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 Bridge loop for partial native bridge (packet2packet).
static int bridge_p2p_rtp_write (struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen)
 Perform a Packet2Packet RTP write.
static void calc_rxstamp (struct timeval *when, struct ast_rtp *rtp, unsigned int timestamp, int mark)
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
static struct ast_rtp_protocolget_proto (struct ast_channel *chan)
 Get channel driver interface structure.
static char * handle_cli_rtcp_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtcp_set_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtcp_stats_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtp_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_stun_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_stun_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static double normdev_compute (double normdev, double sample, unsigned int sample_count)
 Calculate normal deviation.
static int p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
 Helper function to switch a channel and RTP stream out of callback mode.
static int p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
 P2P RTP Callback.
static void p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1)
 Helper function that sets what an RTP structure is bridged to.
static struct ast_frameprocess_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len)
static struct ast_frameprocess_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp)
 Process RTP DTMF and events according to RFC 2833.
static struct ast_frameprocess_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len)
 Process Comfort Noise RTP.
void red_buffer_t140 (struct ast_rtp *rtp, struct ast_frame *f)
 Buffer t140 from chan_sip.
static struct ast_framered_t140_to_red (struct rtp_red *red)
 Construct a redundant frame.
static int red_write (const void *data)
 Write t140 redundacy frame.
static int rtcp_debug_test_addr (struct sockaddr_in *addr)
static char * rtcp_do_debug_ip (struct ast_cli_args *a)
static void rtp_bridge_lock (struct ast_rtp *rtp)
static void rtp_bridge_unlock (struct ast_rtp *rtp)
static int rtp_debug_test_addr (struct sockaddr_in *addr)
static char * rtp_do_debug_ip (struct ast_cli_args *a, int deprecated)
static int rtp_get_rate (int subclass)
int rtp_red_init (struct ast_rtp *rtp, int ti, int *red_data_pt, int num_gen)
 Initialize t140 redundancy.
static int rtp_socket (const char *type)
 Open RTP or RTCP socket for a session. Print a message on failure.
static int rtpread (int *id, int fd, short events, void *cbdata)
static void sanitize_tv (struct timeval *tv)
static struct ast_framesend_dtmf (struct ast_rtp *rtp, enum ast_frame_type type)
static double stddev_compute (double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
static const char * stun_attr2str (int msg)
 helper function to print attribute names
static int stun_get_mapped (struct stun_attr *attr, void *arg)
 Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_response when called from ast_stun_request.
static int stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
 handle an incoming STUN message.
static const char * stun_msg2str (int msg)
 helper function to print message names
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
static void stun_req_id (struct stun_header *req)
 helper function to generate a random request id
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
 wrapper to send an STUN message
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)

Variables

static struct ast_cli_entry cli_rtcp_debug_deprecated = AST_CLI_DEFINE(handle_cli_rtcp_debug_deprecated, "Enable/Disable RTCP debugging")
static struct ast_cli_entry cli_rtcp_stats_deprecated = AST_CLI_DEFINE(handle_cli_rtcp_stats_deprecated, "Enable/Disable RTCP stats")
static struct ast_cli_entry cli_rtp []
static struct ast_cli_entry cli_rtp_debug_deprecated = AST_CLI_DEFINE(handle_cli_rtp_debug_deprecated, "Enable/Disable RTP debugging")
static struct ast_cli_entry cli_stun_debug_deprecated = AST_CLI_DEFINE(handle_cli_stun_debug_deprecated, "Enable/Disable STUN debugging")
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
struct {
   struct rtpPayloadType   payloadType
   char *   subtype
   char *   type
mimeTypes []
static int rtcpdebug
static struct sockaddr_in rtcpdebugaddr
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static int rtcpstats
static int rtpdebug
static struct sockaddr_in rtpdebugaddr
static int rtpend = 31000
static int rtpstart = 5000
static struct rtpPayloadType static_RTP_PT [MAX_RTP_PT]
 Mapping between Asterisk codecs and rtp payload types.
static int strictrtp
static int stundebug


Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

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

samples

Definition at line 67 of file rtp.c.

Referenced by __ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 215 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 222 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 223 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

Definition at line 219 of file rtp.c.

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

#define FLAG_HAS_STUN   (1 << 8)

Definition at line 224 of file rtp.c.

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 217 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 218 of file rtp.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_P2P_NEED_DTMF   (1 << 5)

Definition at line 221 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 220 of file rtp.c.

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

#define MAX_TIMESTAMP_SKEW   640

Definition at line 51 of file rtp.c.

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

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 54 of file rtp.c.

#define RTCP_JITTER_FORMAT1

#define RTCP_JITTER_FORMAT2   "rxjitter=%f;"

#define RTCP_LOSS_FORMAT1

#define RTCP_LOSS_FORMAT2

Value:

"lost=%d;" \
   "expected=%d;"

Referenced by __ast_rtp_get_quality_loss().

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 56 of file rtp.c.

Referenced by __ast_rtp_reload().

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 55 of file rtp.c.

Referenced by __ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 63 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 62 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

Definition at line 58 of file rtp.c.

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

#define RTCP_PT_RR   201

Definition at line 60 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

Definition at line 61 of file rtp.c.

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

#define RTCP_PT_SR   200

Definition at line 59 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 65 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 53 of file rtp.c.

Referenced by ast_rtp_read().

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

Referenced by stddev_compute().

#define STUN_ACCEPT   (1)

Definition at line 345 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 356 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

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

Definition at line 354 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 355 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 366 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 368 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 372 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 344 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

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

Definition at line 364 of file rtp.c.

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

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 371 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 370 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 374 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 365 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 359 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 357 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 358 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 367 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 373 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 369 of file rtp.c.

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


Typedef Documentation

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

callback type to be invoked on stun responses.

Definition at line 506 of file rtp.c.


Enumeration Type Documentation

Enumerator:
STRICT_RTP_OPEN 
STRICT_RTP_LEARN  No RTP packets should be dropped, all sources accepted
STRICT_RTP_CLOSED  Accept next packet as source

Definition at line 85 of file rtp.c.

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


Function Documentation

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int __ast_rtp_reload ( int  reload  )  [static]

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

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

static void __fini_protos ( void   )  [static]

Definition at line 712 of file rtp.c.

00715 {

static void __init_protos ( void   )  [static]

Definition at line 712 of file rtp.c.

00715 {

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

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

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

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

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

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

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

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

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

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

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 3416 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, ast_rtp::themssrc, and timersub().

Referenced by ast_rtcp_write().

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

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

Send RTCP sender's report.

Definition at line 3283 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, timersub(), timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.

Referenced by ast_rtcp_write().

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

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

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

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

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3751 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp().

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

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

Get codec preference.

Definition at line 3746 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

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

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

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

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

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

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

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

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

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

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

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

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

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

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

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

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

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

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

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

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

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

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

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

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

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

References __ast_rtp_reload(), and ast_cli_register_multiple().

Referenced by main().

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

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

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

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

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

Referenced by process_sdp().

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

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

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

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

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

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

Definition at line 2168 of file rtp.c.

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

Referenced by dial_exec_full(), and do_forward().

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

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

References ast_rtp_new_with_bindaddr().

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

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

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

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

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

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

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Register an RTP channel client.

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

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

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Unregister an RTP channel client.

Definition at line 3849 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

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

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

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

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

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

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

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

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

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

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

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

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

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4896 of file rtp.c.

References __ast_rtp_reload().

04897 {
04898    return __ast_rtp_reload(1);
04899 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

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

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

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

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

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

Referenced by handle_request_invite().

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

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

References ast_rtp::constantssrc.

Referenced by create_addr_from_peer(), and handle_request_invite().

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

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

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

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

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

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

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

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

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

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

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

References ast_netsock_set_qos(), and ast_rtp::s.

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

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

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

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

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

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

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

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

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

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

Referenced by ast_rtp_bridge().

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

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

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

Referenced by ast_rtp_bridge().

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

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

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

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

Definition at line 1472 of file rtp.c.

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

Referenced by ast_rtp_read(), and schedule_delivery().

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

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

Definition at line 3093 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

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

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

Get channel driver interface structure.

Definition at line 2068 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(), ast_rtp_make_compatible(), and ast_udptl_bridge().

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

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

Definition at line 4644 of file rtp.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4611 of file rtp.c.

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

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

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

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

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

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

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

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

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

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

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

P2P RTP Callback.

Definition at line 4145 of file rtp.c.

Referenced by bridge_p2p_loop().

04146 {
04147    return 0;
04148 }

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

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

Referenced by bridge_p2p_loop().

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

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.datalen = len - 1;
01157    rtp->f.samples = 0;
01158    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
01159    f = &rtp->f;
01160    return f;
01161 }

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

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

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

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

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

Definition at line 4911 of file rtp.c.

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

Referenced by rtp_red_init().

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

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

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

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

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

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

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

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

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

Definition at line 2445 of file rtp.c.

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

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

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

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

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

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

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

Definition at line 1460 of file rtp.c.

Referenced by calc_rxstamp().

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

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