Wed Aug 18 22:34:32 2010

Asterisk developer's documentation


rtp.c File Reference

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

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

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  frame_list
struct  protos
 List of current sessions. More...
struct  rtp_red
struct  rtpPayloadType
 Structure representing a RTP session.The value of each payload format mapping:. More...
struct  stun_addr
struct  stun_attr
struct  stun_header
struct  stun_state
 here we store credentials extracted from a message More...
struct  stun_trans_id
 STUN support code. More...

Defines

#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))
#define FLAG_3389_WARNING   (1 << 0)
#define FLAG_CALLBACK_MODE   (1 << 6)
#define FLAG_DTMF_COMPENSATE   (1 << 7)
#define FLAG_HAS_DTMF   (1 << 3)
#define FLAG_HAS_STUN   (1 << 8)
#define FLAG_NAT_ACTIVE   (3 << 1)
#define FLAG_NAT_INACTIVE   (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
#define FLAG_P2P_NEED_DTMF   (1 << 5)
#define FLAG_P2P_SENT_MARK   (1 << 4)
#define MAX_TIMESTAMP_SKEW   640
#define RTCP_DEFAULT_INTERVALMS   5000
#define RTCP_JITTER_FORMAT1
#define RTCP_JITTER_FORMAT2   "rxjitter=%f;"
#define RTCP_LOSS_FORMAT1
#define RTCP_LOSS_FORMAT2
#define RTCP_MAX_INTERVALMS   60000
#define RTCP_MIN_INTERVALMS   500
#define RTCP_PT_APP   204
#define RTCP_PT_BYE   203
#define RTCP_PT_FUR   192
#define RTCP_PT_RR   201
#define RTCP_PT_SDES   202
#define RTCP_PT_SR   200
#define RTP_MTU   1200
#define RTP_SEQ_MOD   (1<<16)
#define SQUARE(x)   ((x) * (x))
#define STUN_ACCEPT   (1)
#define STUN_BINDERR   0x0111
#define STUN_BINDREQ   0x0001
 STUN message types 'BIND' refers to transactions used to determine the externally visible addresses. 'SEC' refers to transactions used to establish a session key for subsequent requests. 'SEC' functionality is not supported here.
#define STUN_BINDRESP   0x0101
#define STUN_CHANGE_REQUEST   0x0003
#define STUN_CHANGED_ADDRESS   0x0005
#define STUN_ERROR_CODE   0x0009
#define STUN_IGNORE   (0)
#define STUN_MAPPED_ADDRESS   0x0001
 Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7fff).
#define STUN_MESSAGE_INTEGRITY   0x0008
#define STUN_PASSWORD   0x0007
#define STUN_REFLECTED_FROM   0x000b
#define STUN_RESPONSE_ADDRESS   0x0002
#define STUN_SECERR   0x0112
#define STUN_SECREQ   0x0002
#define STUN_SECRESP   0x0102
#define STUN_SOURCE_ADDRESS   0x0004
#define STUN_UNKNOWN_ATTRIBUTES   0x000a
#define STUN_USERNAME   0x0006

Typedefs

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

Enumerations

enum  strict_rtp_state { STRICT_RTP_OPEN = 0, STRICT_RTP_LEARN, STRICT_RTP_CLOSED }

Functions

static double __ast_rtp_get_qos (struct ast_rtp *rtp, const char *qos, int *found)
static char * __ast_rtp_get_quality (struct ast_rtp *rtp)
static char * __ast_rtp_get_quality_jitter (struct ast_rtp *rtp)
static char * __ast_rtp_get_quality_loss (struct ast_rtp *rtp)
static char * __ast_rtp_get_quality_rtt (struct ast_rtp *rtp)
static int __ast_rtp_reload (int reload)
static void append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sock_in, int *len, int *left)
 append an address to an STUN message
static void append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
 append a string to an STUN message
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
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)
 The RTP bridge.
void ast_rtp_change_source (struct ast_rtp *rtp)
 Indicate that we need to set the marker bit and change the ssrc.
int ast_rtp_codec_getformat (int pt)
 get format from predefined dynamic payload format
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)
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):.
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)
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)
 Indicate that we need to set the marker bit.
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 an RTP channel client.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister an RTP channel client.
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.
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_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Activate payload type.
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)
 Initiate payload type to a known MIME media type for a codec.
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 STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 clear payload 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.
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_framecreate_dtmf_frame (struct ast_rtp *rtp, enum ast_frame_type type)
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 void process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct frame_list *frames)
 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 t.140 data.
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)
 Initalize t.140 redudancy.
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 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 = { .handler = handle_cli_rtcp_debug_deprecated , .summary = "Enable/Disable RTCP debugging" ,__VA_ARGS__ }
static struct ast_cli_entry cli_rtcp_stats_deprecated = { .handler = handle_cli_rtcp_stats_deprecated , .summary = "Enable/Disable RTCP stats" ,__VA_ARGS__ }
static struct ast_cli_entry cli_rtp []
static struct ast_cli_entry cli_rtp_debug_deprecated = { .handler = handle_cli_rtp_debug_deprecated , .summary = "Enable/Disable RTP debugging" ,__VA_ARGS__ }
static struct ast_cli_entry cli_stun_debug_deprecated = { .handler = handle_cli_stun_debug_deprecated , .summary = "Enable/Disable STUN debugging" ,__VA_ARGS__ }
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
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 216 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 223 of file rtp.c.

Referenced by p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 224 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 217 of file rtp.c.

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

#define FLAG_NAT_INACTIVE   (0 << 1)

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

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 221 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

Referenced by __ast_rtp_get_quality_jitter().

#define RTCP_JITTER_FORMAT2   "rxjitter=%f;"

Referenced by __ast_rtp_get_quality_jitter().

#define RTCP_LOSS_FORMAT1

Referenced by __ast_rtp_get_quality_loss().

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

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

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

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

#define STUN_BINDRESP   0x0101

Definition at line 356 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 367 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 369 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 373 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

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

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

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 372 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 371 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 375 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 366 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 360 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 358 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 359 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 368 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 374 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

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


Enumeration Type Documentation

enum strict_rtp_state

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

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

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

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

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

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

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

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

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

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

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

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

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

02977 {
02978    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02979       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
02980          rtp->rtcp->minrtt,
02981          rtp->rtcp->maxrtt,
02982          rtp->rtcp->normdevrtt,
02983          sqrt(rtp->rtcp->stdevrtt)
02984       );
02985    } else {
02986       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available");
02987    }
02988 
02989    return rtp->rtcp->quality_rtt;
02990 }

static int __ast_rtp_reload ( int  reload  )  [static]

Definition at line 4859 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_flags, 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().

04860 {
04861    struct ast_config *cfg;
04862    const char *s;
04863    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04864 
04865    if ((cfg = ast_config_load2("rtp.conf", "rtp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
04866       return 0;
04867 
04868    rtpstart = 5000;
04869    rtpend = 31000;
04870    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04871    strictrtp = STRICT_RTP_OPEN;
04872    if (cfg) {
04873       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
04874          rtpstart = atoi(s);
04875          if (rtpstart < 1024)
04876             rtpstart = 1024;
04877          if (rtpstart > 65535)
04878             rtpstart = 65535;
04879       }
04880       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
04881          rtpend = atoi(s);
04882          if (rtpend < 1024)
04883             rtpend = 1024;
04884          if (rtpend > 65535)
04885             rtpend = 65535;
04886       }
04887       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
04888          rtcpinterval = atoi(s);
04889          if (rtcpinterval == 0)
04890             rtcpinterval = 0; /* Just so we're clear... it's zero */
04891          if (rtcpinterval < RTCP_MIN_INTERVALMS)
04892             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
04893          if (rtcpinterval > RTCP_MAX_INTERVALMS)
04894             rtcpinterval = RTCP_MAX_INTERVALMS;
04895       }
04896       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
04897 #ifdef SO_NO_CHECK
04898          if (ast_false(s))
04899             nochecksums = 1;
04900          else
04901             nochecksums = 0;
04902 #else
04903          if (ast_false(s))
04904             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
04905 #endif
04906       }
04907       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
04908          dtmftimeout = atoi(s);
04909          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
04910             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
04911                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
04912             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04913          };
04914       }
04915       if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
04916          strictrtp = ast_true(s);
04917       }
04918       ast_config_destroy(cfg);
04919    }
04920    if (rtpstart >= rtpend) {
04921       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
04922       rtpstart = 5000;
04923       rtpend = 31000;
04924    }
04925    ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
04926    return 0;
04927 }

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

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Referenced by ast_stun_request(), and stun_handle_packet().

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

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 742 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 2497 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

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

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 1187 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, f, ast_rtp::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().

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

int ast_rtcp_send_h261fur ( void *  data  ) 

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

Definition at line 3304 of file rtp.c.

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

03305 {
03306    struct ast_rtp *rtp = data;
03307    int res;
03308 
03309    rtp->rtcp->sendfur = 1;
03310    res = ast_rtcp_write(data);
03311    
03312    return res;
03313 }

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

03563 {
03564    struct ast_rtp *rtp = (struct ast_rtp *)data;
03565    int res;
03566    
03567    if (!rtp || !rtp->rtcp)
03568       return 0;
03569 
03570    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
03571       res = ast_rtcp_write_sr(data);
03572    else
03573       res = ast_rtcp_write_rr(data);
03574    
03575    return res;
03576 }

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

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

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

Send RTCP sender's report.

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

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

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

Referenced by process_sdp().

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

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 
)

The RTP bridge.

Definition at line 4392 of file rtp.c.

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

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

void ast_rtp_change_source ( struct ast_rtp rtp  ) 

Indicate that we need to set the marker bit and change the ssrc.

Definition at line 2650 of file rtp.c.

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

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

02651 {
02652    if (rtp) {
02653       unsigned int ssrc = ast_random();
02654 
02655       rtp->set_marker_bit = 1;
02656       ast_debug(3, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc);
02657       rtp->ssrc = ssrc;
02658    }
02659 }

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3784 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp_a_audio().

03785 {
03786    if (pt < 0 || pt >= MAX_RTP_PT)
03787       return 0; /* bogus payload type */
03788 
03789    if (static_RTP_PT[pt].isAstFormat)
03790       return static_RTP_PT[pt].code;
03791    else
03792       return 0;
03793 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Get codec preference.

Definition at line 3779 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

03780 {
03781    return &rtp->pref;
03782 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

Definition at line 3733 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, prefs, and ast_rtp::smoother.

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

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

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

Definition at line 3063 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_rtp::s, ast_rtcp::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().

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

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

02112 {
02113    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02114    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02115    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02116    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02117    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;
02118    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;
02119    int srccodec, destcodec, nat_active = 0;
02120 
02121    /* Lock channels */
02122    ast_channel_lock(c0);
02123    if (c1) {
02124       while (ast_channel_trylock(c1)) {
02125          ast_channel_unlock(c0);
02126          usleep(1);
02127          ast_channel_lock(c0);
02128       }
02129    }
02130 
02131    /* Find channel driver interfaces */
02132    destpr = get_proto(c0);
02133    if (c1)
02134       srcpr = get_proto(c1);
02135    if (!destpr) {
02136       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
02137       ast_channel_unlock(c0);
02138       if (c1)
02139          ast_channel_unlock(c1);
02140       return -1;
02141    }
02142    if (!srcpr) {
02143       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
02144       ast_channel_unlock(c0);
02145       if (c1)
02146          ast_channel_unlock(c1);
02147       return -1;
02148    }
02149 
02150    /* Get audio, video  and text interface (if native bridge is possible) */
02151    audio_dest_res = destpr->get_rtp_info(c0, &destp);
02152    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
02153    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
02154    if (srcpr) {
02155       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
02156       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
02157       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
02158    }
02159 
02160    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
02161    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
02162       /* Somebody doesn't want to play... */
02163       ast_channel_unlock(c0);
02164       if (c1)
02165          ast_channel_unlock(c1);
02166       return -1;
02167    }
02168    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)
02169       srccodec = srcpr->get_codec(c1);
02170    else
02171       srccodec = 0;
02172    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)
02173       destcodec = destpr->get_codec(c0);
02174    else
02175       destcodec = 0;
02176    /* Ensure we have at least one matching codec */
02177    if (srcp && !(srccodec & destcodec)) {
02178       ast_channel_unlock(c0);
02179       ast_channel_unlock(c1);
02180       return 0;
02181    }
02182    /* Consider empty media as non-existent */
02183    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
02184       srcp = NULL;
02185    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02186       nat_active = 1;
02187    /* Bridge media early */
02188    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
02189       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02190    ast_channel_unlock(c0);
02191    if (c1)
02192       ast_channel_unlock(c1);
02193    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02194    return 0;
02195 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00726 {
00727    return rtp->s;
00728 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

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

02705 {
02706    struct ast_rtp *bridged = NULL;
02707 
02708    rtp_bridge_lock(rtp);
02709    bridged = rtp->bridged;
02710    rtp_bridge_unlock(rtp);
02711 
02712    return bridged;
02713 }

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

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

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

02335 {
02336    int pt;
02337    
02338    rtp_bridge_lock(rtp);
02339    
02340    *astFormats = *nonAstFormats = 0;
02341    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02342       if (rtp->current_RTP_PT[pt].isAstFormat) {
02343          *astFormats |= rtp->current_RTP_PT[pt].code;
02344       } else {
02345          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02346       }
02347    }
02348 
02349    rtp_bridge_unlock(rtp);
02350 }

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

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

02687 {
02688    if ((them->sin_family != AF_INET) ||
02689       (them->sin_port != rtp->them.sin_port) ||
02690       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02691       them->sin_family = AF_INET;
02692       them->sin_port = rtp->them.sin_port;
02693       them->sin_addr = rtp->them.sin_addr;
02694       return 1;
02695    }
02696    return 0;
02697 }

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

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02826 {
02827    double value;
02828    int found;
02829 
02830    value = __ast_rtp_get_qos(rtp, qos, &found);
02831 
02832    if (!found)
02833       return -1;
02834 
02835    snprintf(buf, buflen, "%.0lf", value);
02836 
02837    return 0;
02838 }

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

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

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 3032 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_rtp_quality::rtt, ast_rtcp::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().

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

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 785 of file rtp.c.

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

Referenced by check_rtp_timeout().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 793 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00794 {
00795    return rtp->rtpkeepalive;
00796 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 777 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

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

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

Definition at line 2699 of file rtp.c.

References ast_rtp::us.

Referenced by add_sdp(), external_rtp_create(), get_our_media_address(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), jingle_create_candidates(), oh323_set_rtp_peer(), skinny_set_rtp_peer(), and start_rtp().

02700 {
02701    *us = rtp->us;
02702 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 813 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4935 of file rtp.c.

References __ast_rtp_reload(), ast_cli_register_multiple(), and cli_rtp.

Referenced by main().

04936 {
04937    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04938    __ast_rtp_reload(0);
04939 }

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

02375 {
02376    int pt = 0;
02377 
02378    rtp_bridge_lock(rtp);
02379 
02380    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02381       code == rtp->rtp_lookup_code_cache_code) {
02382       /* Use our cached mapping, to avoid the overhead of the loop below */
02383       pt = rtp->rtp_lookup_code_cache_result;
02384       rtp_bridge_unlock(rtp);
02385       return pt;
02386    }
02387 
02388    /* Check the dynamic list first */
02389    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02390       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02391          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02392          rtp->rtp_lookup_code_cache_code = code;
02393          rtp->rtp_lookup_code_cache_result = pt;
02394          rtp_bridge_unlock(rtp);
02395          return pt;
02396       }
02397    }
02398 
02399    /* Then the static list */
02400    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02401       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02402          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02403          rtp->rtp_lookup_code_cache_code = code;
02404          rtp->rtp_lookup_code_cache_result = pt;
02405          rtp_bridge_unlock(rtp);
02406          return pt;
02407       }
02408    }
02409 
02410    rtp_bridge_unlock(rtp);
02411 
02412    return -1;
02413 }

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

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

Referenced by process_sdp().

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

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

02417 {
02418    unsigned int i;
02419 
02420    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02421       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02422          if (isAstFormat &&
02423              (code == AST_FORMAT_G726_AAL2) &&
02424              (options & AST_RTP_OPT_G726_NONSTANDARD))
02425             return "G726-32";
02426          else
02427             return mimeTypes[i].subtype;
02428       }
02429    }
02430 
02431    return "";
02432 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 2352 of file rtp.c.

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

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

02353 {
02354    struct rtpPayloadType result;
02355 
02356    result.isAstFormat = result.code = 0;
02357 
02358    if (pt < 0 || pt >= MAX_RTP_PT) 
02359       return result; /* bogus payload type */
02360 
02361    /* Start with negotiated codecs */
02362    rtp_bridge_lock(rtp);
02363    result = rtp->current_RTP_PT[pt];
02364    rtp_bridge_unlock(rtp);
02365 
02366    /* If it doesn't exist, check our static RTP type list, just in case */
02367    if (!result.code) 
02368       result = static_RTP_PT[pt];
02369 
02370    return result;
02371 }

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

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

02198 {
02199    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02200    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02201    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02202    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02203    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;
02204    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; 
02205    int srccodec, destcodec;
02206 
02207    /* Lock channels */
02208    ast_channel_lock(dest);
02209    while (ast_channel_trylock(src)) {
02210       ast_channel_unlock(dest);
02211       usleep(1);
02212       ast_channel_lock(dest);
02213    }
02214 
02215    /* Find channel driver interfaces */
02216    if (!(destpr = get_proto(dest))) {
02217       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
02218       ast_channel_unlock(dest);
02219       ast_channel_unlock(src);
02220       return 0;
02221    }
02222    if (!(srcpr = get_proto(src))) {
02223       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
02224       ast_channel_unlock(dest);
02225       ast_channel_unlock(src);
02226       return 0;
02227    }
02228 
02229    /* Get audio and video interface (if native bridge is possible) */
02230    audio_dest_res = destpr->get_rtp_info(dest, &destp);
02231    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
02232    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
02233    audio_src_res = srcpr->get_rtp_info(src, &srcp);
02234    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
02235    text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
02236 
02237    /* Ensure we have at least one matching codec */
02238    if (srcpr->get_codec)
02239       srccodec = srcpr->get_codec(src);
02240    else
02241       srccodec = 0;
02242    if (destpr->get_codec)
02243       destcodec = destpr->get_codec(dest);
02244    else
02245       destcodec = 0;
02246 
02247    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
02248    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)) {
02249       /* Somebody doesn't want to play... */
02250       ast_channel_unlock(dest);
02251       ast_channel_unlock(src);
02252       return 0;
02253    }
02254    ast_rtp_pt_copy(destp, srcp);
02255    if (vdestp && vsrcp)
02256       ast_rtp_pt_copy(vdestp, vsrcp);
02257    if (tdestp && tsrcp)
02258       ast_rtp_pt_copy(tdestp, tsrcp);
02259    if (media) {
02260       /* Bridge early */
02261       if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02262          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
02263    }
02264    ast_channel_unlock(dest);
02265    ast_channel_unlock(src);
02266    ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
02267    return 1;
02268 }

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

Initializate a RTP session.

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

Definition at line 2629 of file rtp.c.

References ast_rtp_new_with_bindaddr(), io, and sched.

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

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

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

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Indicate that we need to set the marker bit.

Definition at line 2642 of file rtp.c.

References ast_debug, and ast_rtp::set_marker_bit.

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

02643 {
02644    if (rtp) {
02645       rtp->set_marker_bit = 1;
02646       ast_debug(3, "Setting the marker bit due to a source update\n");
02647    }
02648 }

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

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

References ast_calloc, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), errno, LOG_ERROR, rtp_socket(), and sched.

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

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

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

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3882 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03883 {
03884    AST_RWLIST_WRLOCK(&protos);
03885    AST_RWLIST_REMOVE(&protos, proto, list);
03886    AST_RWLIST_UNLOCK(&protos);
03887 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 2035 of file rtp.c.

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

Referenced by gtalk_alloc(), and process_sdp().

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

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

02076 {
02077    unsigned int i;
02078 
02079    rtp_bridge_lock(dest);
02080    rtp_bridge_lock(src);
02081 
02082    for (i = 0; i < MAX_RTP_PT; ++i) {
02083       dest->current_RTP_PT[i].isAstFormat = 
02084          src->current_RTP_PT[i].isAstFormat;
02085       dest->current_RTP_PT[i].code = 
02086          src->current_RTP_PT[i].code; 
02087    }
02088    dest->rtp_lookup_code_cache_isAstFormat = 0;
02089    dest->rtp_lookup_code_cache_code = 0;
02090    dest->rtp_lookup_code_cache_result = 0;
02091 
02092    rtp_bridge_unlock(src);
02093    rtp_bridge_unlock(dest);
02094 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 2056 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, ast_rtp::rtp_lookup_code_cache_result, and static_RTP_PT.

02057 {
02058    int i;
02059 
02060    rtp_bridge_lock(rtp);
02061 
02062    /* Initialize to default payload types */
02063    for (i = 0; i < MAX_RTP_PT; ++i) {
02064       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
02065       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
02066    }
02067 
02068    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02069    rtp->rtp_lookup_code_cache_code = 0;
02070    rtp->rtp_lookup_code_cache_result = 0;
02071 
02072    rtp_bridge_unlock(rtp);
02073 }

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 3614 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(), errno, f, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::set_marker_bit, ast_rtp::ssrc, ast_rtcp::them, ast_rtp::them, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

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

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1581 of file rtp.c.

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

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4929 of file rtp.c.

References __ast_rtp_reload().

04930 {
04931    return __ast_rtp_reload(1);
04932 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

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

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

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

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

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

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

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

Referenced by handle_request_invite().

02677 {
02678    rtp->altthem.sin_port = alt->sin_port;
02679    rtp->altthem.sin_addr = alt->sin_addr;
02680    if (rtp->rtcp) {
02681       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02682       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02683    }
02684 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 803 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 798 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

Definition at line 2274 of file rtp.c.

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

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

02275 {
02276    if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02277       return; /* bogus payload type */
02278 
02279    rtp_bridge_lock(rtp);
02280    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02281    rtp_bridge_unlock(rtp);
02282 } 

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

Definition at line 2661 of file rtp.c.

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

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

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

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 765 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

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

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 771 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

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

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

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

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

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

02304 {
02305    unsigned int i;
02306    int found = 0;
02307 
02308    if (pt < 0 || pt >= MAX_RTP_PT) 
02309       return -1; /* bogus payload type */
02310    
02311    rtp_bridge_lock(rtp);
02312 
02313    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02314       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02315           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02316          found = 1;
02317          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02318          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02319              mimeTypes[i].payloadType.isAstFormat &&
02320              (options & AST_RTP_OPT_G726_NONSTANDARD))
02321             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02322          break;
02323       }
02324    }
02325 
02326    rtp_bridge_unlock(rtp);
02327 
02328    return (found ? 0 : -1);
02329 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 759 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 752 of file rtp.c.

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

Referenced by handle_response_invite().

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

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

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

Referenced by handle_request_bye(), and sip_hangup().

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

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

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

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

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

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 808 of file rtp.c.

References ast_rtp::nat.

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

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

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

Definition at line 2637 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

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

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 828 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

Definition at line 2715 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, ast_rtcp::schedid, rtp_red::schedid, ast_rtp::them, and ast_rtcp::them.

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

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

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

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

Definition at line 707 of file rtp.c.

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

Definition at line 2286 of file rtp.c.

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

Referenced by process_sdp_a_audio(), and process_sdp_a_video().

02287 {
02288    if (pt < 0 || pt >= MAX_RTP_PT)
02289       return; /* bogus payload type */
02290 
02291    rtp_bridge_lock(rtp);
02292    rtp->current_RTP_PT[pt].isAstFormat = 0;
02293    rtp->current_RTP_PT[pt].code = 0;
02294    rtp_bridge_unlock(rtp);
02295 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

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

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

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.

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

References append_attr_string(), ast_log(), ast_select(), stun_attr::attr, LOG_WARNING, STUN_BINDREQ, stun_get_mapped(), stun_handle_packet(), stun_req_id(), stun_send(), and STUN_USERNAME.

Referenced by ast_rtp_stun_request(), and ast_sip_ouraddrfor().

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

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

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, 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().

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

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

References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_unlock, ast_clear_flag, ast_debug, ast_frfree, ast_poll_channel_add(), ast_read(), ast_channel::audiohooks, FLAG_P2P_SENT_MARK, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, p2p_callback_enable(), p2p_set_bridge(), ast_channel::rawreadformat, ast_channel::rawwriteformat, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

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

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_samp2tv(), ast_tvadd(), ast_tvsub(), ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, normdev_compute(), ast_rtcp::normdev_rxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxtransit, ast_rtp::seedrxts, stddev_compute(), ast_rtcp::stdev_rxjitter, and ast_frame::subclass.

Referenced by ast_rtp_read(), and schedule_delivery().

01473 {
01474    struct timeval now;
01475    struct timeval tmp;
01476    double transit;
01477    double current_time;
01478    double d;
01479    double dtv;
01480    double prog;
01481    double normdev_rxjitter_current;
01482    int rate = rtp_get_rate(rtp->f.subclass);
01483 
01484    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01485       gettimeofday(&rtp->rxcore, NULL);
01486       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01487       /* map timestamp to a real time */
01488       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01489       tmp = ast_samp2tv(timestamp, rate);
01490       rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
01491       /* Round to 0.1ms for nice, pretty timestamps */
01492       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01493    }
01494 
01495    gettimeofday(&now,NULL);
01496    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01497    tmp = ast_samp2tv(timestamp, rate);
01498    *when = ast_tvadd(rtp->rxcore, tmp);
01499 
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 3126 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

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

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

Definition at line 878 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_LIST_NEXT, 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().

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

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

Get channel driver interface structure.

Definition at line 2097 of file rtp.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, chan, 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().

02098 {
02099    struct ast_rtp_protocol *cur = NULL;
02100 
02101    AST_RWLIST_RDLOCK(&protos);
02102    AST_RWLIST_TRAVERSE(&protos, cur, list) {
02103       if (cur->type == chan->tech->type)
02104          break;
02105    }
02106    AST_RWLIST_UNLOCK(&protos);
02107 
02108    return cur;
02109 }

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

Definition at line 4677 of file rtp.c.

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

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

static char* handle_cli_rtcp_set_debug ( 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_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(), and ast_cli_entry::usage.

04713 {
04714    switch (cmd) {
04715    case CLI_INIT:
04716       e->command = "rtcp set debug {on|off|ip}";
04717       e->usage =
04718          "Usage: rtcp set debug {on|off|ip host[:port]}\n"
04719          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
04720          "       specified, limit the dumped packets to those to and from\n"
04721          "       the specified 'host' with optional port.\n";
04722       return NULL;
04723    case CLI_GENERATE:
04724       return NULL;
04725    }
04726 
04727    if (a->argc == e->args) { /* set on or off */
04728       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
04729          rtcpdebug = 1;
04730          memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
04731          ast_cli(a->fd, "RTCP Debugging Enabled\n");
04732          return CLI_SUCCESS;
04733       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
04734          rtcpdebug = 0;
04735          ast_cli(a->fd, "RTCP Debugging Disabled\n");
04736          return CLI_SUCCESS;
04737       }
04738    } else if (a->argc == e->args +1) { /* ip */
04739       return rtcp_do_debug_ip(a);
04740    }
04741 
04742    return CLI_SHOWUSAGE;   /* default, failure */
04743 }

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

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

04769 {
04770    switch (cmd) {
04771    case CLI_INIT:
04772       e->command = "rtcp set stats {on|off}";
04773       e->usage =
04774          "Usage: rtcp set stats {on|off}\n"
04775          "       Enable/Disable dumping of RTCP stats.\n";
04776       return NULL;
04777    case CLI_GENERATE:
04778       return NULL;
04779    }
04780 
04781    if (a->argc != e->args)
04782       return CLI_SHOWUSAGE;
04783 
04784    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04785       rtcpstats = 1;
04786    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04787       rtcpstats = 0;
04788    else
04789       return CLI_SHOWUSAGE;
04790 
04791    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04792    return CLI_SUCCESS;
04793 }

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

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

04746 {
04747    switch (cmd) {
04748    case CLI_INIT:
04749       e->command = "rtcp stats [off]";
04750       e->usage =
04751          "Usage: rtcp stats [off]\n"
04752          "       Enable/Disable dumping of RTCP stats.\n";
04753       return NULL;
04754    case CLI_GENERATE:
04755       return NULL;
04756    }
04757 
04758    if (a->argc < 2 || a->argc > 3)
04759       return CLI_SHOWUSAGE;
04760    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04761       return CLI_SHOWUSAGE;
04762 
04763    rtcpstats = (a->argc == 3) ? 0 : 1;
04764    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04765    return CLI_SUCCESS;
04766 }

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

Definition at line 4609 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(), and ast_cli_entry::usage.

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

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

Definition at line 4644 of file rtp.c.

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

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

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

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

04796 {
04797    switch (cmd) {
04798    case CLI_INIT:
04799       e->command = "stun debug [off]";
04800       e->usage =
04801          "Usage: stun debug [off]\n"
04802          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04803          "       debugging\n";
04804       return NULL;
04805    case CLI_GENERATE:
04806       return NULL;
04807    }
04808 
04809    if (a->argc < 2 || a->argc > 3)
04810       return CLI_SHOWUSAGE;
04811    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04812       return CLI_SHOWUSAGE;
04813 
04814    stundebug = (a->argc == 3) ? 0 : 1;
04815    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04816    return CLI_SUCCESS;
04817 }

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

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

04820 {
04821    switch (cmd) {
04822    case CLI_INIT:
04823       e->command = "stun set debug {on|off}";
04824       e->usage =
04825          "Usage: stun set debug {on|off}\n"
04826          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04827          "       debugging\n";
04828       return NULL;
04829    case CLI_GENERATE:
04830       return NULL;
04831    }
04832 
04833    if (a->argc != e->args)
04834       return CLI_SHOWUSAGE;
04835 
04836    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04837       stundebug = 1;
04838    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04839       stundebug = 0;
04840    else
04841       return CLI_SHOWUSAGE;
04842 
04843    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04844    return CLI_SUCCESS;
04845 }

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

Calculate normal deviation.

Definition at line 850 of file rtp.c.

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

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

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 4185 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, chan, ast_channel::fds, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, and rtpread().

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

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

P2P RTP Callback.

Definition at line 4178 of file rtp.c.

Referenced by bridge_p2p_loop().

04179 {
04180    return 0;
04181 }

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

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

Referenced by bridge_p2p_loop().

04205 {
04206    rtp_bridge_lock(rtp0);
04207    rtp0->bridged = rtp1;
04208    rtp_bridge_unlock(rtp0);
04209 }

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

Definition at line 931 of file rtp.c.

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

Referenced by ast_rtp_read().

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

static void process_rfc2833 ( struct ast_rtp rtp,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
struct frame_list frames 
) [static]

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

Definition at line 1022 of file rtp.c.

References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup(), AST_LIST_INSERT_TAIL, ast_log(), ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), create_dtmf_frame(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, FLAG_DTMF_COMPENSATE, frames, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_get_rate(), and ast_frame::samples.

Referenced by ast_rtp_read().

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

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

Process Comfort Noise RTP.

This is incomplete at the moment.

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

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

void red_buffer_t140 ( struct ast_rtp rtp,
struct ast_frame f 
)

Buffer t.140 data.

Parameters:
rtp 
f frame

Definition at line 5039 of file rtp.c.

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

Referenced by sip_write().

05040 {
05041    if (f->datalen > -1) {
05042       struct rtp_red *red = rtp->red;
05043       memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen); 
05044       red->t140.datalen += f->datalen;
05045       red->t140.ts = f->ts;
05046    }
05047 }

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

Construct a redundant frame.

Parameters:
red redundant data structure

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

04956                                                               {
04957    unsigned char *data = red->t140red.data.ptr;
04958    int len = 0;
04959    int i;
04960 
04961    /* replace most aged generation */
04962    if (red->len[0]) {
04963       for (i = 1; i < red->num_gen+1; i++)
04964          len += red->len[i];
04965 
04966       memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 
04967    }
04968    
04969    /* Store length of each generation and primary data length*/
04970    for (i = 0; i < red->num_gen; i++)
04971       red->len[i] = red->len[i+1];
04972    red->len[i] = red->t140.datalen;
04973    
04974    /* write each generation length in red header */
04975    len = red->hdrlen;
04976    for (i = 0; i < red->num_gen; i++)
04977       len += data[i*4+3] = red->len[i];
04978    
04979    /* add primary data to buffer */
04980    memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 
04981    red->t140red.datalen = len + red->t140.datalen;
04982    
04983    /* no primary data and no generations to send */
04984    if (len == red->hdrlen && !red->t140.datalen)
04985       return NULL;
04986 
04987    /* reset t.140 buffer */
04988    red->t140.datalen = 0; 
04989    
04990    return &red->t140red;
04991 }

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

Definition at line 4944 of file rtp.c.

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

Referenced by rtp_red_init().

04945 {
04946    struct ast_rtp *rtp = (struct ast_rtp*) data;
04947    
04948    ast_rtp_write(rtp, &rtp->red->t140); 
04949 
04950    return 1;   
04951 }

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

Definition at line 917 of file rtp.c.

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

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

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

Definition at line 4579 of file rtp.c.

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

Referenced by handle_cli_rtcp_debug_deprecated(), and handle_cli_rtcp_set_debug().

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

static void rtp_bridge_lock ( struct ast_rtp rtp  )  [static]

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

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

static void rtp_bridge_unlock ( struct ast_rtp rtp  )  [static]

Definition at line 841 of file rtp.c.

References ast_mutex_unlock().

Referenced by ast_rtp_get_bridged(), 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().

00842 {
00843 #ifdef P2P_INTENSE
00844    ast_mutex_unlock(&rtp->bridge_lock);
00845 #endif
00846    return;
00847 }

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

Definition at line 904 of file rtp.c.

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

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

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

Definition at line 4545 of file rtp.c.

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

Referenced by handle_cli_rtp_debug_deprecated(), and handle_cli_rtp_set_debug().

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

static int rtp_get_rate ( int  subclass  )  [static]

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

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

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

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

05001 {
05002    struct rtp_red *r;
05003    int x;
05004    
05005    if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
05006       return -1;
05007 
05008    r->t140.frametype = AST_FRAME_TEXT;
05009    r->t140.subclass = AST_FORMAT_T140RED;
05010    r->t140.data.ptr = &r->buf_data; 
05011 
05012    r->t140.ts = 0;
05013    r->t140red = r->t140;
05014    r->t140red.data.ptr = &r->t140red_data;
05015    r->t140red.datalen = 0;
05016    r->ti = ti;
05017    r->num_gen = num_gen;
05018    r->hdrlen = num_gen * 4 + 1;
05019    r->prev_ts = 0;
05020 
05021    for (x = 0; x < num_gen; x++) {
05022       r->pt[x] = red_data_pt[x];
05023       r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 
05024       r->t140red_data[x*4] = r->pt[x];
05025    }
05026    r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
05027    r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
05028    rtp->red = r;
05029 
05030    r->t140.datalen = 0;
05031    
05032    return 0;
05033 }

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

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

Definition at line 2474 of file rtp.c.

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

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

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

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

Definition at line 1175 of file rtp.c.

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

Referenced by p2p_callback_disable().

01176 {
01177    struct ast_rtp *rtp = cbdata;
01178    struct ast_frame *f;
01179    f = ast_rtp_read(rtp);
01180    if (f) {
01181       if (rtp->callback)
01182          rtp->callback(rtp, f, rtp->data);
01183    }
01184    return 1;
01185 }

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

Definition at line 858 of file rtp.c.

References SQUARE.

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

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

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

helper function to print attribute names

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

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

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

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

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 517 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_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(), and STUN_USERNAME.

Referenced by ast_rtp_read(), and ast_stun_request().

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

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

helper function to print message names

Definition at line 378 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

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

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

static void stun_req_id ( struct stun_header req  )  [static]

helper function to generate a random request id

Definition at line 494 of file rtp.c.

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

Referenced by ast_stun_request().

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

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

wrapper to send an STUN message

Definition at line 487 of file rtp.c.

References stun_header::msglen.

Referenced by ast_stun_request(), and stun_handle_packet().

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

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

Definition at line 715 of file rtp.c.

References sec.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


Variable Documentation

struct ast_cli_entry cli_rtcp_debug_deprecated = { .handler = handle_cli_rtcp_debug_deprecated , .summary = "Enable/Disable RTCP debugging" ,__VA_ARGS__ } [static]

Definition at line 4848 of file rtp.c.

struct ast_cli_entry cli_rtcp_stats_deprecated = { .handler = handle_cli_rtcp_stats_deprecated , .summary = "Enable/Disable RTCP stats" ,__VA_ARGS__ } [static]

Definition at line 4849 of file rtp.c.

struct ast_cli_entry cli_rtp[] [static]

Definition at line 4852 of file rtp.c.

Referenced by ast_rtp_init().

struct ast_cli_entry cli_rtp_debug_deprecated = { .handler = handle_cli_rtp_debug_deprecated , .summary = "Enable/Disable RTP debugging" ,__VA_ARGS__ } [static]

Definition at line 4847 of file rtp.c.

struct ast_cli_entry cli_stun_debug_deprecated = { .handler = handle_cli_stun_debug_deprecated , .summary = "Enable/Disable STUN debugging" ,__VA_ARGS__ } [static]

Definition at line 4850 of file rtp.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 69 of file rtp.c.

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

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

struct rtpPayloadType payloadType

Definition at line 1954 of file rtp.c.

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

int rtcpdebug [static]

Are we debugging RTCP?

Definition at line 74 of file rtp.c.

struct sockaddr_in rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 79 of file rtp.c.

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 76 of file rtp.c.

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 75 of file rtp.c.

int rtpdebug [static]

Are we debugging?

Definition at line 73 of file rtp.c.

struct sockaddr_in rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 78 of file rtp.c.

int rtpend = 31000 [static]

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

Definition at line 72 of file rtp.c.

int rtpstart = 5000 [static]

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

Definition at line 71 of file rtp.c.

struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static]

Mapping between Asterisk codecs and rtp payload types.

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

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

Definition at line 1999 of file rtp.c.

Referenced by ast_rtp_codec_getformat(), ast_rtp_lookup_pt(), ast_rtp_pt_default(), and ast_rtp_set_m_type().

int strictrtp [static]

Definition at line 83 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 77 of file rtp.c.

char* subtype

Definition at line 1956 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1955 of file rtp.c.

Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), aji_handle_presence(), amixer_max(), ast_call_forward(), ast_format_str_reduce(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), eventhandler(), g723_len(), h264_decap(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), osp_lookup(), parse_information(), parse_setup(), realtime_require_handler(), require_curl(), require_odbc(), setamixer(), sla_load_config(), and yyparse().


Generated on Wed Aug 18 22:34:32 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7