Fri Jul 24 00:41:57 2009

Asterisk developer's documentation


rtp.c File Reference

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

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

Go to the source code of this file.

Data Structures

struct  ast_rtcp
 Structure defining an RTCP session. More...
struct  ast_rtp
 RTP session description. More...
struct  protos
 List of current sessions. More...
struct  rtp_red
struct  rtpPayloadType
 Structure representing a RTP session.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   3000
#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.
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)
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_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_rtp_protocolget_proto (struct ast_channel *chan)
 Get channel driver interface structure.
static char * handle_cli_rtcp_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtcp_set_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtcp_stats_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtp_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_stun_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_stun_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static double normdev_compute (double normdev, double sample, unsigned int sample_count)
 Calculate normal deviation.
static int p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
 Helper function to switch a channel and RTP stream out of callback mode.
static int p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
 P2P RTP Callback.
static void p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1)
 Helper function that sets what an RTP structure is bridged to.
static struct ast_frameprocess_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len)
static struct ast_frameprocess_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp)
 Process RTP DTMF and events according to RFC 2833.
static struct ast_frameprocess_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len)
 Process Comfort Noise RTP.
void red_buffer_t140 (struct ast_rtp *rtp, struct ast_frame *f)
 Buffer 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 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 struct ast_framesend_dtmf (struct ast_rtp *rtp, enum ast_frame_type type)
static double stddev_compute (double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
static const char * stun_attr2str (int msg)
 helper function to print attribute names
static int stun_get_mapped (struct stun_attr *attr, void *arg)
 Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_response when called from ast_stun_request.
static int stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
 handle an incoming STUN message.
static const char * stun_msg2str (int msg)
 helper function to print message names
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
static void stun_req_id (struct stun_header *req)
 helper function to generate a random request id
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
 wrapper to send an STUN message
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)

Variables

static struct ast_cli_entry cli_rtcp_debug_deprecated = { .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   3000

samples

Definition at line 67 of file rtp.c.

Referenced by __ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 212 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 219 of file rtp.c.

Referenced by p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 220 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

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

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

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

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

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

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

#define STUN_BINDRESP   0x0101

Definition at line 351 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 362 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 364 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 368 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

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

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

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 367 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 366 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 370 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 361 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 355 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 353 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 354 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 363 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 369 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 365 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 502 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 2680 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().

02681 {
02682    *found = 1;
02683 
02684    if (!strcasecmp(qos, "remote_maxjitter"))
02685       return rtp->rtcp->reported_maxjitter * 1000.0;
02686    if (!strcasecmp(qos, "remote_minjitter"))
02687       return rtp->rtcp->reported_minjitter * 1000.0;
02688    if (!strcasecmp(qos, "remote_normdevjitter"))
02689       return rtp->rtcp->reported_normdev_jitter * 1000.0;
02690    if (!strcasecmp(qos, "remote_stdevjitter"))
02691       return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0;
02692 
02693    if (!strcasecmp(qos, "local_maxjitter"))
02694       return rtp->rtcp->maxrxjitter * 1000.0;
02695    if (!strcasecmp(qos, "local_minjitter"))
02696       return rtp->rtcp->minrxjitter * 1000.0;
02697    if (!strcasecmp(qos, "local_normdevjitter"))
02698       return rtp->rtcp->normdev_rxjitter * 1000.0;
02699    if (!strcasecmp(qos, "local_stdevjitter"))
02700       return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0;
02701 
02702    if (!strcasecmp(qos, "maxrtt"))
02703       return rtp->rtcp->maxrtt * 1000.0;
02704    if (!strcasecmp(qos, "minrtt"))
02705       return rtp->rtcp->minrtt * 1000.0;
02706    if (!strcasecmp(qos, "normdevrtt"))
02707       return rtp->rtcp->normdevrtt * 1000.0;
02708    if (!strcasecmp(qos, "stdevrtt"))
02709       return sqrt(rtp->rtcp->stdevrtt) * 1000.0;
02710 
02711    *found = 0;
02712 
02713    return 0.0;
02714 }

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

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

02884 {
02885    /*
02886    *ssrc          our ssrc
02887    *themssrc      their ssrc
02888    *lp            lost packets
02889    *rxjitter      our calculated jitter(rx)
02890    *rxcount       no. received packets
02891    *txjitter      reported jitter of the other end
02892    *txcount       transmitted packets
02893    *rlp           remote lost packets
02894    *rtt           round trip time
02895    */ 
02896 
02897    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02898       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02899          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02900          rtp->ssrc,
02901          rtp->themssrc,
02902          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02903          rtp->rxjitter,
02904          rtp->rxcount,
02905          (double)rtp->rtcp->reported_jitter / 65536.0,
02906          rtp->txcount,
02907          rtp->rtcp->reported_lost,
02908          rtp->rtcp->rtt
02909       );
02910    } else {
02911       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;",
02912          rtp->ssrc,
02913          rtp->themssrc,
02914          rtp->rxjitter,
02915          rtp->rxcount,
02916          rtp->txcount
02917       );
02918    }
02919 
02920    return rtp->rtcp->quality;
02921 }

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

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

02763 {
02764    /*
02765    *ssrc          our ssrc
02766    *themssrc      their ssrc
02767    *lp            lost packets
02768    *rxjitter      our calculated jitter(rx)
02769    *rxcount       no. received packets
02770    *txjitter      reported jitter of the other end
02771    *txcount       transmitted packets
02772    *rlp           remote lost packets
02773    *rtt           round trip time
02774    */
02775 #define RTCP_JITTER_FORMAT1 \
02776    "minrxjitter=%f;" \
02777    "maxrxjitter=%f;" \
02778    "avgrxjitter=%f;" \
02779    "stdevrxjitter=%f;" \
02780    "reported_minjitter=%f;" \
02781    "reported_maxjitter=%f;" \
02782    "reported_avgjitter=%f;" \
02783    "reported_stdevjitter=%f;"
02784 
02785 #define RTCP_JITTER_FORMAT2 \
02786    "rxjitter=%f;"
02787 
02788    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02789       snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1,
02790          rtp->rtcp->minrxjitter,
02791          rtp->rtcp->maxrxjitter,
02792          rtp->rtcp->normdev_rxjitter,
02793          sqrt(rtp->rtcp->stdev_rxjitter),
02794          rtp->rtcp->reported_minjitter,
02795          rtp->rtcp->reported_maxjitter,
02796          rtp->rtcp->reported_normdev_jitter,
02797          sqrt(rtp->rtcp->reported_stdev_jitter)
02798       );
02799    } else {
02800       snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2,
02801          rtp->rxjitter
02802       );
02803    }
02804 
02805    return rtp->rtcp->quality_jitter;
02806 
02807 #undef RTCP_JITTER_FORMAT1
02808 #undef RTCP_JITTER_FORMAT2
02809 }

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

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

02812 {
02813    unsigned int lost;
02814    unsigned int extended;
02815    unsigned int expected;
02816    int fraction;
02817 
02818 #define RTCP_LOSS_FORMAT1 \
02819    "minrxlost=%f;" \
02820    "maxrxlost=%f;" \
02821    "avgrxlostr=%f;" \
02822    "stdevrxlost=%f;" \
02823    "reported_minlost=%f;" \
02824    "reported_maxlost=%f;" \
02825    "reported_avglost=%f;" \
02826    "reported_stdevlost=%f;"
02827 
02828 #define RTCP_LOSS_FORMAT2 \
02829    "lost=%d;" \
02830    "expected=%d;"
02831    
02832    if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) {
02833       snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1,
02834          rtp->rtcp->minrxlost,
02835          rtp->rtcp->maxrxlost,
02836          rtp->rtcp->normdev_rxlost,
02837          sqrt(rtp->rtcp->stdev_rxlost),
02838          rtp->rtcp->reported_minlost,
02839          rtp->rtcp->reported_maxlost,
02840          rtp->rtcp->reported_normdev_lost,
02841          sqrt(rtp->rtcp->reported_stdev_lost)
02842       );
02843    } else {
02844       extended = rtp->cycles + rtp->lastrxseqno;
02845       expected = extended - rtp->seedrxseqno + 1;
02846       if (rtp->rxcount > expected) 
02847          expected += rtp->rxcount - expected;
02848       lost = expected - rtp->rxcount;
02849 
02850       if (!expected || lost <= 0)
02851          fraction = 0;
02852       else
02853          fraction = (lost << 8) / expected;
02854 
02855       snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2,
02856          lost,
02857          expected
02858       );
02859    }
02860 
02861    return rtp->rtcp->quality_loss;
02862 
02863 #undef RTCP_LOSS_FORMAT1
02864 #undef RTCP_LOSS_FORMAT2
02865 }

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

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

02868 {
02869    if (rtp->rtcp && rtp->rtcp->rtcp_info) {
02870       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
02871          rtp->rtcp->minrtt,
02872          rtp->rtcp->maxrtt,
02873          rtp->rtcp->normdevrtt,
02874          sqrt(rtp->rtcp->stdevrtt)
02875       );
02876    } else {
02877       snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available");
02878    }
02879 
02880    return rtp->rtcp->quality_rtt;
02881 }

static int __ast_rtp_reload ( int  reload  )  [static]

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

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

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

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Referenced by ast_stun_request(), and stun_handle_packet().

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

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 732 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

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

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 2409 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

02410 {
02411    struct ast_rtcp *rtcp;
02412 
02413    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
02414       return NULL;
02415    rtcp->s = rtp_socket("RTCP");
02416    rtcp->us.sin_family = AF_INET;
02417    rtcp->them.sin_family = AF_INET;
02418    rtcp->schedid = -1;
02419 
02420    if (rtcp->s < 0) {
02421       ast_free(rtcp);
02422       return NULL;
02423    }
02424 
02425    return rtcp;
02426 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 1130 of file rtp.c.

References ast_rtcp::accumulated_transit, 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().

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

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

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

03196 {
03197    struct ast_rtp *rtp = data;
03198    int res;
03199 
03200    rtp->rtcp->sendfur = 1;
03201    res = ast_rtcp_write(data);
03202    
03203    return res;
03204 }

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

03454 {
03455    struct ast_rtp *rtp = (struct ast_rtp *)data;
03456    int res;
03457    
03458    if (!rtp || !rtp->rtcp)
03459       return 0;
03460 
03461    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
03462       res = ast_rtcp_write_sr(data);
03463    else
03464       res = ast_rtcp_write_rr(data);
03465    
03466    return res;
03467 }

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

03341 {
03342    struct ast_rtp *rtp = (struct ast_rtp *)data;
03343    int res;
03344    int len = 32;
03345    unsigned int lost;
03346    unsigned int extended;
03347    unsigned int expected;
03348    unsigned int expected_interval;
03349    unsigned int received_interval;
03350    int lost_interval;
03351    struct timeval now;
03352    unsigned int *rtcpheader;
03353    char bdata[1024];
03354    struct timeval dlsr;
03355    int fraction;
03356 
03357    double rxlost_current;
03358    
03359    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
03360       return 0;
03361      
03362    if (!rtp->rtcp->them.sin_addr.s_addr) {
03363       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
03364       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03365       return 0;
03366    }
03367 
03368    extended = rtp->cycles + rtp->lastrxseqno;
03369    expected = extended - rtp->seedrxseqno + 1;
03370    lost = expected - rtp->rxcount;
03371    expected_interval = expected - rtp->rtcp->expected_prior;
03372    rtp->rtcp->expected_prior = expected;
03373    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
03374    rtp->rtcp->received_prior = rtp->rxcount;
03375    lost_interval = expected_interval - received_interval;
03376 
03377    if (lost_interval <= 0)
03378       rtp->rtcp->rxlost = 0;
03379    else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
03380    if (rtp->rtcp->rxlost_count == 0)
03381       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
03382    if (lost_interval < rtp->rtcp->minrxlost) 
03383       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
03384    if (lost_interval > rtp->rtcp->maxrxlost) 
03385       rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
03386 
03387    rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
03388    rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
03389    rtp->rtcp->normdev_rxlost = rxlost_current;
03390    rtp->rtcp->rxlost_count++;
03391 
03392    if (expected_interval == 0 || lost_interval <= 0)
03393       fraction = 0;
03394    else
03395       fraction = (lost_interval << 8) / expected_interval;
03396    gettimeofday(&now, NULL);
03397    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
03398    rtcpheader = (unsigned int *)bdata;
03399    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
03400    rtcpheader[1] = htonl(rtp->ssrc);
03401    rtcpheader[2] = htonl(rtp->themssrc);
03402    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
03403    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
03404    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
03405    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
03406    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
03407 
03408    if (rtp->rtcp->sendfur) {
03409       rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
03410       rtcpheader[9] = htonl(rtp->ssrc);               /* Our SSRC */
03411       len += 8;
03412       rtp->rtcp->sendfur = 0;
03413    }
03414 
03415    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
03416    it can change mid call, and SDES can't) */
03417    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
03418    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
03419    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
03420    len += 12;
03421    
03422    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
03423 
03424    if (res < 0) {
03425       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
03426       /* Remove the scheduler */
03427       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03428       return 0;
03429    }
03430 
03431    rtp->rtcp->rr_count++;
03432 
03433    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
03434       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
03435          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 
03436          "  IA jitter: %.4f\n" 
03437          "  Their last SR: %u\n" 
03438          "  DLSR: %4.4f (sec)\n\n",
03439          ast_inet_ntoa(rtp->rtcp->them.sin_addr),
03440          ntohs(rtp->rtcp->them.sin_port),
03441          rtp->ssrc, rtp->themssrc, fraction, lost,
03442          rtp->rxjitter,
03443          rtp->rtcp->themrxlsr,
03444          (double)(ntohl(rtcpheader[7])/65536.0));
03445    }
03446 
03447    return res;
03448 }

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

Send RTCP sender's report.

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

03208 {
03209    struct ast_rtp *rtp = (struct ast_rtp *)data;
03210    int res;
03211    int len = 0;
03212    struct timeval now;
03213    unsigned int now_lsw;
03214    unsigned int now_msw;
03215    unsigned int *rtcpheader;
03216    unsigned int lost;
03217    unsigned int extended;
03218    unsigned int expected;
03219    unsigned int expected_interval;
03220    unsigned int received_interval;
03221    int lost_interval;
03222    int fraction;
03223    struct timeval dlsr;
03224    char bdata[512];
03225 
03226    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
03227    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
03228       return 0;
03229    
03230    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
03231       ast_verbose("RTCP SR transmission error, rtcp halted\n");
03232       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03233       return 0;
03234    }
03235 
03236    gettimeofday(&now, NULL);
03237    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
03238    rtcpheader = (unsigned int *)bdata;
03239    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
03240    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
03241    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
03242    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
03243    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
03244    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
03245    len += 28;
03246    
03247    extended = rtp->cycles + rtp->lastrxseqno;
03248    expected = extended - rtp->seedrxseqno + 1;
03249    if (rtp->rxcount > expected) 
03250       expected += rtp->rxcount - expected;
03251    lost = expected - rtp->rxcount;
03252    expected_interval = expected - rtp->rtcp->expected_prior;
03253    rtp->rtcp->expected_prior = expected;
03254    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
03255    rtp->rtcp->received_prior = rtp->rxcount;
03256    lost_interval = expected_interval - received_interval;
03257    if (expected_interval == 0 || lost_interval <= 0)
03258       fraction = 0;
03259    else
03260       fraction = (lost_interval << 8) / expected_interval;
03261    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
03262    rtcpheader[7] = htonl(rtp->themssrc);
03263    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
03264    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
03265    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
03266    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
03267    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
03268    len += 24;
03269    
03270    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
03271 
03272    if (rtp->rtcp->sendfur) {
03273       rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
03274       rtcpheader[14] = htonl(rtp->ssrc);               /* Our SSRC */
03275       len += 8;
03276       rtp->rtcp->sendfur = 0;
03277    }
03278    
03279    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 
03280    /* it can change mid call, and SDES can't) */
03281    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
03282    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
03283    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
03284    len += 12;
03285    
03286    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
03287    if (res < 0) {
03288       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));
03289       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03290       return 0;
03291    }
03292    
03293    /* FIXME Don't need to get a new one */
03294    gettimeofday(&rtp->rtcp->txlsr, NULL);
03295    rtp->rtcp->sr_count++;
03296 
03297    rtp->rtcp->lastsrtxcount = rtp->txcount;  
03298    
03299    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
03300       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
03301       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
03302       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
03303       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
03304       ast_verbose("  Sent packets: %u\n", rtp->txcount);
03305       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
03306       ast_verbose("  Report block:\n");
03307       ast_verbose("  Fraction lost: %u\n", fraction);
03308       ast_verbose("  Cumulative loss: %u\n", lost);
03309       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
03310       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
03311       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
03312    }
03313    manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n"
03314                    "OurSSRC: %u\r\n"
03315                    "SentNTP: %u.%010u\r\n"
03316                    "SentRTP: %u\r\n"
03317                    "SentPackets: %u\r\n"
03318                    "SentOctets: %u\r\n"
03319                    "ReportBlock:\r\n"
03320                    "FractionLost: %u\r\n"
03321                    "CumulativeLoss: %u\r\n"
03322                    "IAJitter: %.4f\r\n"
03323                    "TheirLastSR: %u\r\n"
03324                    "DLSR: %4.4f (sec)\r\n",
03325                    ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
03326                    rtp->ssrc,
03327                    (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
03328                    rtp->lastts,
03329                    rtp->txcount,
03330                    rtp->txoctetcount,
03331                    fraction,
03332                    lost,
03333                    rtp->rxjitter,
03334                    rtp->rtcp->themrxlsr,
03335                    (double)(ntohl(rtcpheader[12])/65536.0));
03336    return res;
03337 }

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

Referenced by process_sdp().

00497 {
00498    return sizeof(struct ast_rtp);
00499 }

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

04283 {
04284    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
04285    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
04286    struct ast_rtp *tp0 = NULL, *tp1 = NULL;  /* Text RTP channels */
04287    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
04288    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;
04289    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;
04290    enum ast_bridge_result res = AST_BRIDGE_FAILED;
04291    int codec0 = 0, codec1 = 0;
04292    void *pvt0 = NULL, *pvt1 = NULL;
04293 
04294    /* Lock channels */
04295    ast_channel_lock(c0);
04296    while (ast_channel_trylock(c1)) {
04297       ast_channel_unlock(c0);
04298       usleep(1);
04299       ast_channel_lock(c0);
04300    }
04301 
04302    /* Ensure neither channel got hungup during lock avoidance */
04303    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
04304       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
04305       ast_channel_unlock(c0);
04306       ast_channel_unlock(c1);
04307       return AST_BRIDGE_FAILED;
04308    }
04309       
04310    /* Find channel driver interfaces */
04311    if (!(pr0 = get_proto(c0))) {
04312       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
04313       ast_channel_unlock(c0);
04314       ast_channel_unlock(c1);
04315       return AST_BRIDGE_FAILED;
04316    }
04317    if (!(pr1 = get_proto(c1))) {
04318       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
04319       ast_channel_unlock(c0);
04320       ast_channel_unlock(c1);
04321       return AST_BRIDGE_FAILED;
04322    }
04323 
04324    /* Get channel specific interface structures */
04325    pvt0 = c0->tech_pvt;
04326    pvt1 = c1->tech_pvt;
04327 
04328    /* Get audio and video interface (if native bridge is possible) */
04329    audio_p0_res = pr0->get_rtp_info(c0, &p0);
04330    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04331    text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04332    audio_p1_res = pr1->get_rtp_info(c1, &p1);
04333    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04334    text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04335 
04336    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
04337    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
04338       audio_p0_res = AST_RTP_GET_FAILED;
04339    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
04340       audio_p1_res = AST_RTP_GET_FAILED;
04341 
04342    /* Check if a bridge is possible (partial/native) */
04343    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
04344       /* Somebody doesn't want to play... */
04345       ast_channel_unlock(c0);
04346       ast_channel_unlock(c1);
04347       return AST_BRIDGE_FAILED_NOWARN;
04348    }
04349 
04350    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
04351    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
04352       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
04353       audio_p0_res = AST_RTP_TRY_PARTIAL;
04354    }
04355 
04356    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
04357       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
04358       audio_p1_res = AST_RTP_TRY_PARTIAL;
04359    }
04360 
04361    /* If both sides are not using the same method of DTMF transmission 
04362     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
04363     * --------------------------------------------------
04364     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
04365     * |-----------|------------|-----------------------|
04366     * | Inband    | False      | True                  |
04367     * | RFC2833   | True       | True                  |
04368     * | SIP INFO  | False      | False                 |
04369     * --------------------------------------------------
04370     * However, if DTMF from both channels is being monitored by the core, then
04371     * we can still do packet-to-packet bridging, because passing through the 
04372     * core will handle DTMF mode translation.
04373     */
04374    if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
04375       (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
04376       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
04377          ast_channel_unlock(c0);
04378          ast_channel_unlock(c1);
04379          return AST_BRIDGE_FAILED_NOWARN;
04380       }
04381       audio_p0_res = AST_RTP_TRY_PARTIAL;
04382       audio_p1_res = AST_RTP_TRY_PARTIAL;
04383    }
04384 
04385    /* If we need to feed frames into the core don't do a P2P bridge */
04386    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
04387        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
04388       ast_channel_unlock(c0);
04389       ast_channel_unlock(c1);
04390       return AST_BRIDGE_FAILED_NOWARN;
04391    }
04392 
04393    /* Get codecs from both sides */
04394    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
04395    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
04396    if (codec0 && codec1 && !(codec0 & codec1)) {
04397       /* Hey, we can't do native bridging if both parties speak different codecs */
04398       ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
04399       ast_channel_unlock(c0);
04400       ast_channel_unlock(c1);
04401       return AST_BRIDGE_FAILED_NOWARN;
04402    }
04403 
04404    /* If either side can only do a partial bridge, then don't try for a true native bridge */
04405    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
04406       struct ast_format_list fmt0, fmt1;
04407 
04408       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
04409       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
04410          ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
04411          ast_channel_unlock(c0);
04412          ast_channel_unlock(c1);
04413          return AST_BRIDGE_FAILED_NOWARN;
04414       }
04415       /* They must also be using the same packetization */
04416       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
04417       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
04418       if (fmt0.cur_ms != fmt1.cur_ms) {
04419          ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
04420          ast_channel_unlock(c0);
04421          ast_channel_unlock(c1);
04422          return AST_BRIDGE_FAILED_NOWARN;
04423       }
04424 
04425       ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
04426       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
04427    } else {
04428       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04429       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
04430    }
04431 
04432    return res;
04433 }

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3670 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

03671 {
03672    if (pt < 0 || pt > MAX_RTP_PT)
03673       return 0; /* bogus payload type */
03674 
03675    if (static_RTP_PT[pt].isAstFormat)
03676       return static_RTP_PT[pt].code;
03677    else
03678       return 0;
03679 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Get codec preference.

Definition at line 3665 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

03666 {
03667    return &rtp->pref;
03668 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

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

03620 {
03621    struct ast_format_list current_format_old, current_format_new;
03622 
03623    /* if no packets have been sent through this session yet, then
03624     *  changing preferences does not require any extra work
03625     */
03626    if (rtp->lasttxformat == 0) {
03627       rtp->pref = *prefs;
03628       return;
03629    }
03630 
03631    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03632 
03633    rtp->pref = *prefs;
03634 
03635    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03636 
03637    /* if the framing desired for the current format has changed, we may have to create
03638     * or adjust the smoother for this session
03639     */
03640    if ((current_format_new.inc_ms != 0) &&
03641        (current_format_new.cur_ms != current_format_old.cur_ms)) {
03642       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
03643 
03644       if (rtp->smoother) {
03645          ast_smoother_reconfigure(rtp->smoother, new_size);
03646          if (option_debug) {
03647             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
03648          }
03649       } else {
03650          if (!(rtp->smoother = ast_smoother_new(new_size))) {
03651             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03652             return;
03653          }
03654          if (current_format_new.flags) {
03655             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
03656          }
03657          if (option_debug) {
03658             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03659          }
03660       }
03661    }
03662 
03663 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

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

02955 {
02956    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02957       /*Print some info on the call here */
02958       ast_verbose("  RTP-stats\n");
02959       ast_verbose("* Our Receiver:\n");
02960       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02961       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02962       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
02963       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02964       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02965       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
02966       ast_verbose("* Our Sender:\n");
02967       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02968       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02969       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
02970       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
02971       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
02972       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
02973    }
02974 
02975    manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
02976                    "ReceivedPackets: %u\r\n"
02977                    "LostPackets: %u\r\n"
02978                    "Jitter: %.4f\r\n"
02979                    "Transit: %.4f\r\n"
02980                    "RRCount: %u\r\n",
02981                    rtp->themssrc,
02982                    rtp->rxcount,
02983                    rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
02984                    rtp->rxjitter,
02985                    rtp->rxtransit,
02986                    rtp->rtcp ? rtp->rtcp->rr_count : 0);
02987    manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
02988                    "SentPackets: %u\r\n"
02989                    "LostPackets: %u\r\n"
02990                    "Jitter: %u\r\n"
02991                    "SRCount: %u\r\n"
02992                    "RTT: %f\r\n",
02993                    rtp->ssrc,
02994                    rtp->txcount,
02995                    rtp->rtcp ? rtp->rtcp->reported_lost : 0,
02996                    rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
02997                    rtp->rtcp ? rtp->rtcp->sr_count : 0,
02998                    rtp->rtcp ? rtp->rtcp->rtt : 0);
02999    if (rtp->smoother)
03000       ast_smoother_free(rtp->smoother);
03001    if (rtp->ioid)
03002       ast_io_remove(rtp->io, rtp->ioid);
03003    if (rtp->s > -1)
03004       close(rtp->s);
03005    if (rtp->rtcp) {
03006       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03007       close(rtp->rtcp->s);
03008       ast_free(rtp->rtcp);
03009       rtp->rtcp=NULL;
03010    }
03011 #ifdef P2P_INTENSE
03012    ast_mutex_destroy(&rtp->bridge_lock);
03013 #endif
03014    ast_free(rtp);
03015 }

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

02024 {
02025    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02026    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02027    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02028    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02029    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;
02030    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;
02031    int srccodec, destcodec, nat_active = 0;
02032 
02033    /* Lock channels */
02034    ast_channel_lock(c0);
02035    if (c1) {
02036       while (ast_channel_trylock(c1)) {
02037          ast_channel_unlock(c0);
02038          usleep(1);
02039          ast_channel_lock(c0);
02040       }
02041    }
02042 
02043    /* Find channel driver interfaces */
02044    destpr = get_proto(c0);
02045    if (c1)
02046       srcpr = get_proto(c1);
02047    if (!destpr) {
02048       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
02049       ast_channel_unlock(c0);
02050       if (c1)
02051          ast_channel_unlock(c1);
02052       return -1;
02053    }
02054    if (!srcpr) {
02055       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
02056       ast_channel_unlock(c0);
02057       if (c1)
02058          ast_channel_unlock(c1);
02059       return -1;
02060    }
02061 
02062    /* Get audio, video  and text interface (if native bridge is possible) */
02063    audio_dest_res = destpr->get_rtp_info(c0, &destp);
02064    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
02065    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
02066    if (srcpr) {
02067       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
02068       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
02069       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
02070    }
02071 
02072    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
02073    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
02074       /* Somebody doesn't want to play... */
02075       ast_channel_unlock(c0);
02076       if (c1)
02077          ast_channel_unlock(c1);
02078       return -1;
02079    }
02080    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)
02081       srccodec = srcpr->get_codec(c1);
02082    else
02083       srccodec = 0;
02084    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)
02085       destcodec = destpr->get_codec(c0);
02086    else
02087       destcodec = 0;
02088    /* Ensure we have at least one matching codec */
02089    if (srcp && !(srccodec & destcodec)) {
02090       ast_channel_unlock(c0);
02091       ast_channel_unlock(c1);
02092       return 0;
02093    }
02094    /* Consider empty media as non-existent */
02095    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
02096       srcp = NULL;
02097    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02098       nat_active = 1;
02099    /* Bridge media early */
02100    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
02101       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02102    ast_channel_unlock(c0);
02103    if (c1)
02104       ast_channel_unlock(c1);
02105    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02106    return 0;
02107 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00721 {
00722    return rtp->s;
00723 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

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

02596 {
02597    struct ast_rtp *bridged = NULL;
02598 
02599    rtp_bridge_lock(rtp);
02600    bridged = rtp->bridged;
02601    rtp_bridge_unlock(rtp);
02602 
02603    return bridged;
02604 }

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

02247 {
02248    int pt;
02249    
02250    rtp_bridge_lock(rtp);
02251    
02252    *astFormats = *nonAstFormats = 0;
02253    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02254       if (rtp->current_RTP_PT[pt].isAstFormat) {
02255          *astFormats |= rtp->current_RTP_PT[pt].code;
02256       } else {
02257          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02258       }
02259    }
02260 
02261    rtp_bridge_unlock(rtp);
02262 }

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

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

02578 {
02579    if ((them->sin_family != AF_INET) ||
02580       (them->sin_port != rtp->them.sin_port) ||
02581       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02582       them->sin_family = AF_INET;
02583       them->sin_port = rtp->them.sin_port;
02584       them->sin_addr = rtp->them.sin_addr;
02585       return 1;
02586    }
02587    return 0;
02588 }

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

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02717 {
02718    double value;
02719    int found;
02720 
02721    value = __ast_rtp_get_qos(rtp, qos, &found);
02722 
02723    if (!found)
02724       return -1;
02725 
02726    snprintf(buf, buflen, "%.0lf", value);
02727 
02728    return 0;
02729 }

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

02651 {
02652    if (rtp == NULL) {
02653       if (option_debug > 1)
02654          ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
02655       return 0;
02656    }
02657    if (option_debug > 1 && rtp->rtcp == NULL) {
02658       ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
02659    }
02660 
02661    switch (value) {
02662    case AST_RTP_TXCOUNT:
02663       return (unsigned int) rtp->txcount;
02664    case AST_RTP_RXCOUNT:
02665       return (unsigned int) rtp->rxcount;
02666    case AST_RTP_TXJITTER:
02667       return (unsigned int) (rtp->rxjitter * 100.0);
02668    case AST_RTP_RXJITTER:
02669       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
02670    case AST_RTP_RXPLOSS:
02671       return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
02672    case AST_RTP_TXPLOSS:
02673       return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
02674    case AST_RTP_RTT:
02675       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
02676    }
02677    return 0;   /* To make the compiler happy */
02678 }

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

02924 {
02925    if (qual && rtp) {
02926       qual->local_ssrc   = rtp->ssrc;
02927       qual->local_jitter = rtp->rxjitter;
02928       qual->local_count  = rtp->rxcount;
02929       qual->remote_ssrc  = rtp->themssrc;
02930       qual->remote_count = rtp->txcount;
02931 
02932       if (rtp->rtcp) {
02933          qual->local_lostpackets  = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02934          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02935          qual->remote_jitter      = rtp->rtcp->reported_jitter / 65536.0;
02936          qual->rtt                = rtp->rtcp->rtt;
02937       }
02938    }
02939 
02940    switch (qtype) {
02941    case RTPQOS_SUMMARY:
02942       return __ast_rtp_get_quality(rtp);
02943    case RTPQOS_JITTER:
02944       return __ast_rtp_get_quality_jitter(rtp);
02945    case RTPQOS_LOSS:
02946       return __ast_rtp_get_quality_loss(rtp);
02947    case RTPQOS_RTT:
02948       return __ast_rtp_get_quality_rtt(rtp);
02949    }
02950 
02951    return NULL;
02952 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 775 of file rtp.c.

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

Referenced by check_rtp_timeout().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 783 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00784 {
00785    return rtp->rtpkeepalive;
00786 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 767 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

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

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

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

02591 {
02592    *us = rtp->us;
02593 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 803 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00804 {
00805    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00806 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4821 of file rtp.c.

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

Referenced by main().

04822 {
04823    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04824    __ast_rtp_reload(0);
04825 }

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

02287 {
02288    int pt = 0;
02289 
02290    rtp_bridge_lock(rtp);
02291 
02292    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02293       code == rtp->rtp_lookup_code_cache_code) {
02294       /* Use our cached mapping, to avoid the overhead of the loop below */
02295       pt = rtp->rtp_lookup_code_cache_result;
02296       rtp_bridge_unlock(rtp);
02297       return pt;
02298    }
02299 
02300    /* Check the dynamic list first */
02301    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02302       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02303          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02304          rtp->rtp_lookup_code_cache_code = code;
02305          rtp->rtp_lookup_code_cache_result = pt;
02306          rtp_bridge_unlock(rtp);
02307          return pt;
02308       }
02309    }
02310 
02311    /* Then the static list */
02312    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02313       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02314          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02315          rtp->rtp_lookup_code_cache_code = code;
02316          rtp->rtp_lookup_code_cache_result = pt;
02317          rtp_bridge_unlock(rtp);
02318          return pt;
02319       }
02320    }
02321 
02322    rtp_bridge_unlock(rtp);
02323 
02324    return -1;
02325 }

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

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

Referenced by process_sdp().

02348 {
02349    int format;
02350    unsigned len;
02351    char *end = buf;
02352    char *start = buf;
02353 
02354    if (!buf || !size)
02355       return NULL;
02356 
02357    snprintf(end, size, "0x%x (", capability);
02358 
02359    len = strlen(end);
02360    end += len;
02361    size -= len;
02362    start = end;
02363 
02364    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02365       if (capability & format) {
02366          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02367 
02368          snprintf(end, size, "%s|", name);
02369          len = strlen(end);
02370          end += len;
02371          size -= len;
02372       }
02373    }
02374 
02375    if (start == end)
02376       ast_copy_string(start, "nothing)", size); 
02377    else if (size > 1)
02378       *(end -1) = ')';
02379    
02380    return buf;
02381 }

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

02329 {
02330    unsigned int i;
02331 
02332    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02333       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02334          if (isAstFormat &&
02335              (code == AST_FORMAT_G726_AAL2) &&
02336              (options & AST_RTP_OPT_G726_NONSTANDARD))
02337             return "G726-32";
02338          else
02339             return mimeTypes[i].subtype;
02340       }
02341    }
02342 
02343    return "";
02344 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

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

02265 {
02266    struct rtpPayloadType result;
02267 
02268    result.isAstFormat = result.code = 0;
02269 
02270    if (pt < 0 || pt > MAX_RTP_PT) 
02271       return result; /* bogus payload type */
02272 
02273    /* Start with negotiated codecs */
02274    rtp_bridge_lock(rtp);
02275    result = rtp->current_RTP_PT[pt];
02276    rtp_bridge_unlock(rtp);
02277 
02278    /* If it doesn't exist, check our static RTP type list, just in case */
02279    if (!result.code) 
02280       result = static_RTP_PT[pt];
02281 
02282    return result;
02283 }

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

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

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

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02542 {
02543    struct in_addr ia;
02544 
02545    memset(&ia, 0, sizeof(ia));
02546    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02547 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

02433 {
02434 #ifdef P2P_INTENSE
02435    ast_mutex_init(&rtp->bridge_lock);
02436 #endif
02437 
02438    rtp->them.sin_family = AF_INET;
02439    rtp->us.sin_family = AF_INET;
02440    rtp->ssrc = ast_random();
02441    rtp->seqno = ast_random() & 0xffff;
02442    ast_set_flag(rtp, FLAG_HAS_DTMF);
02443    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02444 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2554 of file rtp.c.

References ast_rtp::set_marker_bit.

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

02555 {
02556    if (rtp) {
02557       rtp->set_marker_bit = 1;
02558    }
02559    return;
02560 }

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

02447 {
02448    struct ast_rtp *rtp;
02449    int x;
02450    int startplace;
02451    
02452    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
02453       return NULL;
02454 
02455    ast_rtp_new_init(rtp);
02456 
02457    rtp->s = rtp_socket("RTP");
02458    if (rtp->s < 0)
02459       goto fail;
02460    if (sched && rtcpenable) {
02461       rtp->sched = sched;
02462       rtp->rtcp = ast_rtcp_new();
02463    }
02464    
02465    /*
02466     * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
02467     * Start from a random (even, by RTP spec) port number, and
02468     * iterate until success or no ports are available.
02469     * Note that the requirement of RTP port being even, or RTCP being the
02470     * next one, cannot be enforced in presence of a NAT box because the
02471     * mapping is not under our control.
02472     */
02473    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
02474    x = x & ~1;    /* make it an even number */
02475    startplace = x;      /* remember the starting point */
02476    /* this is constant across the loop */
02477    rtp->us.sin_addr = addr;
02478    if (rtp->rtcp)
02479       rtp->rtcp->us.sin_addr = addr;
02480    for (;;) {
02481       rtp->us.sin_port = htons(x);
02482       if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
02483          /* bind succeeded, if no rtcp then we are done */
02484          if (!rtp->rtcp)
02485             break;
02486          /* have rtcp, try to bind it */
02487          rtp->rtcp->us.sin_port = htons(x + 1);
02488          if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
02489             break;   /* success again, we are really done */
02490          /*
02491           * RTCP bind failed, so close and recreate the
02492           * already bound RTP socket for the next round.
02493           */
02494          close(rtp->s);
02495          rtp->s = rtp_socket("RTP");
02496          if (rtp->s < 0)
02497             goto fail;
02498       }
02499       /*
02500        * If we get here, there was an error in one of the bind()
02501        * calls, so make sure it is nothing unexpected.
02502        */
02503       if (errno != EADDRINUSE) {
02504          /* We got an error that wasn't expected, abort! */
02505          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02506          goto fail;
02507       }
02508       /*
02509        * One of the ports is in use. For the next iteration,
02510        * increment by two and handle wraparound.
02511        * If we reach the starting point, then declare failure.
02512        */
02513       x += 2;
02514       if (x > rtpend)
02515          x = (rtpstart + 1) & ~1;
02516       if (x == startplace) {
02517          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02518          goto fail;
02519       }
02520    }
02521    rtp->sched = sched;
02522    rtp->io = io;
02523    if (callbackmode) {
02524       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02525       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02526    }
02527    ast_rtp_pt_default(rtp);
02528    return rtp;
02529 
02530 fail:
02531    if (rtp->s >= 0)
02532       close(rtp->s);
02533    if (rtp->rtcp) {
02534       close(rtp->rtcp->s);
02535       ast_free(rtp->rtcp);
02536    }
02537    ast_free(rtp);
02538    return NULL;
02539 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

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

03782 {
03783    struct ast_rtp_protocol *cur;
03784 
03785    AST_RWLIST_WRLOCK(&protos);
03786    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03787       if (!strcmp(cur->type, proto->type)) {
03788          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03789          AST_RWLIST_UNLOCK(&protos);
03790          return -1;
03791       }
03792    }
03793    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03794    AST_RWLIST_UNLOCK(&protos);
03795    
03796    return 0;
03797 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3773 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03774 {
03775    AST_RWLIST_WRLOCK(&protos);
03776    AST_RWLIST_REMOVE(&protos, proto, list);
03777    AST_RWLIST_UNLOCK(&protos);
03778 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

01948 {
01949    int i;
01950 
01951    if (!rtp)
01952       return;
01953 
01954    rtp_bridge_lock(rtp);
01955 
01956    for (i = 0; i < MAX_RTP_PT; ++i) {
01957       rtp->current_RTP_PT[i].isAstFormat = 0;
01958       rtp->current_RTP_PT[i].code = 0;
01959    }
01960 
01961    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01962    rtp->rtp_lookup_code_cache_code = 0;
01963    rtp->rtp_lookup_code_cache_result = 0;
01964 
01965    rtp_bridge_unlock(rtp);
01966 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01988 {
01989    unsigned int i;
01990 
01991    rtp_bridge_lock(dest);
01992    rtp_bridge_lock(src);
01993 
01994    for (i = 0; i < MAX_RTP_PT; ++i) {
01995       dest->current_RTP_PT[i].isAstFormat = 
01996          src->current_RTP_PT[i].isAstFormat;
01997       dest->current_RTP_PT[i].code = 
01998          src->current_RTP_PT[i].code; 
01999    }
02000    dest->rtp_lookup_code_cache_isAstFormat = 0;
02001    dest->rtp_lookup_code_cache_code = 0;
02002    dest->rtp_lookup_code_cache_result = 0;
02003 
02004    rtp_bridge_unlock(src);
02005    rtp_bridge_unlock(dest);
02006 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

01969 {
01970    int i;
01971 
01972    rtp_bridge_lock(rtp);
01973 
01974    /* Initialize to default payload types */
01975    for (i = 0; i < MAX_RTP_PT; ++i) {
01976       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01977       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01978    }
01979 
01980    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01981    rtp->rtp_lookup_code_cache_code = 0;
01982    rtp->rtp_lookup_code_cache_result = 0;
01983 
01984    rtp_bridge_unlock(rtp);
01985 }

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

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

03506 {
03507    unsigned char *rtpheader;
03508    int hdrlen = 12;
03509    int res;
03510    unsigned int ms;
03511    int pred;
03512    int mark = 0;
03513 
03514    if (rtp->sending_digit) {
03515       return 0;
03516    }
03517 
03518    ms = calc_txstamp(rtp, &f->delivery);
03519    /* Default prediction */
03520    if (f->frametype == AST_FRAME_VOICE) {
03521       pred = rtp->lastts + f->samples;
03522 
03523       /* Re-calculate last TS */
03524       rtp->lastts = rtp->lastts + ms * 8;
03525       if (ast_tvzero(f->delivery)) {
03526          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
03527             and if so, go with our prediction */
03528          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
03529             rtp->lastts = pred;
03530          else {
03531             ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
03532             mark = 1;
03533          }
03534       }
03535    } else if (f->frametype == AST_FRAME_VIDEO) {
03536       mark = f->subclass & 0x1;
03537       pred = rtp->lastovidtimestamp + f->samples;
03538       /* Re-calculate last TS */
03539       rtp->lastts = rtp->lastts + ms * 90;
03540       /* If it's close to our prediction, go for it */
03541       if (ast_tvzero(f->delivery)) {
03542          if (abs(rtp->lastts - pred) < 7200) {
03543             rtp->lastts = pred;
03544             rtp->lastovidtimestamp += f->samples;
03545          } else {
03546             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);
03547             rtp->lastovidtimestamp = rtp->lastts;
03548          }
03549       }
03550    } else {
03551       pred = rtp->lastotexttimestamp + f->samples;
03552       /* Re-calculate last TS */
03553       rtp->lastts = rtp->lastts + ms;
03554       /* If it's close to our prediction, go for it */
03555       if (ast_tvzero(f->delivery)) {
03556          if (abs(rtp->lastts - pred) < 7200) {
03557             rtp->lastts = pred;
03558             rtp->lastotexttimestamp += f->samples;
03559          } else {
03560             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);
03561             rtp->lastotexttimestamp = rtp->lastts;
03562          }
03563       }
03564    }
03565 
03566    /* If we have been explicitly told to set the marker bit do so */
03567    if (rtp->set_marker_bit) {
03568       mark = 1;
03569       rtp->set_marker_bit = 0;
03570    }
03571 
03572    /* If the timestamp for non-digit packets has moved beyond the timestamp
03573       for digits, update the digit timestamp.
03574    */
03575    if (rtp->lastts > rtp->lastdigitts)
03576       rtp->lastdigitts = rtp->lastts;
03577 
03578    if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
03579       rtp->lastts = f->ts * 8;
03580 
03581    /* Get a pointer to the header */
03582    rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
03583 
03584    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
03585    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
03586    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
03587 
03588    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03589       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03590       if (res < 0) {
03591          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
03592             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));
03593          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
03594             /* Only give this error message once if we are not RTP debugging */
03595             if (option_debug || rtpdebug)
03596                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));
03597             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
03598          }
03599       } else {
03600          rtp->txcount++;
03601          rtp->txoctetcount +=(res - hdrlen);
03602          
03603          /* Do not schedule RR if RTCP isn't run */
03604          if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
03605             rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
03606          }
03607       }
03608             
03609       if (rtp_debug_test_addr(&rtp->them))
03610          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03611                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
03612    }
03613 
03614    rtp->seqno++;
03615 
03616    return 0;
03617 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1525 of file rtp.c.

References ast_assert, ast_codec_get_samples(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose, bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, errno, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, 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_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, send_dtmf(), ast_rtp::sending_digit, ast_frame::seqno, ast_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().

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

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4815 of file rtp.c.

References __ast_rtp_reload().

04816 {
04817    return __ast_rtp_reload(1);
04818 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2627 of file rtp.c.

References ast_rtp::dtmfcount, 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.

02628 {
02629    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02630    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02631    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02632    rtp->lastts = 0;
02633    rtp->lastdigitts = 0;
02634    rtp->lastrxts = 0;
02635    rtp->lastividtimestamp = 0;
02636    rtp->lastovidtimestamp = 0;
02637    rtp->lastitexttimestamp = 0;
02638    rtp->lastotexttimestamp = 0;
02639    rtp->lasteventseqn = 0;
02640    rtp->lastevent = 0;
02641    rtp->lasttxformat = 0;
02642    rtp->lastrxformat = 0;
02643    rtp->dtmfcount = 0;
02644    rtp->dtmfsamples = 0;
02645    rtp->seqno = 0;
02646    rtp->rxseqno = 0;
02647 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

03471 {
03472    unsigned int *rtpheader;
03473    int hdrlen = 12;
03474    int res;
03475    int payload;
03476    char data[256];
03477    level = 127 - (level & 0x7f);
03478    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03479 
03480    /* If we have no peer, return immediately */ 
03481    if (!rtp->them.sin_addr.s_addr)
03482       return 0;
03483 
03484    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03485 
03486    /* Get a pointer to the header */
03487    rtpheader = (unsigned int *)data;
03488    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03489    rtpheader[1] = htonl(rtp->lastts);
03490    rtpheader[2] = htonl(rtp->ssrc); 
03491    data[12] = level;
03492    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03493       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03494       if (res <0) 
03495          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));
03496       if (rtp_debug_test_addr(&rtp->them))
03497          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03498                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03499          
03500    }
03501    return 0;
03502 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

03038 {
03039    unsigned int *rtpheader;
03040    int hdrlen = 12, res = 0, i = 0, payload = 0;
03041    char data[256];
03042 
03043    if ((digit <= '9') && (digit >= '0'))
03044       digit -= '0';
03045    else if (digit == '*')
03046       digit = 10;
03047    else if (digit == '#')
03048       digit = 11;
03049    else if ((digit >= 'A') && (digit <= 'D'))
03050       digit = digit - 'A' + 12;
03051    else if ((digit >= 'a') && (digit <= 'd'))
03052       digit = digit - 'a' + 12;
03053    else {
03054       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03055       return 0;
03056    }
03057 
03058    /* If we have no peer, return immediately */ 
03059    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03060       return 0;
03061 
03062    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
03063 
03064    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03065    rtp->send_duration = 160;
03066    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
03067    
03068    /* Get a pointer to the header */
03069    rtpheader = (unsigned int *)data;
03070    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
03071    rtpheader[1] = htonl(rtp->lastdigitts);
03072    rtpheader[2] = htonl(rtp->ssrc); 
03073 
03074    for (i = 0; i < 2; i++) {
03075       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03076       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03077       if (res < 0) 
03078          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
03079             ast_inet_ntoa(rtp->them.sin_addr),
03080             ntohs(rtp->them.sin_port), strerror(errno));
03081       if (rtp_debug_test_addr(&rtp->them))
03082          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03083                 ast_inet_ntoa(rtp->them.sin_addr),
03084                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03085       /* Increment sequence number */
03086       rtp->seqno++;
03087       /* Increment duration */
03088       rtp->send_duration += 160;
03089       /* Clear marker bit and set seqno */
03090       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
03091    }
03092 
03093    /* Since we received a begin, we can safely store the digit and disable any compensation */
03094    rtp->sending_digit = 1;
03095    rtp->send_digit = digit;
03096    rtp->send_payload = payload;
03097 
03098    return 0;
03099 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

03103 {
03104    unsigned int *rtpheader;
03105    int hdrlen = 12, res = 0;
03106    char data[256];
03107 
03108    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03109       return 0;
03110 
03111    /* Setup packet to send */
03112    rtpheader = (unsigned int *)data;
03113    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
03114    rtpheader[1] = htonl(rtp->lastdigitts);
03115    rtpheader[2] = htonl(rtp->ssrc);
03116    rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
03117    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
03118    
03119    /* Transmit */
03120    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03121    if (res < 0)
03122       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
03123          ast_inet_ntoa(rtp->them.sin_addr),
03124          ntohs(rtp->them.sin_port), strerror(errno));
03125    if (rtp_debug_test_addr(&rtp->them))
03126       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03127              ast_inet_ntoa(rtp->them.sin_addr),
03128              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03129 
03130    /* Increment sequence number */
03131    rtp->seqno++;
03132    /* Increment duration */
03133    rtp->send_duration += 160;
03134 
03135    return 0;
03136 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

03140 {
03141    unsigned int *rtpheader;
03142    int hdrlen = 12, res = 0, i = 0;
03143    char data[256];
03144    
03145    /* If no address, then bail out */
03146    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03147       return 0;
03148    
03149    if ((digit <= '9') && (digit >= '0'))
03150       digit -= '0';
03151    else if (digit == '*')
03152       digit = 10;
03153    else if (digit == '#')
03154       digit = 11;
03155    else if ((digit >= 'A') && (digit <= 'D'))
03156       digit = digit - 'A' + 12;
03157    else if ((digit >= 'a') && (digit <= 'd'))
03158       digit = digit - 'a' + 12;
03159    else {
03160       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03161       return 0;
03162    }
03163 
03164    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03165 
03166    rtpheader = (unsigned int *)data;
03167    rtpheader[1] = htonl(rtp->lastdigitts);
03168    rtpheader[2] = htonl(rtp->ssrc);
03169    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03170    /* Set end bit */
03171    rtpheader[3] |= htonl((1 << 23));
03172 
03173    /* Send 3 termination packets */
03174    for (i = 0; i < 3; i++) {
03175       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
03176       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03177       rtp->seqno++;
03178       if (res < 0)
03179          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
03180             ast_inet_ntoa(rtp->them.sin_addr),
03181             ntohs(rtp->them.sin_port), strerror(errno));
03182       if (rtp_debug_test_addr(&rtp->them))
03183          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03184                 ast_inet_ntoa(rtp->them.sin_addr),
03185                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03186    }
03187    rtp->lastts += rtp->send_duration;
03188    rtp->sending_digit = 0;
03189    rtp->send_digit = 0;
03190 
03191    return res;
03192 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 793 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00794 {
00795    rtp->callback = callback;
00796 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 788 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00789 {
00790    rtp->data = data;
00791 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

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

02187 {
02188    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02189       return; /* bogus payload type */
02190 
02191    rtp_bridge_lock(rtp);
02192    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02193    rtp_bridge_unlock(rtp);
02194 } 

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

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

02563 {
02564    rtp->them.sin_port = them->sin_port;
02565    rtp->them.sin_addr = them->sin_addr;
02566    if (rtp->rtcp) {
02567       int h = ntohs(them->sin_port);
02568       rtp->rtcp->them.sin_port = htons(h + 1);
02569       rtp->rtcp->them.sin_addr = them->sin_addr;
02570    }
02571    rtp->rxseqno = 0;
02572    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02573    if (strictrtp)
02574       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02575 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 755 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00756 {
00757    rtp->rtpholdtimeout = timeout;
00758 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 761 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00762 {
00763    rtp->rtpkeepalive = period;
00764 }

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

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

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

02216 {
02217    unsigned int i;
02218    int found = 0;
02219 
02220    if (pt < 0 || pt > MAX_RTP_PT) 
02221       return -1; /* bogus payload type */
02222    
02223    rtp_bridge_lock(rtp);
02224 
02225    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02226       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02227           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02228          found = 1;
02229          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02230          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02231              mimeTypes[i].payloadType.isAstFormat &&
02232              (options & AST_RTP_OPT_G726_NONSTANDARD))
02233             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02234          break;
02235       }
02236    }
02237 
02238    rtp_bridge_unlock(rtp);
02239 
02240    return (found ? 0 : -1);
02241 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 749 of file rtp.c.

References ast_rtp::rtptimeout.

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

00750 {
00751    rtp->rtptimeout = timeout;
00752 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 742 of file rtp.c.

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

Referenced by handle_response_invite().

00743 {
00744    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00745    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00746 }

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

02731                                                                      {
02732    char *audioqos;
02733    char *audioqos_jitter;
02734    char *audioqos_loss;
02735    char *audioqos_rtt;
02736    struct ast_channel *bridge;
02737 
02738    if (!rtp || !chan)
02739       return;
02740 
02741    bridge = ast_bridged_channel(chan);
02742 
02743    audioqos        = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
02744    audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
02745    audioqos_loss   = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
02746    audioqos_rtt    = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
02747 
02748    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
02749    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
02750    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
02751    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
02752 
02753    if (!bridge)
02754       return;
02755 
02756    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
02757    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
02758    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
02759    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
02760 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00809 {
00810    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00811 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00814 {
00815    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00816 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 798 of file rtp.c.

References ast_rtp::nat.

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

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

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

Definition at line 2549 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

02550 {
02551    return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
02552 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 818 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00819 {
00820    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00821 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

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

02607 {
02608    if (rtp->rtcp) {
02609       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02610    }
02611    if (rtp->red) {
02612       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02613       free(rtp->red);
02614       rtp->red = NULL;
02615    }
02616 
02617    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02618    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02619    if (rtp->rtcp) {
02620       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02621       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02622    }
02623    
02624    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02625 }

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

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00703 {
00704    ast_stun_request(rtp->s, suggestion, username, NULL);
00705 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

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

02199 {
02200    if (pt < 0 || pt > MAX_RTP_PT)
02201       return; /* bogus payload type */
02202 
02203    rtp_bridge_lock(rtp);
02204    rtp->current_RTP_PT[pt].isAstFormat = 0;
02205    rtp->current_RTP_PT[pt].code = 0;
02206    rtp_bridge_unlock(rtp);
02207 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 3681 of file rtp.c.

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

03682 {
03683    struct ast_frame *f;
03684    int codec;
03685    int hdrlen = 12;
03686    int subclass;
03687    
03688 
03689    /* If we have no peer, return immediately */ 
03690    if (!rtp->them.sin_addr.s_addr)
03691       return 0;
03692 
03693    /* If there is no data length, return immediately */
03694    if (!_f->datalen && !rtp->red)
03695       return 0;
03696    
03697    /* Make sure we have enough space for RTP header */
03698    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
03699       ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
03700       return -1;
03701    }
03702 
03703    if (rtp->red) {
03704       /* return 0; */
03705       /* no primary data or generations to send */
03706       if ((_f = red_t140_to_red(rtp->red)) == NULL) 
03707          return 0;
03708    }
03709 
03710    /* The bottom bit of a video subclass contains the marker bit */
03711    subclass = _f->subclass;
03712    if (_f->frametype == AST_FRAME_VIDEO)
03713       subclass &= ~0x1;
03714 
03715    codec = ast_rtp_lookup_code(rtp, 1, subclass);
03716    if (codec < 0) {
03717       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
03718       return -1;
03719    }
03720 
03721    if (rtp->lasttxformat != subclass) {
03722       /* New format, reset the smoother */
03723       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
03724       rtp->lasttxformat = subclass;
03725       if (rtp->smoother)
03726          ast_smoother_free(rtp->smoother);
03727       rtp->smoother = NULL;
03728    }
03729 
03730    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
03731       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
03732       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
03733          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
03734             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));
03735             return -1;
03736          }
03737          if (fmt.flags)
03738             ast_smoother_set_flags(rtp->smoother, fmt.flags);
03739          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));
03740       }
03741    }
03742    if (rtp->smoother) {
03743       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03744          ast_smoother_feed_be(rtp->smoother, _f);
03745       } else {
03746          ast_smoother_feed(rtp->smoother, _f);
03747       }
03748 
03749       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
03750          if (f->subclass == AST_FORMAT_G722) {
03751             /* G.722 is silllllllllllllly */
03752             f->samples /= 2;
03753          }
03754 
03755          ast_rtp_raw_write(rtp, f, codec);
03756       }
03757    } else {
03758       /* Don't buffer outgoing frames; send them one-per-packet: */
03759       if (_f->offset < hdrlen) 
03760          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
03761       else
03762          f = _f;
03763       if (f->data.ptr)
03764          ast_rtp_raw_write(rtp, f, codec);
03765       if (f != _f)
03766          ast_frfree(f);
03767    }
03768       
03769    return 0;
03770 }

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

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

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

03801 {
03802    struct ast_frame *fr = NULL;
03803    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03804    int oldcodec0 = codec0, oldcodec1 = codec1;
03805    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
03806    struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
03807    
03808    /* Set it up so audio goes directly between the two endpoints */
03809 
03810    /* Test the first channel */
03811    if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
03812       ast_rtp_get_peer(p1, &ac1);
03813       if (vp1)
03814          ast_rtp_get_peer(vp1, &vac1);
03815       if (tp1)
03816          ast_rtp_get_peer(tp1, &tac1);
03817    } else
03818       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
03819    
03820    /* Test the second channel */
03821    if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
03822       ast_rtp_get_peer(p0, &ac0);
03823       if (vp0)
03824          ast_rtp_get_peer(vp0, &vac0);
03825       if (tp0)
03826          ast_rtp_get_peer(tp0, &tac0);
03827    } else
03828       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
03829 
03830    /* Now we can unlock and move into our loop */
03831    ast_channel_unlock(c0);
03832    ast_channel_unlock(c1);
03833 
03834    ast_poll_channel_add(c0, c1);
03835 
03836    /* Throw our channels into the structure and enter the loop */
03837    cs[0] = c0;
03838    cs[1] = c1;
03839    cs[2] = NULL;
03840    for (;;) {
03841       /* Check if anything changed */
03842       if ((c0->tech_pvt != pvt0) ||
03843           (c1->tech_pvt != pvt1) ||
03844           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03845           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03846          ast_debug(1, "Oooh, something is weird, backing out\n");
03847          if (c0->tech_pvt == pvt0)
03848             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
03849                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03850          if (c1->tech_pvt == pvt1)
03851             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
03852                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03853          ast_poll_channel_del(c0, c1);
03854          return AST_BRIDGE_RETRY;
03855       }
03856 
03857       /* Check if they have changed their address */
03858       ast_rtp_get_peer(p1, &t1);
03859       if (vp1)
03860          ast_rtp_get_peer(vp1, &vt1);
03861       if (tp1)
03862          ast_rtp_get_peer(tp1, &tt1);
03863       if (pr1->get_codec)
03864          codec1 = pr1->get_codec(c1);
03865       ast_rtp_get_peer(p0, &t0);
03866       if (vp0)
03867          ast_rtp_get_peer(vp0, &vt0);
03868       if (tp0)
03869          ast_rtp_get_peer(tp0, &tt0);
03870       if (pr0->get_codec)
03871          codec0 = pr0->get_codec(c0);
03872       if ((inaddrcmp(&t1, &ac1)) ||
03873           (vp1 && inaddrcmp(&vt1, &vac1)) ||
03874           (tp1 && inaddrcmp(&tt1, &tac1)) ||
03875           (codec1 != oldcodec1)) {
03876          ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03877             c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
03878          ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
03879             c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
03880          ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n",
03881             c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1);
03882          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03883             c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
03884          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03885             c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
03886          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03887             c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1);
03888          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)))
03889             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
03890          memcpy(&ac1, &t1, sizeof(ac1));
03891          memcpy(&vac1, &vt1, sizeof(vac1));
03892          memcpy(&tac1, &tt1, sizeof(tac1));
03893          oldcodec1 = codec1;
03894       }
03895       if ((inaddrcmp(&t0, &ac0)) ||
03896           (vp0 && inaddrcmp(&vt0, &vac0)) ||
03897           (tp0 && inaddrcmp(&tt0, &tac0))) {
03898          ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03899             c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
03900          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03901             c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
03902          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)))
03903             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
03904          memcpy(&ac0, &t0, sizeof(ac0));
03905          memcpy(&vac0, &vt0, sizeof(vac0));
03906          memcpy(&tac0, &tt0, sizeof(tac0));
03907          oldcodec0 = codec0;
03908       }
03909 
03910       /* Wait for frame to come in on the channels */
03911       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03912          if (!timeoutms) {
03913             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
03914                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03915             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
03916                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03917             return AST_BRIDGE_RETRY;
03918          }
03919          ast_debug(1, "Ooh, empty read...\n");
03920          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03921             break;
03922          continue;
03923       }
03924       fr = ast_read(who);
03925       other = (who == c0) ? c1 : c0;
03926       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03927              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
03928               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
03929          /* Break out of bridge */
03930          *fo = fr;
03931          *rc = who;
03932          ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03933          if (c0->tech_pvt == pvt0)
03934             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
03935                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03936          if (c1->tech_pvt == pvt1)
03937             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
03938                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03939          ast_poll_channel_del(c0, c1);
03940          return AST_BRIDGE_COMPLETE;
03941       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03942          if ((fr->subclass == AST_CONTROL_HOLD) ||
03943              (fr->subclass == AST_CONTROL_UNHOLD) ||
03944              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03945              (fr->subclass == AST_CONTROL_T38) ||
03946              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03947             if (fr->subclass == AST_CONTROL_HOLD) {
03948                /* If we someone went on hold we want the other side to reinvite back to us */
03949                if (who == c0)
03950                   pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0);
03951                else
03952                   pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0);
03953             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03954                /* If they went off hold they should go back to being direct */
03955                if (who == c0)
03956                   pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
03957                else
03958                   pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
03959             }
03960             /* Update local address information */
03961             ast_rtp_get_peer(p0, &t0);
03962             memcpy(&ac0, &t0, sizeof(ac0));
03963             ast_rtp_get_peer(p1, &t1);
03964             memcpy(&ac1, &t1, sizeof(ac1));
03965             /* Update codec information */
03966             if (pr0->get_codec && c0->tech_pvt)
03967                oldcodec0 = codec0 = pr0->get_codec(c0);
03968             if (pr1->get_codec && c1->tech_pvt)
03969                oldcodec1 = codec1 = pr1->get_codec(c1);
03970             ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
03971             ast_frfree(fr);
03972          } else {
03973             *fo = fr;
03974             *rc = who;
03975             ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03976             return AST_BRIDGE_COMPLETE;
03977          }
03978       } else {
03979          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03980              (fr->frametype == AST_FRAME_DTMF_END) ||
03981              (fr->frametype == AST_FRAME_VOICE) ||
03982              (fr->frametype == AST_FRAME_VIDEO) ||
03983              (fr->frametype == AST_FRAME_IMAGE) ||
03984              (fr->frametype == AST_FRAME_HTML) ||
03985              (fr->frametype == AST_FRAME_MODEM) ||
03986              (fr->frametype == AST_FRAME_TEXT)) {
03987             ast_write(other, fr);
03988          }
03989          ast_frfree(fr);
03990       }
03991       /* Swap priority */
03992 #ifndef HAVE_EPOLL
03993       cs[2] = cs[0];
03994       cs[0] = cs[1];
03995       cs[1] = cs[2];
03996 #endif
03997    }
03998 
03999    ast_poll_channel_del(c0, c1);
04000 
04001    if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
04002       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
04003    if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
04004       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
04005 
04006    return AST_BRIDGE_FAILED;
04007 }

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

04108 {
04109    struct ast_frame *fr = NULL;
04110    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
04111    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
04112    int p0_callback = 0, p1_callback = 0;
04113    enum ast_bridge_result res = AST_BRIDGE_FAILED;
04114 
04115    /* Okay, setup each RTP structure to do P2P forwarding */
04116    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
04117    p2p_set_bridge(p0, p1);
04118    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
04119    p2p_set_bridge(p1, p0);
04120 
04121    /* Activate callback modes if possible */
04122    p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
04123    p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
04124 
04125    /* Now let go of the channel locks and be on our way */
04126    ast_channel_unlock(c0);
04127    ast_channel_unlock(c1);
04128 
04129    ast_poll_channel_add(c0, c1);
04130 
04131    /* Go into a loop forwarding frames until we don't need to anymore */
04132    cs[0] = c0;
04133    cs[1] = c1;
04134    cs[2] = NULL;
04135    for (;;) {
04136       /* If the underlying formats have changed force this bridge to break */
04137       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
04138          ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n");
04139          res = AST_BRIDGE_FAILED_NOWARN;
04140          break;
04141       }
04142       /* Check if anything changed */
04143       if ((c0->tech_pvt != pvt0) ||
04144           (c1->tech_pvt != pvt1) ||
04145           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
04146           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
04147          ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n");
04148          /* 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 */
04149          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
04150             ast_frfree(fr);
04151          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
04152             ast_frfree(fr);
04153          res = AST_BRIDGE_RETRY;
04154          break;
04155       }
04156       /* Wait on a channel to feed us a frame */
04157       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
04158          if (!timeoutms) {
04159             res = AST_BRIDGE_RETRY;
04160             break;
04161          }
04162          if (option_debug > 2)
04163             ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n");
04164          if (ast_check_hangup(c0) || ast_check_hangup(c1))
04165             break;
04166          continue;
04167       }
04168       /* Read in frame from channel */
04169       fr = ast_read(who);
04170       other = (who == c0) ? c1 : c0;
04171       /* Depending on the frame we may need to break out of our bridge */
04172       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
04173              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
04174              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
04175          /* Record received frame and who */
04176          *fo = fr;
04177          *rc = who;
04178          ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
04179          res = AST_BRIDGE_COMPLETE;
04180          break;
04181       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
04182          if ((fr->subclass == AST_CONTROL_HOLD) ||
04183              (fr->subclass == AST_CONTROL_UNHOLD) ||
04184              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
04185              (fr->subclass == AST_CONTROL_T38) ||
04186              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
04187             /* If we are going on hold, then break callback mode and P2P bridging */
04188             if (fr->subclass == AST_CONTROL_HOLD) {
04189                if (p0_callback)
04190                   p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
04191                if (p1_callback)
04192                   p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
04193                p2p_set_bridge(p0, NULL);
04194                p2p_set_bridge(p1, NULL);
04195             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
04196                /* If we are off hold, then go back to callback mode and P2P bridging */
04197                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
04198                p2p_set_bridge(p0, p1);
04199                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
04200                p2p_set_bridge(p1, p0);
04201                p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
04202                p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
04203             }
04204             ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
04205             ast_frfree(fr);
04206          } else {
04207             *fo = fr;
04208             *rc = who;
04209             ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
04210             res = AST_BRIDGE_COMPLETE;
04211             break;
04212          }
04213       } else {
04214          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
04215              (fr->frametype == AST_FRAME_DTMF_END) ||
04216              (fr->frametype == AST_FRAME_VOICE) ||
04217              (fr->frametype == AST_FRAME_VIDEO) ||
04218              (fr->frametype == AST_FRAME_IMAGE) ||
04219              (fr->frametype == AST_FRAME_HTML) ||
04220              (fr->frametype == AST_FRAME_MODEM) ||
04221              (fr->frametype == AST_FRAME_TEXT)) {
04222             ast_write(other, fr);
04223          }
04224 
04225          ast_frfree(fr);
04226       }
04227       /* Swap priority */
04228 #ifndef HAVE_EPOLL
04229       cs[2] = cs[0];
04230       cs[0] = cs[1];
04231       cs[1] = cs[2];
04232 #endif
04233    }
04234 
04235    /* If we are totally avoiding the core, then restore our link to it */
04236    if (p0_callback)
04237       p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
04238    if (p1_callback)
04239       p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
04240 
04241    /* Break out of the direct bridge */
04242    p2p_set_bridge(p0, NULL);
04243    p2p_set_bridge(p1, NULL);
04244 
04245    ast_poll_channel_del(c0, c1);
04246 
04247    return res;
04248 }

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

01472 {
01473    int res = 0, payload = 0, bridged_payload = 0, mark;
01474    struct rtpPayloadType rtpPT;
01475    int reconstruct = ntohl(rtpheader[0]);
01476 
01477    /* Get fields from packet */
01478    payload = (reconstruct & 0x7f0000) >> 16;
01479    mark = (((reconstruct & 0x800000) >> 23) != 0);
01480 
01481    /* Check what the payload value should be */
01482    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01483 
01484    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01485    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01486       return -1;
01487 
01488    /* Otherwise adjust bridged payload to match */
01489    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01490 
01491    /* 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 */
01492    if (!bridged->current_RTP_PT[bridged_payload].code)
01493       return -1;
01494 
01495 
01496    /* If the mark bit has not been sent yet... do it now */
01497    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01498       mark = 1;
01499       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01500    }
01501 
01502    /* Reconstruct part of the packet */
01503    reconstruct &= 0xFF80FFFF;
01504    reconstruct |= (bridged_payload << 16);
01505    reconstruct |= (mark << 23);
01506    rtpheader[0] = htonl(reconstruct);
01507 
01508    /* Send the packet back out */
01509    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01510    if (res < 0) {
01511       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01512          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));
01513       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01514          if (option_debug || rtpdebug)
01515             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));
01516          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01517       }
01518       return 0;
01519    } else if (rtp_debug_test_addr(&bridged->them))
01520          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);
01521 
01522    return 0;
01523 }

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

Definition at line 1413 of file rtp.c.

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

Referenced by ast_rtp_read(), and schedule_delivery().

01414 {
01415    struct timeval now;
01416    double transit;
01417    double current_time;
01418    double d;
01419    double dtv;
01420    double prog;
01421    
01422    double normdev_rxjitter_current;
01423    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01424       gettimeofday(&rtp->rxcore, NULL);
01425       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01426       /* map timestamp to a real time */
01427       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01428       rtp->rxcore.tv_sec -= timestamp / 8000;
01429       rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
01430       /* Round to 0.1ms for nice, pretty timestamps */
01431       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01432       if (rtp->rxcore.tv_usec < 0) {
01433          /* Adjust appropriately if necessary */
01434          rtp->rxcore.tv_usec += 1000000;
01435          rtp->rxcore.tv_sec -= 1;
01436       }
01437    }
01438 
01439    gettimeofday(&now,NULL);
01440    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01441    when->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
01442    when->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
01443    if (when->tv_usec >= 1000000) {
01444       when->tv_usec -= 1000000;
01445       when->tv_sec += 1;
01446    }
01447    prog = (double)((timestamp-rtp->seedrxts)/8000.);
01448    dtv = (double)rtp->drxcore + (double)(prog);
01449    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01450    transit = current_time - dtv;
01451    d = transit - rtp->rxtransit;
01452    rtp->rxtransit = transit;
01453    if (d<0)
01454       d=-d;
01455    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01456    if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
01457       rtp->rtcp->maxrxjitter = rtp->rxjitter;
01458    if (rtp->rtcp->rxjitter_count == 1) 
01459       rtp->rtcp->minrxjitter = rtp->rxjitter;
01460    if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01461       rtp->rtcp->minrxjitter = rtp->rxjitter;
01462       
01463    normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
01464    rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
01465 
01466    rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
01467    rtp->rtcp->rxjitter_count++;
01468 }

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

Definition at line 3017 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

03018 {
03019    struct timeval t;
03020    long ms;
03021    if (ast_tvzero(rtp->txcore)) {
03022       rtp->txcore = ast_tvnow();
03023       /* Round to 20ms for nice, pretty timestamps */
03024       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
03025    }
03026    /* Use previous txcore if available */
03027    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
03028    ms = ast_tvdiff_ms(t, rtp->txcore);
03029    if (ms < 0)
03030       ms = 0;
03031    /* Use what we just got for next time */
03032    rtp->txcore = t;
03033    return (unsigned int) ms;
03034 }

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

Get channel driver interface structure.

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

02010 {
02011    struct ast_rtp_protocol *cur = NULL;
02012 
02013    AST_RWLIST_RDLOCK(&protos);
02014    AST_RWLIST_TRAVERSE(&protos, cur, list) {
02015       if (cur->type == chan->tech->type)
02016          break;
02017    }
02018    AST_RWLIST_UNLOCK(&protos);
02019 
02020    return cur;
02021 }

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

Definition at line 4563 of file rtp.c.

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

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

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

Definition at line 4598 of file rtp.c.

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

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

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

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

04655 {
04656    switch (cmd) {
04657    case CLI_INIT:
04658       e->command = "rtcp set stats {on|off}";
04659       e->usage =
04660          "Usage: rtcp set stats {on|off}\n"
04661          "       Enable/Disable dumping of RTCP stats.\n";
04662       return NULL;
04663    case CLI_GENERATE:
04664       return NULL;
04665    }
04666 
04667    if (a->argc != e->args)
04668       return CLI_SHOWUSAGE;
04669 
04670    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04671       rtcpstats = 1;
04672    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04673       rtcpstats = 0;
04674    else
04675       return CLI_SHOWUSAGE;
04676 
04677    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04678    return CLI_SUCCESS;
04679 }

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

Definition at line 4631 of file rtp.c.

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

04632 {
04633    switch (cmd) {
04634    case CLI_INIT:
04635       e->command = "rtcp stats [off]";
04636       e->usage =
04637          "Usage: rtcp stats [off]\n"
04638          "       Enable/Disable dumping of RTCP stats.\n";
04639       return NULL;
04640    case CLI_GENERATE:
04641       return NULL;
04642    }
04643 
04644    if (a->argc < 2 || a->argc > 3)
04645       return CLI_SHOWUSAGE;
04646    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04647       return CLI_SHOWUSAGE;
04648 
04649    rtcpstats = (a->argc == 3) ? 0 : 1;
04650    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04651    return CLI_SUCCESS;
04652 }

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

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

04496 {
04497    switch (cmd) {
04498    case CLI_INIT:
04499       e->command = "rtp debug [off|ip]";
04500       e->usage =
04501          "Usage: rtp debug [off]|[ip host[:port]]\n"
04502          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
04503          "       specified, limit the dumped packets to those to and from\n"
04504          "       the specified 'host' with optional port.\n";
04505       return NULL;
04506    case CLI_GENERATE:
04507       return NULL;
04508    }
04509 
04510    if (a->argc < 2 || a->argc > 4)
04511       return CLI_SHOWUSAGE;
04512    if (a->argc == 2) {
04513       rtpdebug = 1;
04514       memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
04515       ast_cli(a->fd, "RTP Debugging Enabled\n");
04516    } else if (a->argc == 3) {
04517       if (strncasecmp(a->argv[2], "off", 3))
04518          return CLI_SHOWUSAGE;
04519       rtpdebug = 0;
04520       ast_cli(a->fd, "RTP Debugging Disabled\n");
04521    } else {
04522       if (strncasecmp(a->argv[2], "ip", 2))
04523          return CLI_SHOWUSAGE;
04524       return rtp_do_debug_ip(a);
04525    }
04526 
04527    return CLI_SUCCESS;
04528 }

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

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

04531 {
04532    switch (cmd) {
04533    case CLI_INIT:
04534       e->command = "rtp set debug {on|off|ip}";
04535       e->usage =
04536          "Usage: rtp set debug {on|off|ip host[:port]}\n"
04537          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
04538          "       specified, limit the dumped packets to those to and from\n"
04539          "       the specified 'host' with optional port.\n";
04540       return NULL;
04541    case CLI_GENERATE:
04542       return NULL;
04543    }
04544 
04545    if (a->argc == e->args) { /* set on or off */
04546       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
04547          rtpdebug = 1;
04548          memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
04549          ast_cli(a->fd, "RTP Debugging Enabled\n");
04550          return CLI_SUCCESS;
04551       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
04552          rtpdebug = 0;
04553          ast_cli(a->fd, "RTP Debugging Disabled\n");
04554          return CLI_SUCCESS;
04555       }
04556    } else if (a->argc == e->args +1) { /* ip */
04557       return rtp_do_debug_ip(a);
04558    }
04559 
04560    return CLI_SHOWUSAGE;   /* default, failure */
04561 }

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

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

04682 {
04683    switch (cmd) {
04684    case CLI_INIT:
04685       e->command = "stun debug [off]";
04686       e->usage =
04687          "Usage: stun debug [off]\n"
04688          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04689          "       debugging\n";
04690       return NULL;
04691    case CLI_GENERATE:
04692       return NULL;
04693    }
04694 
04695    if (a->argc < 2 || a->argc > 3)
04696       return CLI_SHOWUSAGE;
04697    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04698       return CLI_SHOWUSAGE;
04699 
04700    stundebug = (a->argc == 3) ? 0 : 1;
04701    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04702    return CLI_SUCCESS;
04703 }

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

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

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

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

Calculate normal deviation.

Definition at line 840 of file rtp.c.

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

00841 {
00842    normdev = normdev * sample_count + sample;
00843    sample_count++;
00844 
00845    return normdev / sample_count;
00846 }

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

04076 {
04077    ast_channel_lock(chan);
04078 
04079    /* Remove the callback from the IO context */
04080    ast_io_remove(rtp->io, iod[0]);
04081 
04082    /* Restore file descriptors */
04083    chan->fds[0] = ast_rtp_fd(rtp);
04084    ast_channel_unlock(chan);
04085 
04086    /* Restore callback mode if previously used */
04087    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
04088       rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp);
04089 
04090    return 0;
04091 }

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

P2P RTP Callback.

Definition at line 4068 of file rtp.c.

Referenced by bridge_p2p_loop().

04069 {
04070    return 0;
04071 }

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

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

Referenced by bridge_p2p_loop().

04095 {
04096    rtp_bridge_lock(rtp0);
04097    rtp0->bridged = rtp1;
04098    rtp_bridge_unlock(rtp0);
04099 }

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

Definition at line 920 of file rtp.c.

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

Referenced by ast_rtp_read().

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

static struct ast_frame* process_rfc2833 ( struct ast_rtp rtp,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp 
) [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 
Returns:

Definition at line 1010 of file rtp.c.

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

Referenced by ast_rtp_read().

01011 {
01012    unsigned int event;
01013    unsigned int event_end;
01014    unsigned int samples;
01015    char resp = 0;
01016    struct ast_frame *f = NULL;
01017 
01018    /* Figure out event, event end, and samples */
01019    event = ntohl(*((unsigned int *)(data)));
01020    event >>= 24;
01021    event_end = ntohl(*((unsigned int *)(data)));
01022    event_end <<= 8;
01023    event_end >>= 24;
01024    samples = ntohl(*((unsigned int *)(data)));
01025    samples &= 0xFFFF;
01026 
01027    /* Print out debug if turned on */
01028    if (rtpdebug || option_debug > 2)
01029       ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
01030 
01031    /* Figure out what digit was pressed */
01032    if (event < 10) {
01033       resp = '0' + event;
01034    } else if (event < 11) {
01035       resp = '*';
01036    } else if (event < 12) {
01037       resp = '#';
01038    } else if (event < 16) {
01039       resp = 'A' + (event - 12);
01040    } else if (event < 17) {   /* Event 16: Hook flash */
01041       resp = 'X'; 
01042    } else {
01043       /* Not a supported event */
01044       ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
01045       return &ast_null_frame;
01046    }
01047 
01048    if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
01049       if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
01050          rtp->resp = resp;
01051          rtp->dtmfcount = 0;
01052          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01053          f->len = 0;
01054          rtp->lastevent = timestamp;
01055       }
01056    } else {
01057       if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) {
01058          rtp->resp = resp;
01059          f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
01060          rtp->dtmfcount = dtmftimeout;
01061       } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) {
01062          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01063          f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
01064          rtp->resp = 0;
01065          rtp->dtmfcount = 0;
01066          rtp->lastevent = seqno;
01067       }
01068    }
01069 
01070    rtp->dtmfsamples = samples;
01071 
01072    return f;
01073 }

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

01082 {
01083    struct ast_frame *f = NULL;
01084    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
01085       totally help us out becuase we don't have an engine to keep it going and we are not
01086       guaranteed to have it every 20ms or anything */
01087    if (rtpdebug)
01088       ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
01089 
01090    if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
01091       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
01092          ast_inet_ntoa(rtp->them.sin_addr));
01093       ast_set_flag(rtp, FLAG_3389_WARNING);
01094    }
01095    
01096    /* Must have at least one byte */
01097    if (!len)
01098       return NULL;
01099    if (len < 24) {
01100       rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
01101       rtp->f.datalen = len - 1;
01102       rtp->f.offset = AST_FRIENDLY_OFFSET;
01103       memcpy(rtp->f.data.ptr, data + 1, len - 1);
01104    } else {
01105       rtp->f.data.ptr = NULL;
01106       rtp->f.offset = 0;
01107       rtp->f.datalen = 0;
01108    }
01109    rtp->f.frametype = AST_FRAME_CNG;
01110    rtp->f.subclass = data[0] & 0x7f;
01111    rtp->f.datalen = len - 1;
01112    rtp->f.samples = 0;
01113    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
01114    f = &rtp->f;
01115    return f;
01116 }

void red_buffer_t140 ( struct ast_rtp rtp,
struct ast_frame f 
)

Buffer t.140 data.

Parameters:
rtp 
f frame

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

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

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

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

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

Definition at line 4830 of file rtp.c.

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

Referenced by rtp_red_init().

04831 {
04832    struct ast_rtp *rtp = (struct ast_rtp*) data;
04833    
04834    ast_rtp_write(rtp, &rtp->red->t140); 
04835 
04836    return 1;   
04837 }

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

Definition at line 906 of file rtp.c.

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

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

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

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

04466 {
04467    struct hostent *hp;
04468    struct ast_hostent ahp;
04469    int port = 0;
04470    char *p, *arg;
04471 
04472    arg = a->argv[3];
04473    p = strstr(arg, ":");
04474    if (p) {
04475       *p = '\0';
04476       p++;
04477       port = atoi(p);
04478    }
04479    hp = ast_gethostbyname(arg, &ahp);
04480    if (hp == NULL) {
04481       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04482       return CLI_FAILURE;
04483    }
04484    rtcpdebugaddr.sin_family = AF_INET;
04485    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
04486    rtcpdebugaddr.sin_port = htons(port);
04487    if (port == 0)
04488       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
04489    else
04490       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
04491    rtcpdebug = 1;
04492    return CLI_SUCCESS;
04493 }

static void rtp_bridge_lock ( struct ast_rtp rtp  )  [static]

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

00824 {
00825 #ifdef P2P_INTENSE
00826    ast_mutex_lock(&rtp->bridge_lock);
00827 #endif
00828    return;
00829 }

static void rtp_bridge_unlock ( struct ast_rtp rtp  )  [static]

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

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

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

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

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

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

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

04436 {
04437    struct hostent *hp;
04438    struct ast_hostent ahp;
04439    int port = 0;
04440    char *p, *arg;
04441 
04442    arg = a->argv[3];
04443    p = strstr(arg, ":");
04444    if (p) {
04445       *p = '\0';
04446       p++;
04447       port = atoi(p);
04448    }
04449    hp = ast_gethostbyname(arg, &ahp);
04450    if (hp == NULL) {
04451       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04452       return CLI_FAILURE;
04453    }
04454    rtpdebugaddr.sin_family = AF_INET;
04455    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
04456    rtpdebugaddr.sin_port = htons(port);
04457    if (port == 0)
04458       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
04459    else
04460       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
04461    rtpdebug = 1;
04462    return CLI_SUCCESS;
04463 }

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

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

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

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

Definition at line 2386 of file rtp.c.

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

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

02387 {
02388    int s = socket(AF_INET, SOCK_DGRAM, 0);
02389    if (s < 0) {
02390       if (type == NULL)
02391          type = "RTP/RTCP";
02392       ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
02393    } else {
02394       long flags = fcntl(s, F_GETFL);
02395       fcntl(s, F_SETFL, flags | O_NONBLOCK);
02396 #ifdef SO_NO_CHECK
02397       if (nochecksums)
02398          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
02399 #endif
02400    }
02401    return s;
02402 }

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

Definition at line 1118 of file rtp.c.

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

Referenced by p2p_callback_disable().

01119 {
01120    struct ast_rtp *rtp = cbdata;
01121    struct ast_frame *f;
01122    f = ast_rtp_read(rtp);
01123    if (f) {
01124       if (rtp->callback)
01125          rtp->callback(rtp, f, rtp->data);
01126    }
01127    return 1;
01128 }

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

Definition at line 868 of file rtp.c.

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

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

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

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

Definition at line 848 of file rtp.c.

References SQUARE.

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

00849 {
00850 /*
00851       for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
00852       return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
00853       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
00854       optimized formula
00855 */
00856 #define SQUARE(x) ((x) * (x))
00857 
00858    stddev = sample_count * stddev;
00859    sample_count++;
00860 
00861    return stddev + 
00862           ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) + 
00863           ( SQUARE(sample - normdev_curent) / sample_count );
00864 
00865 #undef SQUARE
00866 }

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

helper function to print attribute names

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

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

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

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

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

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

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

helper function to print message names

Definition at line 373 of file rtp.c.

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

Referenced by stun_handle_packet().

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

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

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

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

static void stun_req_id ( struct stun_header req  )  [static]

helper function to generate a random request id

Definition at line 489 of file rtp.c.

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

Referenced by ast_stun_request().

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

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

wrapper to send an STUN message

Definition at line 482 of file rtp.c.

References stun_header::msglen.

Referenced by ast_stun_request(), and stun_handle_packet().

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

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

Definition at line 710 of file rtp.c.

References sec.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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


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

struct ast_cli_entry cli_rtp[] [static]

Definition at line 4738 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 4733 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 4736 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 1866 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 1911 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 1868 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1867 of file rtp.c.

Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), aji_handle_presence(), amixer_max(), 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 Fri Jul 24 00:41:58 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7