Thu Jul 9 13:41:31 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 "asterisk/rtp.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  rtpPayloadType
 Structure representing a RTP session.The value of each payload format mapping:. More...
struct  stun_addr
struct  stun_attr
struct  stun_header
struct  stun_state
 here we store credentials extracted from a message More...
struct  stun_trans_id
 STUN support code. More...

Defines

#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))
#define FLAG_3389_WARNING   (1 << 0)
#define FLAG_CALLBACK_MODE   (1 << 6)
#define FLAG_DTMF_COMPENSATE   (1 << 7)
#define FLAG_HAS_DTMF   (1 << 3)
#define FLAG_HAS_STUN   (1 << 8)
#define FLAG_NAT_ACTIVE   (3 << 1)
#define FLAG_NAT_INACTIVE   (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
#define FLAG_P2P_NEED_DTMF   (1 << 5)
#define FLAG_P2P_SENT_MARK   (1 << 4)
#define MAX_TIMESTAMP_SKEW   640
#define RTCP_DEFAULT_INTERVALMS   5000
#define RTCP_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 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 int __ast_rtp_reload (int reload)
static void append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, 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)
char * ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual)
 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_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt)
 set potential alternate source for RTP media
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Activate payload type.
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Initiate payload type to a known MIME media type for a codec.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_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 tos, int cos, 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 *tv, 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 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.
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)
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 const char * stun_attr2str (int msg)
 helper function to print attribute names
static int stun_get_mapped (struct stun_attr *attr, void *arg)
 Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_response when called from ast_stun_request.
static int stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
 handle an incoming STUN message.
static const char * stun_msg2str (int msg)
 helper function to print message names
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
static void stun_req_id (struct stun_header *req)
 helper function to generate a random request id
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
 wrapper to send an STUN message
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)

Variables

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


Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

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

samples

Definition at line 65 of file rtp.c.

Referenced by __ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 193 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 200 of file rtp.c.

Referenced by p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 194 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 195 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 196 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 199 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

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

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

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

Referenced by __ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 61 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 60 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

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

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

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

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 63 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 51 of file rtp.c.

Referenced by ast_rtp_read().

#define STUN_ACCEPT   (1)

Definition at line 294 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

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

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

#define STUN_BINDRESP   0x0101

Definition at line 304 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 315 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 317 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 321 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

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

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

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 320 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 319 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 323 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 314 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 308 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 306 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 307 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 316 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 322 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

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

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


Function Documentation

static int __ast_rtp_reload ( int  reload  )  [static]

Definition at line 4296 of file rtp.c.

References ast_config_destroy(), ast_config_load, ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTMF_TIMEOUT, LOG_WARNING, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and STRICT_RTP_OPEN.

Referenced by ast_rtp_init(), and ast_rtp_reload().

04297 {
04298    struct ast_config *cfg;
04299    const char *s;
04300    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04301 
04302    if ((cfg = ast_config_load("rtp.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
04303       return 0;
04304 
04305    rtpstart = 5000;
04306    rtpend = 31000;
04307    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04308    strictrtp = STRICT_RTP_OPEN;
04309    if (cfg) {
04310       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
04311          rtpstart = atoi(s);
04312          if (rtpstart < 1024)
04313             rtpstart = 1024;
04314          if (rtpstart > 65535)
04315             rtpstart = 65535;
04316       }
04317       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
04318          rtpend = atoi(s);
04319          if (rtpend < 1024)
04320             rtpend = 1024;
04321          if (rtpend > 65535)
04322             rtpend = 65535;
04323       }
04324       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
04325          rtcpinterval = atoi(s);
04326          if (rtcpinterval == 0)
04327             rtcpinterval = 0; /* Just so we're clear... it's zero */
04328          if (rtcpinterval < RTCP_MIN_INTERVALMS)
04329             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
04330          if (rtcpinterval > RTCP_MAX_INTERVALMS)
04331             rtcpinterval = RTCP_MAX_INTERVALMS;
04332       }
04333       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
04334 #ifdef SO_NO_CHECK
04335          if (ast_false(s))
04336             nochecksums = 1;
04337          else
04338             nochecksums = 0;
04339 #else
04340          if (ast_false(s))
04341             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
04342 #endif
04343       }
04344       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
04345          dtmftimeout = atoi(s);
04346          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
04347             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
04348                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
04349             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
04350          };
04351       }
04352       if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
04353          strictrtp = ast_true(s);
04354       }
04355       ast_config_destroy(cfg);
04356    }
04357    if (rtpstart >= rtpend) {
04358       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
04359       rtpstart = 5000;
04360       rtpend = 31000;
04361    }
04362    ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
04363    return 0;
04364 }

static void append_attr_address ( struct stun_attr **  attr,
int  attrval,
struct sockaddr_in *  sin,
int *  len,
int *  left 
) [static]

append an address to an STUN message

Definition at line 416 of file rtp.c.

References stun_addr::addr.

Referenced by stun_handle_packet().

00417 {
00418    int size = sizeof(**attr) + 8;
00419    struct stun_addr *addr;
00420    if (*left > size) {
00421       (*attr)->attr = htons(attrval);
00422       (*attr)->len = htons(8);
00423       addr = (struct stun_addr *)((*attr)->value);
00424       addr->unused = 0;
00425       addr->family = 0x01;
00426       addr->port = sin->sin_port;
00427       addr->addr = sin->sin_addr.s_addr;
00428       (*attr) = (struct stun_attr *)((*attr)->value + 8);
00429       *len += size;
00430       *left -= size;
00431    }
00432 }

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

Referenced by ast_stun_request(), and stun_handle_packet().

00403 {
00404    int size = sizeof(**attr) + strlen(s);
00405    if (*left > size) {
00406       (*attr)->attr = htons(attrval);
00407       (*attr)->len = htons(strlen(s));
00408       memcpy((*attr)->value, s, strlen(s));
00409       (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
00410       *len += size;
00411       *left -= size;
00412    }
00413 }

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 685 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00686 {
00687    unsigned int interval;
00688    /*! \todo XXX Do a more reasonable calculation on this one
00689     * Look in RFC 3550 Section A.7 for an example*/
00690    interval = rtcpinterval;
00691    return interval;
00692 }

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

00679 {
00680    if (rtp->rtcp)
00681       return rtp->rtcp->s;
00682    return -1;
00683 }

static struct ast_rtcp* ast_rtcp_new ( void   )  [static]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 2241 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr().

02242 {
02243    struct ast_rtcp *rtcp;
02244 
02245    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
02246       return NULL;
02247    rtcp->s = rtp_socket("RTCP");
02248    rtcp->us.sin_family = AF_INET;
02249    rtcp->them.sin_family = AF_INET;
02250    rtcp->schedid = -1;
02251 
02252    if (rtcp->s < 0) {
02253       ast_free(rtcp);
02254       return NULL;
02255    }
02256 
02257    return rtcp;
02258 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 1090 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_rtcp::altthem, ast_assert, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, EVENT_FLAG_REPORTING, f, ast_rtp::f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, 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().

01091 {
01092    socklen_t len;
01093    int position, i, packetwords;
01094    int res;
01095    struct sockaddr_in sin;
01096    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
01097    unsigned int *rtcpheader;
01098    int pt;
01099    struct timeval now;
01100    unsigned int length;
01101    int rc;
01102    double rttsec;
01103    uint64_t rtt = 0;
01104    unsigned int dlsr;
01105    unsigned int lsr;
01106    unsigned int msw;
01107    unsigned int lsw;
01108    unsigned int comp;
01109    struct ast_frame *f = &ast_null_frame;
01110    
01111    if (!rtp || !rtp->rtcp)
01112       return &ast_null_frame;
01113 
01114    len = sizeof(sin);
01115    
01116    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
01117                0, (struct sockaddr *)&sin, &len);
01118    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
01119    
01120    if (res < 0) {
01121       ast_assert(errno != EBADF);
01122       if (errno != EAGAIN) {
01123          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
01124          return NULL;
01125       }
01126       return &ast_null_frame;
01127    }
01128 
01129    packetwords = res / 4;
01130    
01131    if (rtp->nat) {
01132       /* Send to whoever sent to us */
01133       if (((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01134           (rtp->rtcp->them.sin_port != sin.sin_port)) && 
01135           ((rtp->rtcp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) || 
01136           (rtp->rtcp->altthem.sin_port != sin.sin_port))) {
01137          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01138          if (option_debug || rtpdebug)
01139             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));
01140       }
01141    }
01142 
01143    ast_debug(1, "Got RTCP report of %d bytes\n", res);
01144 
01145    /* Process a compound packet */
01146    position = 0;
01147    while (position < packetwords) {
01148       i = position;
01149       length = ntohl(rtcpheader[i]);
01150       pt = (length & 0xff0000) >> 16;
01151       rc = (length & 0x1f000000) >> 24;
01152       length &= 0xffff;
01153  
01154       if ((i + length) > packetwords) {
01155          if (option_debug || rtpdebug)
01156             ast_log(LOG_DEBUG, "RTCP Read too short\n");
01157          return &ast_null_frame;
01158       }
01159       
01160       if (rtcp_debug_test_addr(&sin)) {
01161          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01162          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
01163          ast_verbose("Reception reports: %d\n", rc);
01164          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
01165       }
01166  
01167       i += 2; /* Advance past header and ssrc */
01168       
01169       switch (pt) {
01170       case RTCP_PT_SR:
01171          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
01172          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
01173          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
01174          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
01175  
01176          if (rtcp_debug_test_addr(&sin)) {
01177             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
01178             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
01179             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
01180          }
01181          i += 5;
01182          if (rc < 1)
01183             break;
01184          /* Intentional fall through */
01185       case RTCP_PT_RR:
01186          /* Don't handle multiple reception reports (rc > 1) yet */
01187          /* Calculate RTT per RFC */
01188          gettimeofday(&now, NULL);
01189          timeval2ntp(now, &msw, &lsw);
01190          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
01191             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
01192             lsr = ntohl(rtcpheader[i + 4]);
01193             dlsr = ntohl(rtcpheader[i + 5]);
01194             rtt = comp - lsr - dlsr;
01195 
01196             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
01197                sess->ee_delay = (eedelay * 1000) / 65536; */
01198             if (rtt < 4294) {
01199                 rtt = (rtt * 1000000) >> 16;
01200             } else {
01201                 rtt = (rtt * 1000) >> 16;
01202                 rtt *= 1000;
01203             }
01204             rtt = rtt / 1000.;
01205             rttsec = rtt / 1000.;
01206 
01207             if (comp - dlsr >= lsr) {
01208                rtp->rtcp->accumulated_transit += rttsec;
01209                rtp->rtcp->rtt = rttsec;
01210                if (rtp->rtcp->maxrtt<rttsec)
01211                   rtp->rtcp->maxrtt = rttsec;
01212                if (rtp->rtcp->minrtt>rttsec)
01213                   rtp->rtcp->minrtt = rttsec;
01214             } else if (rtcp_debug_test_addr(&sin)) {
01215                ast_verbose("Internal RTCP NTP clock skew detected: "
01216                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
01217                         "diff=%d\n",
01218                         lsr, comp, dlsr, dlsr / 65536,
01219                         (dlsr % 65536) * 1000 / 65536,
01220                         dlsr - (comp - lsr));
01221             }
01222          }
01223 
01224          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01225          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01226          if (rtcp_debug_test_addr(&sin)) {
01227             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01228             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01229             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01230             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01231             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01232             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01233             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01234             if (rtt)
01235                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
01236          }
01237          if (rtt) {
01238             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01239                             "PT: %d(%s)\r\n"
01240                             "ReceptionReports: %d\r\n"
01241                             "SenderSSRC: %u\r\n"
01242                             "FractionLost: %ld\r\n"
01243                             "PacketsLost: %d\r\n"
01244                             "HighestSequence: %ld\r\n"
01245                             "SequenceNumberCycles: %ld\r\n"
01246                             "IAJitter: %u\r\n"
01247                             "LastSR: %lu.%010lu\r\n"
01248                             "DLSR: %4.4f(sec)\r\n"
01249                             "RTT: %llu(sec)\r\n",
01250                             ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
01251                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01252                             rc,
01253                             rtcpheader[i + 1],
01254                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01255                             rtp->rtcp->reported_lost,
01256                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01257                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01258                             rtp->rtcp->reported_jitter,
01259                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01260                             ntohl(rtcpheader[i + 5])/65536.0,
01261                             (unsigned long long)rtt);
01262          } else {
01263             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01264                             "PT: %d(%s)\r\n"
01265                             "ReceptionReports: %d\r\n"
01266                             "SenderSSRC: %u\r\n"
01267                             "FractionLost: %ld\r\n"
01268                             "PacketsLost: %d\r\n"
01269                             "HighestSequence: %ld\r\n"
01270                             "SequenceNumberCycles: %ld\r\n"
01271                             "IAJitter: %u\r\n"
01272                             "LastSR: %lu.%010lu\r\n"
01273                             "DLSR: %4.4f(sec)\r\n",
01274                             ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
01275                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01276                             rc,
01277                             rtcpheader[i + 1],
01278                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01279                             rtp->rtcp->reported_lost,
01280                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01281                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01282                             rtp->rtcp->reported_jitter,
01283                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
01284                             ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01285                             ntohl(rtcpheader[i + 5])/65536.0);
01286          }
01287          break;
01288       case RTCP_PT_FUR:
01289          if (rtcp_debug_test_addr(&sin))
01290             ast_verbose("Received an RTCP Fast Update Request\n");
01291          rtp->f.frametype = AST_FRAME_CONTROL;
01292          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
01293          rtp->f.datalen = 0;
01294          rtp->f.samples = 0;
01295          rtp->f.mallocd = 0;
01296          rtp->f.src = "RTP";
01297          f = &rtp->f;
01298          break;
01299       case RTCP_PT_SDES:
01300          if (rtcp_debug_test_addr(&sin))
01301             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01302          break;
01303       case RTCP_PT_BYE:
01304          if (rtcp_debug_test_addr(&sin))
01305             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01306          break;
01307       default:
01308          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));
01309          break;
01310       }
01311       position += (length + 1);
01312    }
01313          
01314    return f;
01315 }

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

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

02771 {
02772    struct ast_rtp *rtp = data;
02773    int res;
02774 
02775    rtp->rtcp->sendfur = 1;
02776    res = ast_rtcp_write(data);
02777    
02778    return res;
02779 }

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

03011 {
03012    struct ast_rtp *rtp = (struct ast_rtp *)data;
03013    int res;
03014    
03015    if (!rtp || !rtp->rtcp)
03016       return 0;
03017 
03018    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
03019       res = ast_rtcp_write_sr(data);
03020    else
03021       res = ast_rtcp_write_rr(data);
03022    
03023    return res;
03024 }

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 2915 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::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::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, and timersub().

Referenced by ast_rtcp_write().

02916 {
02917    struct ast_rtp *rtp = (struct ast_rtp *)data;
02918    int res;
02919    int len = 32;
02920    unsigned int lost;
02921    unsigned int extended;
02922    unsigned int expected;
02923    unsigned int expected_interval;
02924    unsigned int received_interval;
02925    int lost_interval;
02926    struct timeval now;
02927    unsigned int *rtcpheader;
02928    char bdata[1024];
02929    struct timeval dlsr;
02930    int fraction;
02931 
02932    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
02933       return 0;
02934      
02935    if (!rtp->rtcp->them.sin_addr.s_addr) {
02936       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
02937       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02938       return 0;
02939    }
02940 
02941    extended = rtp->cycles + rtp->lastrxseqno;
02942    expected = extended - rtp->seedrxseqno + 1;
02943    lost = expected - rtp->rxcount;
02944    expected_interval = expected - rtp->rtcp->expected_prior;
02945    rtp->rtcp->expected_prior = expected;
02946    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02947    rtp->rtcp->received_prior = rtp->rxcount;
02948    lost_interval = expected_interval - received_interval;
02949    if (expected_interval == 0 || lost_interval <= 0)
02950       fraction = 0;
02951    else
02952       fraction = (lost_interval << 8) / expected_interval;
02953    gettimeofday(&now, NULL);
02954    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02955    rtcpheader = (unsigned int *)bdata;
02956    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
02957    rtcpheader[1] = htonl(rtp->ssrc);
02958    rtcpheader[2] = htonl(rtp->themssrc);
02959    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02960    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02961    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02962    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
02963    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02964 
02965    if (rtp->rtcp->sendfur) {
02966       rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
02967       rtcpheader[9] = htonl(rtp->ssrc);               /* Our SSRC */
02968       len += 8;
02969       rtp->rtcp->sendfur = 0;
02970    }
02971 
02972    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
02973    it can change mid call, and SDES can't) */
02974    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02975    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02976    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
02977    len += 12;
02978    
02979    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02980 
02981    if (res < 0) {
02982       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
02983       /* Remove the scheduler */
02984       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02985       return 0;
02986    }
02987 
02988    rtp->rtcp->rr_count++;
02989 
02990    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02991       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
02992          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 
02993          "  IA jitter: %.4f\n" 
02994          "  Their last SR: %u\n" 
02995          "  DLSR: %4.4f (sec)\n\n",
02996          ast_inet_ntoa(rtp->rtcp->them.sin_addr),
02997          ntohs(rtp->rtcp->them.sin_port),
02998          rtp->ssrc, rtp->themssrc, fraction, lost,
02999          rtp->rxjitter,
03000          rtp->rtcp->themrxlsr,
03001          (double)(ntohl(rtcpheader[7])/65536.0));
03002    }
03003 
03004    return res;
03005 }

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

Send RTCP sender's report.

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

02783 {
02784    struct ast_rtp *rtp = (struct ast_rtp *)data;
02785    int res;
02786    int len = 0;
02787    struct timeval now;
02788    unsigned int now_lsw;
02789    unsigned int now_msw;
02790    unsigned int *rtcpheader;
02791    unsigned int lost;
02792    unsigned int extended;
02793    unsigned int expected;
02794    unsigned int expected_interval;
02795    unsigned int received_interval;
02796    int lost_interval;
02797    int fraction;
02798    struct timeval dlsr;
02799    char bdata[512];
02800 
02801    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
02802    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
02803       return 0;
02804    
02805    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
02806       ast_verbose("RTCP SR transmission error, rtcp halted\n");
02807       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02808       return 0;
02809    }
02810 
02811    gettimeofday(&now, NULL);
02812    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
02813    rtcpheader = (unsigned int *)bdata;
02814    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
02815    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
02816    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
02817    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
02818    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
02819    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
02820    len += 28;
02821    
02822    extended = rtp->cycles + rtp->lastrxseqno;
02823    expected = extended - rtp->seedrxseqno + 1;
02824    if (rtp->rxcount > expected) 
02825       expected += rtp->rxcount - expected;
02826    lost = expected - rtp->rxcount;
02827    expected_interval = expected - rtp->rtcp->expected_prior;
02828    rtp->rtcp->expected_prior = expected;
02829    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02830    rtp->rtcp->received_prior = rtp->rxcount;
02831    lost_interval = expected_interval - received_interval;
02832    if (expected_interval == 0 || lost_interval <= 0)
02833       fraction = 0;
02834    else
02835       fraction = (lost_interval << 8) / expected_interval;
02836    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02837    rtcpheader[7] = htonl(rtp->themssrc);
02838    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02839    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02840    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02841    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
02842    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02843    len += 24;
02844    
02845    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
02846 
02847    if (rtp->rtcp->sendfur) {
02848       rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
02849       rtcpheader[14] = htonl(rtp->ssrc);               /* Our SSRC */
02850       len += 8;
02851       rtp->rtcp->sendfur = 0;
02852    }
02853    
02854    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 
02855    /* it can change mid call, and SDES can't) */
02856    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02857    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02858    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
02859    len += 12;
02860    
02861    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02862    if (res < 0) {
02863       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));
02864       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02865       return 0;
02866    }
02867    
02868    /* FIXME Don't need to get a new one */
02869    gettimeofday(&rtp->rtcp->txlsr, NULL);
02870    rtp->rtcp->sr_count++;
02871 
02872    rtp->rtcp->lastsrtxcount = rtp->txcount;  
02873    
02874    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02875       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
02876       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
02877       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
02878       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
02879       ast_verbose("  Sent packets: %u\n", rtp->txcount);
02880       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
02881       ast_verbose("  Report block:\n");
02882       ast_verbose("  Fraction lost: %u\n", fraction);
02883       ast_verbose("  Cumulative loss: %u\n", lost);
02884       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
02885       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
02886       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
02887    }
02888    manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n"
02889                    "OurSSRC: %u\r\n"
02890                    "SentNTP: %u.%010u\r\n"
02891                    "SentRTP: %u\r\n"
02892                    "SentPackets: %u\r\n"
02893                    "SentOctets: %u\r\n"
02894                    "ReportBlock:\r\n"
02895                    "FractionLost: %u\r\n"
02896                    "CumulativeLoss: %u\r\n"
02897                    "IAJitter: %.4f\r\n"
02898                    "TheirLastSR: %u\r\n"
02899                    "DLSR: %4.4f (sec)\r\n",
02900                    ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
02901                    rtp->ssrc,
02902                    (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
02903                    rtp->lastts,
02904                    rtp->txcount,
02905                    rtp->txoctetcount,
02906                    fraction,
02907                    lost,
02908                    rtp->rxjitter,
02909                    rtp->rtcp->themrxlsr,
02910                    (double)(ntohl(rtcpheader[12])/65536.0));
02911    return res;
02912 }

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

Referenced by process_sdp().

00450 {
00451    return sizeof(struct ast_rtp);
00452 }

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

03834 {
03835    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03836    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03837    struct ast_rtp *tp0 = NULL, *tp1 = NULL;  /* Text RTP channels */
03838    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03839    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;
03840    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;
03841    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03842    int codec0 = 0, codec1 = 0;
03843    void *pvt0 = NULL, *pvt1 = NULL;
03844 
03845    /* Lock channels */
03846    ast_channel_lock(c0);
03847    while (ast_channel_trylock(c1)) {
03848       ast_channel_unlock(c0);
03849       usleep(1);
03850       ast_channel_lock(c0);
03851    }
03852 
03853    /* Ensure neither channel got hungup during lock avoidance */
03854    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03855       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
03856       ast_channel_unlock(c0);
03857       ast_channel_unlock(c1);
03858       return AST_BRIDGE_FAILED;
03859    }
03860       
03861    /* Find channel driver interfaces */
03862    if (!(pr0 = get_proto(c0))) {
03863       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03864       ast_channel_unlock(c0);
03865       ast_channel_unlock(c1);
03866       return AST_BRIDGE_FAILED;
03867    }
03868    if (!(pr1 = get_proto(c1))) {
03869       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03870       ast_channel_unlock(c0);
03871       ast_channel_unlock(c1);
03872       return AST_BRIDGE_FAILED;
03873    }
03874 
03875    /* Get channel specific interface structures */
03876    pvt0 = c0->tech_pvt;
03877    pvt1 = c1->tech_pvt;
03878 
03879    /* Get audio and video interface (if native bridge is possible) */
03880    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03881    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03882    text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03883    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03884    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03885    text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03886 
03887    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03888    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03889       audio_p0_res = AST_RTP_GET_FAILED;
03890    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03891       audio_p1_res = AST_RTP_GET_FAILED;
03892 
03893    /* Check if a bridge is possible (partial/native) */
03894    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03895       /* Somebody doesn't want to play... */
03896       ast_channel_unlock(c0);
03897       ast_channel_unlock(c1);
03898       return AST_BRIDGE_FAILED_NOWARN;
03899    }
03900 
03901    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03902    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03903       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03904       audio_p0_res = AST_RTP_TRY_PARTIAL;
03905    }
03906 
03907    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03908       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03909       audio_p1_res = AST_RTP_TRY_PARTIAL;
03910    }
03911 
03912    /* If both sides are not using the same method of DTMF transmission 
03913     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03914     * --------------------------------------------------
03915     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03916     * |-----------|------------|-----------------------|
03917     * | Inband    | False      | True                  |
03918     * | RFC2833   | True       | True                  |
03919     * | SIP INFO  | False      | False                 |
03920     * --------------------------------------------------
03921     * However, if DTMF from both channels is being monitored by the core, then
03922     * we can still do packet-to-packet bridging, because passing through the 
03923     * core will handle DTMF mode translation.
03924     */
03925    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03926        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03927       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03928          ast_channel_unlock(c0);
03929          ast_channel_unlock(c1);
03930          return AST_BRIDGE_FAILED_NOWARN;
03931       }
03932       audio_p0_res = AST_RTP_TRY_PARTIAL;
03933       audio_p1_res = AST_RTP_TRY_PARTIAL;
03934    }
03935 
03936    /* If we need to feed frames into the core don't do a P2P bridge */
03937    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
03938        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
03939       ast_channel_unlock(c0);
03940       ast_channel_unlock(c1);
03941       return AST_BRIDGE_FAILED_NOWARN;
03942    }
03943 
03944    /* Get codecs from both sides */
03945    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03946    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03947    if (codec0 && codec1 && !(codec0 & codec1)) {
03948       /* Hey, we can't do native bridging if both parties speak different codecs */
03949       ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03950       ast_channel_unlock(c0);
03951       ast_channel_unlock(c1);
03952       return AST_BRIDGE_FAILED_NOWARN;
03953    }
03954 
03955    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03956    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03957       struct ast_format_list fmt0, fmt1;
03958 
03959       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03960       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03961          ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
03962          ast_channel_unlock(c0);
03963          ast_channel_unlock(c1);
03964          return AST_BRIDGE_FAILED_NOWARN;
03965       }
03966       /* They must also be using the same packetization */
03967       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
03968       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
03969       if (fmt0.cur_ms != fmt1.cur_ms) {
03970          ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
03971          ast_channel_unlock(c0);
03972          ast_channel_unlock(c1);
03973          return AST_BRIDGE_FAILED_NOWARN;
03974       }
03975 
03976       ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03977       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03978    } else {
03979       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
03980       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03981    }
03982 
03983    return res;
03984 }

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3227 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

03228 {
03229    if (pt < 0 || pt > MAX_RTP_PT)
03230       return 0; /* bogus payload type */
03231 
03232    if (static_RTP_PT[pt].isAstFormat)
03233       return static_RTP_PT[pt].code;
03234    else
03235       return 0;
03236 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Get codec preference.

Definition at line 3222 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

03223 {
03224    return &rtp->pref;
03225 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

Definition at line 3176 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(), check_user_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().

03177 {
03178    struct ast_format_list current_format_old, current_format_new;
03179 
03180    /* if no packets have been sent through this session yet, then
03181     *  changing preferences does not require any extra work
03182     */
03183    if (rtp->lasttxformat == 0) {
03184       rtp->pref = *prefs;
03185       return;
03186    }
03187 
03188    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03189 
03190    rtp->pref = *prefs;
03191 
03192    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03193 
03194    /* if the framing desired for the current format has changed, we may have to create
03195     * or adjust the smoother for this session
03196     */
03197    if ((current_format_new.inc_ms != 0) &&
03198        (current_format_new.cur_ms != current_format_old.cur_ms)) {
03199       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
03200 
03201       if (rtp->smoother) {
03202          ast_smoother_reconfigure(rtp->smoother, new_size);
03203          if (option_debug) {
03204             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
03205          }
03206       } else {
03207          if (!(rtp->smoother = ast_smoother_new(new_size))) {
03208             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03209             return;
03210          }
03211          if (current_format_new.flags) {
03212             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
03213          }
03214          if (option_debug) {
03215             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03216          }
03217       }
03218    }
03219 
03220 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

Definition at line 2529 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(), check_user_ok(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), jingle_free_pvt(), mgcp_hangup(), oh323_alloc(), sip_alloc(), skinny_hangup(), start_rtp(), unalloc_sub(), and unistim_hangup().

02530 {
02531    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02532       /*Print some info on the call here */
02533       ast_verbose("  RTP-stats\n");
02534       ast_verbose("* Our Receiver:\n");
02535       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02536       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02537       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
02538       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02539       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02540       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
02541       ast_verbose("* Our Sender:\n");
02542       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02543       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02544       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
02545       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
02546       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
02547       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
02548    }
02549 
02550    manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
02551                    "ReceivedPackets: %u\r\n"
02552                    "LostPackets: %u\r\n"
02553                    "Jitter: %.4f\r\n"
02554                    "Transit: %.4f\r\n"
02555                    "RRCount: %u\r\n",
02556                    rtp->themssrc,
02557                    rtp->rxcount,
02558                    rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
02559                    rtp->rxjitter,
02560                    rtp->rxtransit,
02561                    rtp->rtcp ? rtp->rtcp->rr_count : 0);
02562    manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
02563                    "SentPackets: %u\r\n"
02564                    "LostPackets: %u\r\n"
02565                    "Jitter: %u\r\n"
02566                    "SRCount: %u\r\n"
02567                    "RTT: %f\r\n",
02568                    rtp->ssrc,
02569                    rtp->txcount,
02570                    rtp->rtcp ? rtp->rtcp->reported_lost : 0,
02571                    rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
02572                    rtp->rtcp ? rtp->rtcp->sr_count : 0,
02573                    rtp->rtcp ? rtp->rtcp->rtt : 0);
02574    if (rtp->smoother)
02575       ast_smoother_free(rtp->smoother);
02576    if (rtp->ioid)
02577       ast_io_remove(rtp->io, rtp->ioid);
02578    if (rtp->s > -1)
02579       close(rtp->s);
02580    if (rtp->rtcp) {
02581       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02582       close(rtp->rtcp->s);
02583       ast_free(rtp->rtcp);
02584       rtp->rtcp=NULL;
02585    }
02586 #ifdef P2P_INTENSE
02587    ast_mutex_destroy(&rtp->bridge_lock);
02588 #endif
02589    ast_free(rtp);
02590 }

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

01856 {
01857    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01858    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01859    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
01860    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01861    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;
01862    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;
01863    int srccodec, destcodec, nat_active = 0;
01864 
01865    /* Lock channels */
01866    ast_channel_lock(c0);
01867    if (c1) {
01868       while (ast_channel_trylock(c1)) {
01869          ast_channel_unlock(c0);
01870          usleep(1);
01871          ast_channel_lock(c0);
01872       }
01873    }
01874 
01875    /* Find channel driver interfaces */
01876    destpr = get_proto(c0);
01877    if (c1)
01878       srcpr = get_proto(c1);
01879    if (!destpr) {
01880       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
01881       ast_channel_unlock(c0);
01882       if (c1)
01883          ast_channel_unlock(c1);
01884       return -1;
01885    }
01886    if (!srcpr) {
01887       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
01888       ast_channel_unlock(c0);
01889       if (c1)
01890          ast_channel_unlock(c1);
01891       return -1;
01892    }
01893 
01894    /* Get audio, video  and text interface (if native bridge is possible) */
01895    audio_dest_res = destpr->get_rtp_info(c0, &destp);
01896    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
01897    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
01898    if (srcpr) {
01899       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
01900       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
01901       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
01902    }
01903 
01904    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01905    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
01906       /* Somebody doesn't want to play... */
01907       ast_channel_unlock(c0);
01908       if (c1)
01909          ast_channel_unlock(c1);
01910       return -1;
01911    }
01912    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)
01913       srccodec = srcpr->get_codec(c1);
01914    else
01915       srccodec = 0;
01916    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)
01917       destcodec = destpr->get_codec(c0);
01918    else
01919       destcodec = 0;
01920    /* Ensure we have at least one matching codec */
01921    if (srcp && !(srccodec & destcodec)) {
01922       ast_channel_unlock(c0);
01923       ast_channel_unlock(c1);
01924       return 0;
01925    }
01926    /* Consider empty media as non-existent */
01927    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
01928       srcp = NULL;
01929    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01930       nat_active = 1;
01931    /* Bridge media early */
01932    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
01933       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
01934    ast_channel_unlock(c0);
01935    if (c1)
01936       ast_channel_unlock(c1);
01937    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
01938    return 0;
01939 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00674 {
00675    return rtp->s;
00676 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

Definition at line 2436 of file rtp.c.

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

Referenced by __sip_destroy(), and ast_rtp_read().

02437 {
02438    struct ast_rtp *bridged = NULL;
02439 
02440    rtp_bridge_lock(rtp);
02441    bridged = rtp->bridged;
02442    rtp_bridge_unlock(rtp);
02443 
02444    return bridged;
02445 }

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

02079 {
02080    int pt;
02081    
02082    rtp_bridge_lock(rtp);
02083    
02084    *astFormats = *nonAstFormats = 0;
02085    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02086       if (rtp->current_RTP_PT[pt].isAstFormat) {
02087          *astFormats |= rtp->current_RTP_PT[pt].code;
02088       } else {
02089          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02090       }
02091    }
02092 
02093    rtp_bridge_unlock(rtp);
02094 }

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

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

02419 {
02420    if ((them->sin_family != AF_INET) ||
02421       (them->sin_port != rtp->them.sin_port) ||
02422       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02423       them->sin_family = AF_INET;
02424       them->sin_port = rtp->them.sin_port;
02425       them->sin_addr = rtp->them.sin_addr;
02426       return 1;
02427    }
02428    return 0;
02429 }

char* ast_rtp_get_quality ( struct ast_rtp rtp,
struct ast_rtp_quality qual 
)

Return RTCP quality string.

Definition at line 2485 of file rtp.c.

References 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::quality, 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, 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(), handle_request_bye(), and sip_hangup().

02486 {
02487    /*
02488    *ssrc          our ssrc
02489    *themssrc      their ssrc
02490    *lp            lost packets
02491    *rxjitter      our calculated jitter(rx)
02492    *rxcount       no. received packets
02493    *txjitter      reported jitter of the other end
02494    *txcount       transmitted packets
02495    *rlp           remote lost packets
02496    *rtt           round trip time
02497    */
02498 
02499    if (qual && rtp) {
02500       qual->local_ssrc = rtp->ssrc;
02501       qual->local_jitter = rtp->rxjitter;
02502       qual->local_count = rtp->rxcount;
02503       qual->remote_ssrc = rtp->themssrc;
02504       qual->remote_count = rtp->txcount;
02505       if (rtp->rtcp) {
02506          qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02507          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02508          qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02509          qual->rtt = rtp->rtcp->rtt;
02510       }
02511    }
02512    if (rtp->rtcp) {
02513       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02514          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02515          rtp->ssrc,
02516          rtp->themssrc,
02517          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02518          rtp->rxjitter,
02519          rtp->rxcount,
02520          (double)rtp->rtcp->reported_jitter / 65536.0,
02521          rtp->txcount,
02522          rtp->rtcp->reported_lost,
02523          rtp->rtcp->rtt);
02524       return rtp->rtcp->quality;
02525    } else
02526       return "<Unknown> - RTP/RTCP has already been destroyed";
02527 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 728 of file rtp.c.

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

Referenced by check_rtp_timeout().

00729 {
00730    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00731       return 0;
00732    return rtp->rtpholdtimeout;
00733 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 736 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00737 {
00738    return rtp->rtpkeepalive;
00739 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 720 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

00721 {
00722    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00723       return 0;
00724    return rtp->rtptimeout;
00725 }

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

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

02432 {
02433    *us = rtp->us;
02434 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 756 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00757 {
00758    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00759 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4372 of file rtp.c.

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

Referenced by main().

04373 {
04374    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04375    __ast_rtp_reload(0);
04376 }

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

02119 {
02120    int pt = 0;
02121 
02122    rtp_bridge_lock(rtp);
02123 
02124    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02125       code == rtp->rtp_lookup_code_cache_code) {
02126       /* Use our cached mapping, to avoid the overhead of the loop below */
02127       pt = rtp->rtp_lookup_code_cache_result;
02128       rtp_bridge_unlock(rtp);
02129       return pt;
02130    }
02131 
02132    /* Check the dynamic list first */
02133    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02134       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02135          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02136          rtp->rtp_lookup_code_cache_code = code;
02137          rtp->rtp_lookup_code_cache_result = pt;
02138          rtp_bridge_unlock(rtp);
02139          return pt;
02140       }
02141    }
02142 
02143    /* Then the static list */
02144    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02145       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02146          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02147          rtp->rtp_lookup_code_cache_code = code;
02148          rtp->rtp_lookup_code_cache_result = pt;
02149          rtp_bridge_unlock(rtp);
02150          return pt;
02151       }
02152    }
02153 
02154    rtp_bridge_unlock(rtp);
02155 
02156    return -1;
02157 }

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

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

Referenced by process_sdp().

02180 {
02181    int format;
02182    unsigned len;
02183    char *end = buf;
02184    char *start = buf;
02185 
02186    if (!buf || !size)
02187       return NULL;
02188 
02189    snprintf(end, size, "0x%x (", capability);
02190 
02191    len = strlen(end);
02192    end += len;
02193    size -= len;
02194    start = end;
02195 
02196    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02197       if (capability & format) {
02198          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02199 
02200          snprintf(end, size, "%s|", name);
02201          len = strlen(end);
02202          end += len;
02203          size -= len;
02204       }
02205    }
02206 
02207    if (start == end)
02208       ast_copy_string(start, "nothing)", size); 
02209    else if (size > 1)
02210       *(end -1) = ')';
02211    
02212    return buf;
02213 }

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

02161 {
02162    unsigned int i;
02163 
02164    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02165       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02166          if (isAstFormat &&
02167              (code == AST_FORMAT_G726_AAL2) &&
02168              (options & AST_RTP_OPT_G726_NONSTANDARD))
02169             return "G726-32";
02170          else
02171             return mimeTypes[i].subtype;
02172       }
02173    }
02174 
02175    return "";
02176 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

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

02097 {
02098    struct rtpPayloadType result;
02099 
02100    result.isAstFormat = result.code = 0;
02101 
02102    if (pt < 0 || pt > MAX_RTP_PT) 
02103       return result; /* bogus payload type */
02104 
02105    /* Start with negotiated codecs */
02106    rtp_bridge_lock(rtp);
02107    result = rtp->current_RTP_PT[pt];
02108    rtp_bridge_unlock(rtp);
02109 
02110    /* If it doesn't exist, check our static RTP type list, just in case */
02111    if (!result.code) 
02112       result = static_RTP_PT[pt];
02113 
02114    return result;
02115 }

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

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

01942 {
01943    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01944    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01945    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
01946    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01947    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;
01948    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; 
01949    int srccodec, destcodec;
01950 
01951    /* Lock channels */
01952    ast_channel_lock(dest);
01953    while (ast_channel_trylock(src)) {
01954       ast_channel_unlock(dest);
01955       usleep(1);
01956       ast_channel_lock(dest);
01957    }
01958 
01959    /* Find channel driver interfaces */
01960    if (!(destpr = get_proto(dest))) {
01961       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01962       ast_channel_unlock(dest);
01963       ast_channel_unlock(src);
01964       return 0;
01965    }
01966    if (!(srcpr = get_proto(src))) {
01967       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
01968       ast_channel_unlock(dest);
01969       ast_channel_unlock(src);
01970       return 0;
01971    }
01972 
01973    /* Get audio and video interface (if native bridge is possible) */
01974    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01975    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01976    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
01977    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01978    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01979    text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
01980 
01981    /* Ensure we have at least one matching codec */
01982    if (srcpr->get_codec)
01983       srccodec = srcpr->get_codec(src);
01984    else
01985       srccodec = 0;
01986    if (destpr->get_codec)
01987       destcodec = destpr->get_codec(dest);
01988    else
01989       destcodec = 0;
01990 
01991    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01992    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)) {
01993       /* Somebody doesn't want to play... */
01994       ast_channel_unlock(dest);
01995       ast_channel_unlock(src);
01996       return 0;
01997    }
01998    ast_rtp_pt_copy(destp, srcp);
01999    if (vdestp && vsrcp)
02000       ast_rtp_pt_copy(vdestp, vsrcp);
02001    if (tdestp && tsrcp)
02002       ast_rtp_pt_copy(tdestp, tsrcp);
02003    if (media) {
02004       /* Bridge early */
02005       if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02006          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
02007    }
02008    ast_channel_unlock(dest);
02009    ast_channel_unlock(src);
02010    ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
02011    return 1;
02012 }

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02374 {
02375    struct in_addr ia;
02376 
02377    memset(&ia, 0, sizeof(ia));
02378    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02379 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

02265 {
02266 #ifdef P2P_INTENSE
02267    ast_mutex_init(&rtp->bridge_lock);
02268 #endif
02269 
02270    rtp->them.sin_family = AF_INET;
02271    rtp->us.sin_family = AF_INET;
02272    rtp->ssrc = ast_random();
02273    rtp->seqno = ast_random() & 0xffff;
02274    ast_set_flag(rtp, FLAG_HAS_DTMF);
02275    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02276 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

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

02387 {
02388    if (rtp) {
02389       rtp->set_marker_bit = 1;
02390    }
02391    return;
02392 }

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

02279 {
02280    struct ast_rtp *rtp;
02281    int x;
02282    int startplace;
02283    
02284    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
02285       return NULL;
02286 
02287    ast_rtp_new_init(rtp);
02288 
02289    rtp->s = rtp_socket("RTP");
02290    if (rtp->s < 0)
02291       goto fail;
02292    if (sched && rtcpenable) {
02293       rtp->sched = sched;
02294       rtp->rtcp = ast_rtcp_new();
02295    }
02296    
02297    /*
02298     * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
02299     * Start from a random (even, by RTP spec) port number, and
02300     * iterate until success or no ports are available.
02301     * Note that the requirement of RTP port being even, or RTCP being the
02302     * next one, cannot be enforced in presence of a NAT box because the
02303     * mapping is not under our control.
02304     */
02305    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
02306    x = x & ~1;    /* make it an even number */
02307    startplace = x;      /* remember the starting point */
02308    /* this is constant across the loop */
02309    rtp->us.sin_addr = addr;
02310    if (rtp->rtcp)
02311       rtp->rtcp->us.sin_addr = addr;
02312    for (;;) {
02313       rtp->us.sin_port = htons(x);
02314       if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
02315          /* bind succeeded, if no rtcp then we are done */
02316          if (!rtp->rtcp)
02317             break;
02318          /* have rtcp, try to bind it */
02319          rtp->rtcp->us.sin_port = htons(x + 1);
02320          if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
02321             break;   /* success again, we are really done */
02322          /*
02323           * RTCP bind failed, so close and recreate the
02324           * already bound RTP socket for the next round.
02325           */
02326          close(rtp->s);
02327          rtp->s = rtp_socket("RTP");
02328          if (rtp->s < 0)
02329             goto fail;
02330       }
02331       /*
02332        * If we get here, there was an error in one of the bind()
02333        * calls, so make sure it is nothing unexpected.
02334        */
02335       if (errno != EADDRINUSE) {
02336          /* We got an error that wasn't expected, abort! */
02337          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02338          goto fail;
02339       }
02340       /*
02341        * One of the ports is in use. For the next iteration,
02342        * increment by two and handle wraparound.
02343        * If we reach the starting point, then declare failure.
02344        */
02345       x += 2;
02346       if (x > rtpend)
02347          x = (rtpstart + 1) & ~1;
02348       if (x == startplace) {
02349          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02350          goto fail;
02351       }
02352    }
02353    rtp->sched = sched;
02354    rtp->io = io;
02355    if (callbackmode) {
02356       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02357       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02358    }
02359    ast_rtp_pt_default(rtp);
02360    return rtp;
02361 
02362 fail:
02363    if (rtp->s >= 0)
02364       close(rtp->s);
02365    if (rtp->rtcp) {
02366       close(rtp->rtcp->s);
02367       ast_free(rtp->rtcp);
02368    }
02369    ast_free(rtp);
02370    return NULL;
02371 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

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

03332 {
03333    struct ast_rtp_protocol *cur;
03334 
03335    AST_RWLIST_WRLOCK(&protos);
03336    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03337       if (!strcmp(cur->type, proto->type)) {
03338          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03339          AST_RWLIST_UNLOCK(&protos);
03340          return -1;
03341       }
03342    }
03343    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03344    AST_RWLIST_UNLOCK(&protos);
03345    
03346    return 0;
03347 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3323 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03324 {
03325    AST_RWLIST_WRLOCK(&protos);
03326    AST_RWLIST_REMOVE(&protos, proto, list);
03327    AST_RWLIST_UNLOCK(&protos);
03328 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

01780 {
01781    int i;
01782 
01783    if (!rtp)
01784       return;
01785 
01786    rtp_bridge_lock(rtp);
01787 
01788    for (i = 0; i < MAX_RTP_PT; ++i) {
01789       rtp->current_RTP_PT[i].isAstFormat = 0;
01790       rtp->current_RTP_PT[i].code = 0;
01791    }
01792 
01793    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01794    rtp->rtp_lookup_code_cache_code = 0;
01795    rtp->rtp_lookup_code_cache_result = 0;
01796 
01797    rtp_bridge_unlock(rtp);
01798 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01820 {
01821    unsigned int i;
01822 
01823    rtp_bridge_lock(dest);
01824    rtp_bridge_lock(src);
01825 
01826    for (i = 0; i < MAX_RTP_PT; ++i) {
01827       dest->current_RTP_PT[i].isAstFormat = 
01828          src->current_RTP_PT[i].isAstFormat;
01829       dest->current_RTP_PT[i].code = 
01830          src->current_RTP_PT[i].code; 
01831    }
01832    dest->rtp_lookup_code_cache_isAstFormat = 0;
01833    dest->rtp_lookup_code_cache_code = 0;
01834    dest->rtp_lookup_code_cache_result = 0;
01835 
01836    rtp_bridge_unlock(src);
01837    rtp_bridge_unlock(dest);
01838 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

01801 {
01802    int i;
01803 
01804    rtp_bridge_lock(rtp);
01805 
01806    /* Initialize to default payload types */
01807    for (i = 0; i < MAX_RTP_PT; ++i) {
01808       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01809       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01810    }
01811 
01812    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01813    rtp->rtp_lookup_code_cache_code = 0;
01814    rtp->rtp_lookup_code_cache_result = 0;
01815 
01816    rtp_bridge_unlock(rtp);
01817 }

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

03063 {
03064    unsigned char *rtpheader;
03065    int hdrlen = 12;
03066    int res;
03067    unsigned int ms;
03068    int pred;
03069    int mark = 0;
03070 
03071    if (rtp->sending_digit) {
03072       return 0;
03073    }
03074 
03075    ms = calc_txstamp(rtp, &f->delivery);
03076    /* Default prediction */
03077    if (f->frametype == AST_FRAME_VOICE) {
03078       pred = rtp->lastts + f->samples;
03079 
03080       /* Re-calculate last TS */
03081       rtp->lastts = rtp->lastts + ms * 8;
03082       if (ast_tvzero(f->delivery)) {
03083          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
03084             and if so, go with our prediction */
03085          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
03086             rtp->lastts = pred;
03087          else {
03088             ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
03089             mark = 1;
03090          }
03091       }
03092    } else if (f->frametype == AST_FRAME_VIDEO) {
03093       mark = f->subclass & 0x1;
03094       pred = rtp->lastovidtimestamp + f->samples;
03095       /* Re-calculate last TS */
03096       rtp->lastts = rtp->lastts + ms * 90;
03097       /* If it's close to our prediction, go for it */
03098       if (ast_tvzero(f->delivery)) {
03099          if (abs(rtp->lastts - pred) < 7200) {
03100             rtp->lastts = pred;
03101             rtp->lastovidtimestamp += f->samples;
03102          } else {
03103             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);
03104             rtp->lastovidtimestamp = rtp->lastts;
03105          }
03106       }
03107    } else {
03108       pred = rtp->lastotexttimestamp + f->samples;
03109       /* Re-calculate last TS */
03110       rtp->lastts = rtp->lastts + ms;
03111       /* If it's close to our prediction, go for it */
03112       if (ast_tvzero(f->delivery)) {
03113          if (abs(rtp->lastts - pred) < 7200) {
03114             rtp->lastts = pred;
03115             rtp->lastotexttimestamp += f->samples;
03116          } else {
03117             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);
03118             rtp->lastotexttimestamp = rtp->lastts;
03119          }
03120       }
03121    }
03122 
03123    /* If we have been explicitly told to set the marker bit do so */
03124    if (rtp->set_marker_bit) {
03125       mark = 1;
03126       rtp->set_marker_bit = 0;
03127    }
03128 
03129    /* If the timestamp for non-digit packets has moved beyond the timestamp
03130       for digits, update the digit timestamp.
03131    */
03132    if (rtp->lastts > rtp->lastdigitts)
03133       rtp->lastdigitts = rtp->lastts;
03134 
03135    if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
03136       rtp->lastts = f->ts * 8;
03137 
03138    /* Get a pointer to the header */
03139    rtpheader = (unsigned char *)(f->data - hdrlen);
03140 
03141    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
03142    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
03143    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
03144 
03145    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03146       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03147       if (res < 0) {
03148          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
03149             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));
03150          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
03151             /* Only give this error message once if we are not RTP debugging */
03152             if (option_debug || rtpdebug)
03153                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));
03154             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
03155          }
03156       } else {
03157          rtp->txcount++;
03158          rtp->txoctetcount +=(res - hdrlen);
03159          
03160          /* Do not schedule RR if RTCP isn't run */
03161          if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
03162             rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
03163          }
03164       }
03165             
03166       if (rtp_debug_test_addr(&rtp->them))
03167          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03168                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
03169    }
03170 
03171    rtp->seqno++;
03172 
03173    return 0;
03174 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1420 of file rtp.c.

References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_samp2tv(), ast_sched_add(), ast_set_flag, ast_tv(), ast_tvdiff_ms(), ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, 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_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_frame::src, ast_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_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().

01421 {
01422    int res;
01423    struct sockaddr_in sin;
01424    socklen_t len;
01425    unsigned int seqno;
01426    int version;
01427    int payloadtype;
01428    int hdrlen = 12;
01429    int padding;
01430    int mark;
01431    int ext;
01432    int cc;
01433    unsigned int ssrc;
01434    unsigned int timestamp;
01435    unsigned int *rtpheader;
01436    struct rtpPayloadType rtpPT;
01437    struct ast_rtp *bridged = NULL;
01438    
01439    /* If time is up, kill it */
01440    if (rtp->sending_digit)
01441       ast_rtp_senddigit_continuation(rtp);
01442 
01443    len = sizeof(sin);
01444    
01445    /* Cache where the header will go */
01446    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
01447                0, (struct sockaddr *)&sin, &len);
01448 
01449    /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */
01450    if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
01451       /* Copy over address that this packet was received on */
01452       memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address));
01453       /* Now move over to actually protecting the RTP port */
01454       rtp->strict_rtp_state = STRICT_RTP_CLOSED;
01455       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));
01456    } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
01457       /* If the address we previously learned doesn't match the address this packet came in on simply drop it */
01458       if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
01459          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(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01460          return &ast_null_frame;
01461       }
01462    }
01463 
01464    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
01465    if (res < 0) {
01466       ast_assert(errno != EBADF);
01467       if (errno != EAGAIN) {
01468          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up.\n", strerror(errno));
01469          return NULL;
01470       }
01471       return &ast_null_frame;
01472    }
01473    
01474    if (res < hdrlen) {
01475       ast_log(LOG_WARNING, "RTP Read too short\n");
01476       return &ast_null_frame;
01477    }
01478 
01479    /* Get fields */
01480    seqno = ntohl(rtpheader[0]);
01481 
01482    /* Check RTP version */
01483    version = (seqno & 0xC0000000) >> 30;
01484    if (!version) {
01485       /* If the two high bits are 0, this might be a
01486        * STUN message, so process it. stun_handle_packet()
01487        * answers to requests, and it returns STUN_ACCEPT
01488        * if the request is valid.
01489        */
01490       if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) &&
01491          (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
01492          memcpy(&rtp->them, &sin, sizeof(rtp->them));
01493       }
01494       return &ast_null_frame;
01495    }
01496 
01497 #if 0 /* Allow to receive RTP stream with closed transmission path */
01498    /* If we don't have the other side's address, then ignore this */
01499    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
01500       return &ast_null_frame;
01501 #endif
01502 
01503    /* Send to whoever send to us if NAT is turned on */
01504    if (rtp->nat) {
01505       if (((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01506           (rtp->them.sin_port != sin.sin_port)) && 
01507           ((rtp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01508           (rtp->altthem.sin_port != sin.sin_port))) {
01509          rtp->them = sin;
01510          if (rtp->rtcp) {
01511             memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01512             rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1);
01513          }
01514          rtp->rxseqno = 0;
01515          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01516          if (option_debug || rtpdebug)
01517             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));
01518       }
01519    }
01520 
01521    /* If we are bridged to another RTP stream, send direct */
01522    if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
01523       return &ast_null_frame;
01524 
01525    if (version != 2)
01526       return &ast_null_frame;
01527 
01528    payloadtype = (seqno & 0x7f0000) >> 16;
01529    padding = seqno & (1 << 29);
01530    mark = seqno & (1 << 23);
01531    ext = seqno & (1 << 28);
01532    cc = (seqno & 0xF000000) >> 24;
01533    seqno &= 0xffff;
01534    timestamp = ntohl(rtpheader[1]);
01535    ssrc = ntohl(rtpheader[2]);
01536    
01537    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
01538       if (option_debug || rtpdebug)
01539          ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
01540       mark = 1;
01541    }
01542 
01543    rtp->rxssrc = ssrc;
01544    
01545    if (padding) {
01546       /* Remove padding bytes */
01547       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01548    }
01549    
01550    if (cc) {
01551       /* CSRC fields present */
01552       hdrlen += cc*4;
01553    }
01554 
01555    if (ext) {
01556       /* RTP Extension present */
01557       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
01558       hdrlen += 4;
01559       if (option_debug) {
01560          int profile;
01561          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
01562          if (profile == 0x505a)
01563             ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
01564          else
01565             ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
01566       }
01567    }
01568 
01569    if (res < hdrlen) {
01570       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
01571       return &ast_null_frame;
01572    }
01573 
01574    rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
01575 
01576    if (rtp->rxcount==1) {
01577       /* This is the first RTP packet successfully received from source */
01578       rtp->seedrxseqno = seqno;
01579    }
01580 
01581    /* Do not schedule RR if RTCP isn't run */
01582    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
01583       /* Schedule transmission of Receiver Report */
01584       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01585    }
01586    if ( (int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
01587       rtp->cycles += RTP_SEQ_MOD;
01588 
01589    rtp->lastrxseqno = seqno;
01590    
01591    if (!rtp->themssrc)
01592       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
01593    
01594    if (rtp_debug_test_addr(&sin))
01595       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01596          ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
01597 
01598    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
01599    if (!rtpPT.isAstFormat) {
01600       struct ast_frame *f = NULL;
01601 
01602       /* This is special in-band data that's not one of our codecs */
01603       if (rtpPT.code == AST_RTP_DTMF) {
01604          /* It's special -- rfc2833 process it */
01605          if (rtp_debug_test_addr(&sin)) {
01606             unsigned char *data;
01607             unsigned int event;
01608             unsigned int event_end;
01609             unsigned int duration;
01610             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
01611             event = ntohl(*((unsigned int *)(data)));
01612             event >>= 24;
01613             event_end = ntohl(*((unsigned int *)(data)));
01614             event_end <<= 8;
01615             event_end >>= 24;
01616             duration = ntohl(*((unsigned int *)(data)));
01617             duration &= 0xFFFF;
01618             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(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
01619          }
01620          f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
01621       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
01622          /* It's really special -- process it the Cisco way */
01623          if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
01624             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01625             rtp->lastevent = seqno;
01626          }
01627       } else if (rtpPT.code == AST_RTP_CN) {
01628          /* Comfort Noise */
01629          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01630       } else {
01631          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
01632       }
01633       return f ? f : &ast_null_frame;
01634    }
01635    rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
01636    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;
01637 
01638    rtp->rxseqno = seqno;
01639 
01640    if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
01641       rtp->dtmf_timeout = 0;
01642 
01643       if (rtp->resp) {
01644          struct ast_frame *f;
01645          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01646          f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
01647          rtp->resp = 0;
01648          rtp->dtmf_timeout = rtp->dtmf_duration = 0;
01649          return f;
01650       }
01651    }
01652 
01653    /* Record received timestamp as last received now */
01654    rtp->lastrxts = timestamp;
01655 
01656    rtp->f.mallocd = 0;
01657    rtp->f.datalen = res - hdrlen;
01658    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
01659    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
01660    rtp->f.seqno = seqno;
01661    if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
01662       rtp->f.samples = ast_codec_get_samples(&rtp->f);
01663       if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
01664          ast_frame_byteswap_be(&rtp->f);
01665       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
01666       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
01667       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
01668       rtp->f.ts = timestamp / 8;
01669       rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 );
01670    } else if(rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
01671       /* Video -- samples is # of samples vs. 90000 */
01672       if (!rtp->lastividtimestamp)
01673          rtp->lastividtimestamp = timestamp;
01674       rtp->f.samples = timestamp - rtp->lastividtimestamp;
01675       rtp->lastividtimestamp = timestamp;
01676       rtp->f.delivery.tv_sec = 0;
01677       rtp->f.delivery.tv_usec = 0;
01678       /* Pass the RTP marker bit as bit 0 in the subclass field.
01679        * This is ok because subclass is actually a bitmask, and
01680        * the low bits represent audio formats, that are not
01681        * involved here since we deal with video.
01682        */
01683       if (mark)
01684          rtp->f.subclass |= 0x1;
01685    } else {
01686       /* TEXT -- samples is # of samples vs. 1000 */
01687       if (!rtp->lastitexttimestamp)
01688          rtp->lastitexttimestamp = timestamp;
01689       rtp->f.samples = timestamp - rtp->lastitexttimestamp;
01690       rtp->lastitexttimestamp = timestamp;
01691       rtp->f.delivery.tv_sec = 0;
01692       rtp->f.delivery.tv_usec = 0;
01693    }
01694    rtp->f.src = "RTP";
01695    return &rtp->f;
01696 }

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4366 of file rtp.c.

References __ast_rtp_reload().

04367 {
04368    return __ast_rtp_reload(1);
04369 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2463 of file rtp.c.

References ast_rtp::dtmf_timeout, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.

02464 {
02465    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02466    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02467    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02468    rtp->lastts = 0;
02469    rtp->lastdigitts = 0;
02470    rtp->lastrxts = 0;
02471    rtp->lastividtimestamp = 0;
02472    rtp->lastovidtimestamp = 0;
02473    rtp->lastitexttimestamp = 0;
02474    rtp->lastotexttimestamp = 0;
02475    rtp->lasteventseqn = 0;
02476    rtp->lastevent = 0;
02477    rtp->lasttxformat = 0;
02478    rtp->lastrxformat = 0;
02479    rtp->dtmf_timeout = 0;
02480    rtp->dtmfsamples = 0;
02481    rtp->seqno = 0;
02482    rtp->rxseqno = 0;
02483 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

03028 {
03029    unsigned int *rtpheader;
03030    int hdrlen = 12;
03031    int res;
03032    int payload;
03033    char data[256];
03034    level = 127 - (level & 0x7f);
03035    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03036 
03037    /* If we have no peer, return immediately */ 
03038    if (!rtp->them.sin_addr.s_addr)
03039       return 0;
03040 
03041    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03042 
03043    /* Get a pointer to the header */
03044    rtpheader = (unsigned int *)data;
03045    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03046    rtpheader[1] = htonl(rtp->lastts);
03047    rtpheader[2] = htonl(rtp->ssrc); 
03048    data[12] = level;
03049    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03050       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03051       if (res <0) 
03052          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));
03053       if (rtp_debug_test_addr(&rtp->them))
03054          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03055                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03056          
03057    }
03058    return 0;
03059 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

02613 {
02614    unsigned int *rtpheader;
02615    int hdrlen = 12, res = 0, i = 0, payload = 0;
02616    char data[256];
02617 
02618    if ((digit <= '9') && (digit >= '0'))
02619       digit -= '0';
02620    else if (digit == '*')
02621       digit = 10;
02622    else if (digit == '#')
02623       digit = 11;
02624    else if ((digit >= 'A') && (digit <= 'D'))
02625       digit = digit - 'A' + 12;
02626    else if ((digit >= 'a') && (digit <= 'd'))
02627       digit = digit - 'a' + 12;
02628    else {
02629       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02630       return 0;
02631    }
02632 
02633    /* If we have no peer, return immediately */ 
02634    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02635       return 0;
02636 
02637    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02638 
02639    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02640    rtp->send_duration = 160;
02641    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
02642    
02643    /* Get a pointer to the header */
02644    rtpheader = (unsigned int *)data;
02645    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02646    rtpheader[1] = htonl(rtp->lastdigitts);
02647    rtpheader[2] = htonl(rtp->ssrc); 
02648 
02649    for (i = 0; i < 2; i++) {
02650       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02651       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02652       if (res < 0) 
02653          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02654             ast_inet_ntoa(rtp->them.sin_addr),
02655             ntohs(rtp->them.sin_port), strerror(errno));
02656       if (rtp_debug_test_addr(&rtp->them))
02657          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02658                 ast_inet_ntoa(rtp->them.sin_addr),
02659                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02660       /* Increment sequence number */
02661       rtp->seqno++;
02662       /* Increment duration */
02663       rtp->send_duration += 160;
02664       /* Clear marker bit and set seqno */
02665       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02666    }
02667 
02668    /* Since we received a begin, we can safely store the digit and disable any compensation */
02669    rtp->sending_digit = 1;
02670    rtp->send_digit = digit;
02671    rtp->send_payload = payload;
02672 
02673    return 0;
02674 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

02678 {
02679    unsigned int *rtpheader;
02680    int hdrlen = 12, res = 0;
02681    char data[256];
02682 
02683    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02684       return 0;
02685 
02686    /* Setup packet to send */
02687    rtpheader = (unsigned int *)data;
02688    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02689    rtpheader[1] = htonl(rtp->lastdigitts);
02690    rtpheader[2] = htonl(rtp->ssrc);
02691    rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
02692    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02693    
02694    /* Transmit */
02695    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02696    if (res < 0)
02697       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02698          ast_inet_ntoa(rtp->them.sin_addr),
02699          ntohs(rtp->them.sin_port), strerror(errno));
02700    if (rtp_debug_test_addr(&rtp->them))
02701       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02702              ast_inet_ntoa(rtp->them.sin_addr),
02703              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02704 
02705    /* Increment sequence number */
02706    rtp->seqno++;
02707    /* Increment duration */
02708    rtp->send_duration += 160;
02709 
02710    return 0;
02711 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

02715 {
02716    unsigned int *rtpheader;
02717    int hdrlen = 12, res = 0, i = 0;
02718    char data[256];
02719    
02720    /* If no address, then bail out */
02721    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02722       return 0;
02723    
02724    if ((digit <= '9') && (digit >= '0'))
02725       digit -= '0';
02726    else if (digit == '*')
02727       digit = 10;
02728    else if (digit == '#')
02729       digit = 11;
02730    else if ((digit >= 'A') && (digit <= 'D'))
02731       digit = digit - 'A' + 12;
02732    else if ((digit >= 'a') && (digit <= 'd'))
02733       digit = digit - 'a' + 12;
02734    else {
02735       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02736       return 0;
02737    }
02738 
02739    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02740 
02741    rtpheader = (unsigned int *)data;
02742    rtpheader[1] = htonl(rtp->lastdigitts);
02743    rtpheader[2] = htonl(rtp->ssrc);
02744    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02745    /* Set end bit */
02746    rtpheader[3] |= htonl((1 << 23));
02747 
02748    /* Send 3 termination packets */
02749    for (i = 0; i < 3; i++) {
02750       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02751       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02752       rtp->seqno++;
02753       if (res < 0)
02754          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02755             ast_inet_ntoa(rtp->them.sin_addr),
02756             ntohs(rtp->them.sin_port), strerror(errno));
02757       if (rtp_debug_test_addr(&rtp->them))
02758          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02759                 ast_inet_ntoa(rtp->them.sin_addr),
02760                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02761    }
02762    rtp->lastts += rtp->send_duration;
02763    rtp->sending_digit = 0;
02764    rtp->send_digit = 0;
02765 
02766    return res;
02767 }

void ast_rtp_set_alt_peer ( struct ast_rtp rtp,
struct sockaddr_in *  alt 
)

set potential alternate source for RTP media

Since:
1.4.26
This function may be used to give the RTP stack a hint that there is a potential second source of media. One case where this is used is when the SIP stack receives a REINVITE to which it will be replying with a 491. In such a scenario, the IP and port information in the SDP of that REINVITE lets us know that we may receive media from that source/those sources even though the SIP transaction was unable to be completed successfully

Parameters:
rtp The RTP structure we wish to set up an alternate host/port on
alt The address information for the alternate media source
Return values:
void 

Definition at line 2408 of file rtp.c.

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

Referenced by handle_request_invite().

02409 {
02410    rtp->altthem.sin_port = alt->sin_port;
02411    rtp->altthem.sin_addr = alt->sin_addr;
02412    if (rtp->rtcp) {
02413       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02414       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02415    }
02416 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 746 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00747 {
00748    rtp->callback = callback;
00749 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 741 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00742 {
00743    rtp->data = data;
00744 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

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

02019 {
02020    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02021       return; /* bogus payload type */
02022 
02023    rtp_bridge_lock(rtp);
02024    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02025    rtp_bridge_unlock(rtp);
02026 } 

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

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

02395 {
02396    rtp->them.sin_port = them->sin_port;
02397    rtp->them.sin_addr = them->sin_addr;
02398    if (rtp->rtcp) {
02399       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02400       rtp->rtcp->them.sin_addr = them->sin_addr;
02401    }
02402    rtp->rxseqno = 0;
02403    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02404    if (strictrtp)
02405       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02406 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 708 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00709 {
00710    rtp->rtpholdtimeout = timeout;
00711 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 714 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00715 {
00716    rtp->rtpkeepalive = period;
00717 }

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

02048 {
02049    unsigned int i;
02050    int found = 0;
02051 
02052    if (pt < 0 || pt > MAX_RTP_PT) 
02053       return -1; /* bogus payload type */
02054    
02055    rtp_bridge_lock(rtp);
02056 
02057    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02058       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02059           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02060          found = 1;
02061          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02062          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02063              mimeTypes[i].payloadType.isAstFormat &&
02064              (options & AST_RTP_OPT_G726_NONSTANDARD))
02065             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02066          break;
02067       }
02068    }
02069 
02070    rtp_bridge_unlock(rtp);
02071 
02072    return (found ? 0 : -1);
02073 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 702 of file rtp.c.

References ast_rtp::rtptimeout.

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

00703 {
00704    rtp->rtptimeout = timeout;
00705 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 695 of file rtp.c.

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

Referenced by handle_response_invite().

00696 {
00697    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00698    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00699 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00762 {
00763    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00764 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00767 {
00768    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00769 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 751 of file rtp.c.

References ast_rtp::nat.

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

00752 {
00753    rtp->nat = nat;
00754 }

int ast_rtp_setqos ( struct ast_rtp rtp,
int  tos,
int  cos,
char *  desc 
)

Definition at line 2381 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

02382 {
02383    return ast_netsock_set_qos(rtp->s, tos, cos, desc);
02384 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 771 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00772 {
00773    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00774 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

Definition at line 2447 of file rtp.c.

References ast_clear_flag, AST_SCHED_DEL, FLAG_P2P_SENT_MARK, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::them, and ast_rtcp::them.

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

02448 {
02449    if (rtp->rtcp) {
02450       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02451    }
02452 
02453    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02454    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02455    if (rtp->rtcp) {
02456       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02457       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02458    }
02459    
02460    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02461 }

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

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00656 {
00657    ast_stun_request(rtp->s, suggestion, username, NULL);
00658 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

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

02031 {
02032    if (pt < 0 || pt > MAX_RTP_PT)
02033       return; /* bogus payload type */
02034 
02035    rtp_bridge_lock(rtp);
02036    rtp->current_RTP_PT[pt].isAstFormat = 0;
02037    rtp->current_RTP_PT[pt].code = 0;
02038    rtp_bridge_unlock(rtp);
02039 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 3238 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::smoother, ast_frame::subclass, and ast_rtp::them.

Referenced by gtalk_write(), jingle_write(), mgcp_write(), oh323_write(), sip_write(), skinny_write(), and unistim_write().

03239 {
03240    struct ast_frame *f;
03241    int codec;
03242    int hdrlen = 12;
03243    int subclass;
03244    
03245 
03246    /* If we have no peer, return immediately */ 
03247    if (!rtp->them.sin_addr.s_addr)
03248       return 0;
03249 
03250    /* If there is no data length, return immediately */
03251    if (!_f->datalen) 
03252       return 0;
03253    
03254    /* Make sure we have enough space for RTP header */
03255    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
03256       ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
03257       return -1;
03258    }
03259 
03260    /* The bottom bit of a video subclass contains the marker bit */
03261    subclass = _f->subclass;
03262    if (_f->frametype == AST_FRAME_VIDEO)
03263       subclass &= ~0x1;
03264 
03265    codec = ast_rtp_lookup_code(rtp, 1, subclass);
03266    if (codec < 0) {
03267       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
03268       return -1;
03269    }
03270 
03271    if (rtp->lasttxformat != subclass) {
03272       /* New format, reset the smoother */
03273       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
03274       rtp->lasttxformat = subclass;
03275       if (rtp->smoother)
03276          ast_smoother_free(rtp->smoother);
03277       rtp->smoother = NULL;
03278    }
03279 
03280    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
03281       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
03282       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
03283          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
03284             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));
03285             return -1;
03286          }
03287          if (fmt.flags)
03288             ast_smoother_set_flags(rtp->smoother, fmt.flags);
03289          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));
03290       }
03291    }
03292    if (rtp->smoother) {
03293       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03294          ast_smoother_feed_be(rtp->smoother, _f);
03295       } else {
03296          ast_smoother_feed(rtp->smoother, _f);
03297       }
03298 
03299       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
03300          if (f->subclass == AST_FORMAT_G722) {
03301             /* G.722 is silllllllllllllly */
03302             f->samples /= 2;
03303          }
03304 
03305          ast_rtp_raw_write(rtp, f, codec);
03306       }
03307    } else {
03308       /* Don't buffer outgoing frames; send them one-per-packet: */
03309       if (_f->offset < hdrlen) 
03310          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
03311       else
03312          f = _f;
03313       if (f->data)
03314          ast_rtp_raw_write(rtp, f, codec);
03315       if (f != _f)
03316          ast_frfree(f);
03317    }
03318       
03319    return 0;
03320 }

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

00591 {
00592    struct stun_header *req;
00593    unsigned char reqdata[1024];
00594    int reqlen, reqleft;
00595    struct stun_attr *attr;
00596    int res = 0;
00597    int retry;
00598    
00599    req = (struct stun_header *)reqdata;
00600    stun_req_id(req);
00601    reqlen = 0;
00602    reqleft = sizeof(reqdata) - sizeof(struct stun_header);
00603    req->msgtype = 0;
00604    req->msglen = 0;
00605    attr = (struct stun_attr *)req->ies;
00606    if (username)
00607       append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00608    req->msglen = htons(reqlen);
00609    req->msgtype = htons(STUN_BINDREQ);
00610    for (retry = 0; retry < 3; retry++) {  /* XXX make retries configurable */
00611       /* send request, possibly wait for reply */
00612       unsigned char reply_buf[1024];
00613       fd_set rfds;
00614       struct timeval to = { 3, 0 }; /* timeout, make it configurable */
00615       struct sockaddr_in src;
00616       socklen_t srclen;
00617 
00618       res = stun_send(s, dst, req);
00619       if (res < 0) {
00620          ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
00621             retry, res);
00622          continue;
00623       }
00624       if (answer == NULL)
00625          break;
00626       FD_ZERO(&rfds);
00627       FD_SET(s, &rfds);
00628       res = ast_select(s + 1, &rfds, NULL, NULL, &to);
00629       if (res <= 0)  /* timeout or error */
00630          continue;
00631       memset(&src, '\0', sizeof(src));
00632       srclen = sizeof(src);
00633       /* XXX pass -1 in the size, because stun_handle_packet might
00634        * write past the end of the buffer.
00635        */
00636       res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
00637          0, (struct sockaddr *)&src, &srclen);
00638       if (res < 0) {
00639          ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
00640             retry, res);
00641          continue;
00642       }
00643       memset(answer, '\0', sizeof(struct sockaddr_in));
00644       stun_handle_packet(s, &src, reply_buf, res,
00645          stun_get_mapped, answer);
00646       res = 0; /* signal regular exit */
00647       break;
00648    }
00649    return res;
00650 }

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 3350 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_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

03351 {
03352    struct ast_frame *fr = NULL;
03353    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03354    int oldcodec0 = codec0, oldcodec1 = codec1;
03355    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
03356    struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
03357    
03358    /* Set it up so audio goes directly between the two endpoints */
03359 
03360    /* Test the first channel */
03361    if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
03362       ast_rtp_get_peer(p1, &ac1);
03363       if (vp1)
03364          ast_rtp_get_peer(vp1, &vac1);
03365       if (tp1)
03366          ast_rtp_get_peer(tp1, &tac1);
03367    } else
03368       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
03369    
03370    /* Test the second channel */
03371    if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
03372       ast_rtp_get_peer(p0, &ac0);
03373       if (vp0)
03374          ast_rtp_get_peer(vp0, &vac0);
03375       if (tp0)
03376          ast_rtp_get_peer(tp0, &tac0);
03377    } else
03378       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
03379 
03380    /* Now we can unlock and move into our loop */
03381    ast_channel_unlock(c0);
03382    ast_channel_unlock(c1);
03383 
03384    ast_poll_channel_add(c0, c1);
03385 
03386    /* Throw our channels into the structure and enter the loop */
03387    cs[0] = c0;
03388    cs[1] = c1;
03389    cs[2] = NULL;
03390    for (;;) {
03391       /* Check if anything changed */
03392       if ((c0->tech_pvt != pvt0) ||
03393           (c1->tech_pvt != pvt1) ||
03394           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03395           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03396          ast_debug(1, "Oooh, something is weird, backing out\n");
03397          if (c0->tech_pvt == pvt0)
03398             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
03399                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03400          if (c1->tech_pvt == pvt1)
03401             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
03402                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03403          ast_poll_channel_del(c0, c1);
03404          return AST_BRIDGE_RETRY;
03405       }
03406 
03407       /* Check if they have changed their address */
03408       ast_rtp_get_peer(p1, &t1);
03409       if (vp1)
03410          ast_rtp_get_peer(vp1, &vt1);
03411       if (tp1)
03412          ast_rtp_get_peer(tp1, &tt1);
03413       if (pr1->get_codec)
03414          codec1 = pr1->get_codec(c1);
03415       ast_rtp_get_peer(p0, &t0);
03416       if (vp0)
03417          ast_rtp_get_peer(vp0, &vt0);
03418       if (tp0)
03419          ast_rtp_get_peer(tp0, &tt0);
03420       if (pr0->get_codec)
03421          codec0 = pr0->get_codec(c0);
03422       if ((inaddrcmp(&t1, &ac1)) ||
03423           (vp1 && inaddrcmp(&vt1, &vac1)) ||
03424           (tp1 && inaddrcmp(&tt1, &tac1)) ||
03425           (codec1 != oldcodec1)) {
03426          ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03427             c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
03428          ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
03429             c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
03430          ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n",
03431             c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1);
03432          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03433             c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
03434          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03435             c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
03436          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03437             c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1);
03438          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)))
03439             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
03440          memcpy(&ac1, &t1, sizeof(ac1));
03441          memcpy(&vac1, &vt1, sizeof(vac1));
03442          memcpy(&tac1, &tt1, sizeof(tac1));
03443          oldcodec1 = codec1;
03444       }
03445       if ((inaddrcmp(&t0, &ac0)) ||
03446           (vp0 && inaddrcmp(&vt0, &vac0)) ||
03447           (tp0 && inaddrcmp(&tt0, &tac0)) ||
03448           (codec0 != oldcodec0)) {
03449          ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
03450             c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
03451          ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
03452             c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
03453          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)))
03454             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
03455          memcpy(&ac0, &t0, sizeof(ac0));
03456          memcpy(&vac0, &vt0, sizeof(vac0));
03457          memcpy(&tac0, &tt0, sizeof(tac0));
03458          oldcodec0 = codec0;
03459       }
03460 
03461       /* Wait for frame to come in on the channels */
03462       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03463          if (!timeoutms) {
03464             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
03465                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03466             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
03467                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03468             return AST_BRIDGE_RETRY;
03469          }
03470          ast_debug(1, "Ooh, empty read...\n");
03471          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03472             break;
03473          continue;
03474       }
03475       fr = ast_read(who);
03476       other = (who == c0) ? c1 : c0;
03477       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03478              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
03479               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
03480          /* Break out of bridge */
03481          *fo = fr;
03482          *rc = who;
03483          ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03484          if (c0->tech_pvt == pvt0)
03485             if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
03486                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03487          if (c1->tech_pvt == pvt1)
03488             if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
03489                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03490          ast_poll_channel_del(c0, c1);
03491          return AST_BRIDGE_COMPLETE;
03492       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03493          if ((fr->subclass == AST_CONTROL_HOLD) ||
03494              (fr->subclass == AST_CONTROL_UNHOLD) ||
03495              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03496              (fr->subclass == AST_CONTROL_T38) ||
03497              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03498             if (fr->subclass == AST_CONTROL_HOLD) {
03499                /* If we someone went on hold we want the other side to reinvite back to us */
03500                if (who == c0)
03501                   pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0);
03502                else
03503                   pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0);
03504             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03505                /* If they went off hold they should go back to being direct */
03506                if (who == c0)
03507                   pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
03508                else
03509                   pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
03510             }
03511             /* Update local address information */
03512             ast_rtp_get_peer(p0, &t0);
03513             memcpy(&ac0, &t0, sizeof(ac0));
03514             ast_rtp_get_peer(p1, &t1);
03515             memcpy(&ac1, &t1, sizeof(ac1));
03516             /* Update codec information */
03517             if (pr0->get_codec && c0->tech_pvt)
03518                oldcodec0 = codec0 = pr0->get_codec(c0);
03519             if (pr1->get_codec && c1->tech_pvt)
03520                oldcodec1 = codec1 = pr1->get_codec(c1);
03521             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03522             ast_frfree(fr);
03523          } else {
03524             *fo = fr;
03525             *rc = who;
03526             ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03527             return AST_BRIDGE_COMPLETE;
03528          }
03529       } else {
03530          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03531              (fr->frametype == AST_FRAME_DTMF_END) ||
03532              (fr->frametype == AST_FRAME_VOICE) ||
03533              (fr->frametype == AST_FRAME_VIDEO) ||
03534              (fr->frametype == AST_FRAME_IMAGE) ||
03535              (fr->frametype == AST_FRAME_HTML) ||
03536              (fr->frametype == AST_FRAME_MODEM) ||
03537              (fr->frametype == AST_FRAME_TEXT)) {
03538             ast_write(other, fr);
03539          }
03540          ast_frfree(fr);
03541       }
03542       /* Swap priority */
03543 #ifndef HAVE_EPOLL
03544       cs[2] = cs[0];
03545       cs[0] = cs[1];
03546       cs[1] = cs[2];
03547 #endif
03548    }
03549 
03550    ast_poll_channel_del(c0, c1);
03551 
03552    if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
03553       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03554    if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
03555       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03556 
03557    return AST_BRIDGE_FAILED;
03558 }

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

03659 {
03660    struct ast_frame *fr = NULL;
03661    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03662    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03663    int p0_callback = 0, p1_callback = 0;
03664    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03665 
03666    /* Okay, setup each RTP structure to do P2P forwarding */
03667    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03668    p2p_set_bridge(p0, p1);
03669    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03670    p2p_set_bridge(p1, p0);
03671 
03672    /* Activate callback modes if possible */
03673    p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
03674    p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
03675 
03676    /* Now let go of the channel locks and be on our way */
03677    ast_channel_unlock(c0);
03678    ast_channel_unlock(c1);
03679 
03680    ast_poll_channel_add(c0, c1);
03681 
03682    /* Go into a loop forwarding frames until we don't need to anymore */
03683    cs[0] = c0;
03684    cs[1] = c1;
03685    cs[2] = NULL;
03686    for (;;) {
03687       /* If the underlying formats have changed force this bridge to break */
03688       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
03689          ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n");
03690          res = AST_BRIDGE_FAILED_NOWARN;
03691          break;
03692       }
03693       /* Check if anything changed */
03694       if ((c0->tech_pvt != pvt0) ||
03695           (c1->tech_pvt != pvt1) ||
03696           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03697           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03698          ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n");
03699          /* 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 */
03700          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03701             ast_frfree(fr);
03702          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03703             ast_frfree(fr);
03704          res = AST_BRIDGE_RETRY;
03705          break;
03706       }
03707       /* Wait on a channel to feed us a frame */
03708       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03709          if (!timeoutms) {
03710             res = AST_BRIDGE_RETRY;
03711             break;
03712          }
03713          if (option_debug > 2)
03714             ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n");
03715          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03716             break;
03717          continue;
03718       }
03719       /* Read in frame from channel */
03720       fr = ast_read(who);
03721       other = (who == c0) ? c1 : c0;
03722       /* Depending on the frame we may need to break out of our bridge */
03723       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03724              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03725              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03726          /* Record received frame and who */
03727          *fo = fr;
03728          *rc = who;
03729          ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
03730          res = AST_BRIDGE_COMPLETE;
03731          break;
03732       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03733          if ((fr->subclass == AST_CONTROL_HOLD) ||
03734              (fr->subclass == AST_CONTROL_UNHOLD) ||
03735              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03736              (fr->subclass == AST_CONTROL_T38) ||
03737              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03738             /* If we are going on hold, then break callback mode and P2P bridging */
03739             if (fr->subclass == AST_CONTROL_HOLD) {
03740                if (p0_callback)
03741                   p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
03742                if (p1_callback)
03743                   p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
03744                p2p_set_bridge(p0, NULL);
03745                p2p_set_bridge(p1, NULL);
03746             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03747                /* If we are off hold, then go back to callback mode and P2P bridging */
03748                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03749                p2p_set_bridge(p0, p1);
03750                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03751                p2p_set_bridge(p1, p0);
03752                p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
03753                p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
03754             }
03755             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03756             ast_frfree(fr);
03757          } else {
03758             *fo = fr;
03759             *rc = who;
03760             ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03761             res = AST_BRIDGE_COMPLETE;
03762             break;
03763          }
03764       } else {
03765          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03766              (fr->frametype == AST_FRAME_DTMF_END) ||
03767              (fr->frametype == AST_FRAME_VOICE) ||
03768              (fr->frametype == AST_FRAME_VIDEO) ||
03769              (fr->frametype == AST_FRAME_IMAGE) ||
03770              (fr->frametype == AST_FRAME_HTML) ||
03771              (fr->frametype == AST_FRAME_MODEM) ||
03772              (fr->frametype == AST_FRAME_TEXT)) {
03773             ast_write(other, fr);
03774          }
03775 
03776          ast_frfree(fr);
03777       }
03778       /* Swap priority */
03779 #ifndef HAVE_EPOLL
03780       cs[2] = cs[0];
03781       cs[0] = cs[1];
03782       cs[1] = cs[2];
03783 #endif
03784    }
03785 
03786    /* If we are totally avoiding the core, then restore our link to it */
03787    if (p0_callback)
03788       p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
03789    if (p1_callback)
03790       p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
03791 
03792    /* Break out of the direct bridge */
03793    p2p_set_bridge(p0, NULL);
03794    p2p_set_bridge(p1, NULL);
03795 
03796    ast_poll_channel_del(c0, c1);
03797 
03798    return res;
03799 }

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

01367 {
01368    int res = 0, payload = 0, bridged_payload = 0, mark;
01369    struct rtpPayloadType rtpPT;
01370    int reconstruct = ntohl(rtpheader[0]);
01371 
01372    /* Get fields from packet */
01373    payload = (reconstruct & 0x7f0000) >> 16;
01374    mark = (((reconstruct & 0x800000) >> 23) != 0);
01375 
01376    /* Check what the payload value should be */
01377    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01378 
01379    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01380    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01381       return -1;
01382 
01383    /* Otherwise adjust bridged payload to match */
01384    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01385 
01386    /* 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 */
01387    if (!bridged->current_RTP_PT[bridged_payload].code)
01388       return -1;
01389 
01390 
01391    /* If the mark bit has not been sent yet... do it now */
01392    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01393       mark = 1;
01394       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01395    }
01396 
01397    /* Reconstruct part of the packet */
01398    reconstruct &= 0xFF80FFFF;
01399    reconstruct |= (bridged_payload << 16);
01400    reconstruct |= (mark << 23);
01401    rtpheader[0] = htonl(reconstruct);
01402 
01403    /* Send the packet back out */
01404    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01405    if (res < 0) {
01406       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01407          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));
01408       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01409          if (option_debug || rtpdebug)
01410             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));
01411          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01412       }
01413       return 0;
01414    } else if (rtp_debug_test_addr(&bridged->them))
01415          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);
01416 
01417    return 0;
01418 }

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

Definition at line 1317 of file rtp.c.

References ast_rtp::drxcore, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtp::rtcp, ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtp::rxtransit, and ast_rtp::seedrxts.

Referenced by ast_rtp_read(), and schedule_delivery().

01318 {
01319    struct timeval now;
01320    double transit;
01321    double current_time;
01322    double d;
01323    double dtv;
01324    double prog;
01325    
01326    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01327       gettimeofday(&rtp->rxcore, NULL);
01328       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01329       /* map timestamp to a real time */
01330       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01331       rtp->rxcore.tv_sec -= timestamp / 8000;
01332       rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
01333       /* Round to 0.1ms for nice, pretty timestamps */
01334       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01335       if (rtp->rxcore.tv_usec < 0) {
01336          /* Adjust appropriately if necessary */
01337          rtp->rxcore.tv_usec += 1000000;
01338          rtp->rxcore.tv_sec -= 1;
01339       }
01340    }
01341 
01342    gettimeofday(&now,NULL);
01343    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01344    tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
01345    tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
01346    if (tv->tv_usec >= 1000000) {
01347       tv->tv_usec -= 1000000;
01348       tv->tv_sec += 1;
01349    }
01350    prog = (double)((timestamp-rtp->seedrxts)/8000.);
01351    dtv = (double)rtp->drxcore + (double)(prog);
01352    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01353    transit = current_time - dtv;
01354    d = transit - rtp->rxtransit;
01355    rtp->rxtransit = transit;
01356    if (d<0)
01357       d=-d;
01358    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01359    if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
01360       rtp->rtcp->maxrxjitter = rtp->rxjitter;
01361    if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01362       rtp->rtcp->minrxjitter = rtp->rxjitter;
01363 }

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

Definition at line 2592 of file rtp.c.

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

Referenced by ast_rtp_raw_write().

02593 {
02594    struct timeval t;
02595    long ms;
02596    if (ast_tvzero(rtp->txcore)) {
02597       rtp->txcore = ast_tvnow();
02598       /* Round to 20ms for nice, pretty timestamps */
02599       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02600    }
02601    /* Use previous txcore if available */
02602    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02603    ms = ast_tvdiff_ms(t, rtp->txcore);
02604    if (ms < 0)
02605       ms = 0;
02606    /* Use what we just got for next time */
02607    rtp->txcore = t;
02608    return (unsigned int) ms;
02609 }

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

Get channel driver interface structure.

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

01842 {
01843    struct ast_rtp_protocol *cur = NULL;
01844 
01845    AST_RWLIST_RDLOCK(&protos);
01846    AST_RWLIST_TRAVERSE(&protos, cur, list) {
01847       if (cur->type == chan->tech->type)
01848          break;
01849    }
01850    AST_RWLIST_UNLOCK(&protos);
01851 
01852    return cur;
01853 }

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

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

04115 {
04116    switch (cmd) {
04117    case CLI_INIT:
04118       e->command = "rtcp debug [off|ip]";
04119       e->usage =
04120          "Usage: rtcp debug [off]|[ip host[:port]]\n"
04121          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
04122          "       specified, limit the dumped packets to those to and from\n"
04123          "       the specified 'host' with optional port.\n";
04124       return NULL;
04125    case CLI_GENERATE:
04126       return NULL;
04127    }
04128 
04129    if (a->argc < 2 || a->argc > 4)
04130       return CLI_SHOWUSAGE;
04131    if (a->argc == 2) {
04132       rtcpdebug = 1;
04133       memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
04134       ast_cli(a->fd, "RTCP Debugging Enabled\n");
04135    } else if (a->argc == 3) {
04136       if (strncasecmp(a->argv[2], "off", 3))
04137          return CLI_SHOWUSAGE;
04138       rtcpdebug = 0;
04139       ast_cli(a->fd, "RTCP Debugging Disabled\n");
04140    } else {
04141       if (strncasecmp(a->argv[2], "ip", 2))
04142          return CLI_SHOWUSAGE;
04143       return rtcp_do_debug_ip(a);
04144    }
04145 
04146    return CLI_SUCCESS;
04147 }

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

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

04150 {
04151    switch (cmd) {
04152    case CLI_INIT:
04153       e->command = "rtcp set debug {on|off|ip}";
04154       e->usage =
04155          "Usage: rtcp set debug {on|off|ip host[:port]}\n"
04156          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
04157          "       specified, limit the dumped packets to those to and from\n"
04158          "       the specified 'host' with optional port.\n";
04159       return NULL;
04160    case CLI_GENERATE:
04161       return NULL;
04162    }
04163 
04164    if (a->argc == e->args) { /* set on or off */
04165       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
04166          rtcpdebug = 1;
04167          memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
04168          ast_cli(a->fd, "RTCP Debugging Enabled\n");
04169          return CLI_SUCCESS;
04170       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
04171          rtcpdebug = 0;
04172          ast_cli(a->fd, "RTCP Debugging Disabled\n");
04173          return CLI_SUCCESS;
04174       }
04175    } else if (a->argc == e->args +1) { /* ip */
04176       return rtcp_do_debug_ip(a);
04177    }
04178 
04179    return CLI_SHOWUSAGE;   /* default, failure */
04180 }

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

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

04206 {
04207    switch (cmd) {
04208    case CLI_INIT:
04209       e->command = "rtcp set stats {on|off}";
04210       e->usage =
04211          "Usage: rtcp set stats {on|off}\n"
04212          "       Enable/Disable dumping of RTCP stats.\n";
04213       return NULL;
04214    case CLI_GENERATE:
04215       return NULL;
04216    }
04217 
04218    if (a->argc != e->args)
04219       return CLI_SHOWUSAGE;
04220 
04221    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04222       rtcpstats = 1;
04223    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04224       rtcpstats = 0;
04225    else
04226       return CLI_SHOWUSAGE;
04227 
04228    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04229    return CLI_SUCCESS;
04230 }

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

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

04183 {
04184    switch (cmd) {
04185    case CLI_INIT:
04186       e->command = "rtcp stats [off]";
04187       e->usage =
04188          "Usage: rtcp stats [off]\n"
04189          "       Enable/Disable dumping of RTCP stats.\n";
04190       return NULL;
04191    case CLI_GENERATE:
04192       return NULL;
04193    }
04194 
04195    if (a->argc < 2 || a->argc > 3)
04196       return CLI_SHOWUSAGE;
04197    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04198       return CLI_SHOWUSAGE;
04199 
04200    rtcpstats = (a->argc == 3) ? 0 : 1;
04201    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
04202    return CLI_SUCCESS;
04203 }

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

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

04047 {
04048    switch (cmd) {
04049    case CLI_INIT:
04050       e->command = "rtp debug [off|ip]";
04051       e->usage =
04052          "Usage: rtp debug [off]|[ip host[:port]]\n"
04053          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
04054          "       specified, limit the dumped packets to those to and from\n"
04055          "       the specified 'host' with optional port.\n";
04056       return NULL;
04057    case CLI_GENERATE:
04058       return NULL;
04059    }
04060 
04061    if (a->argc < 2 || a->argc > 4)
04062       return CLI_SHOWUSAGE;
04063    if (a->argc == 2) {
04064       rtpdebug = 1;
04065       memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
04066       ast_cli(a->fd, "RTP Debugging Enabled\n");
04067    } else if (a->argc == 3) {
04068       if (strncasecmp(a->argv[2], "off", 3))
04069          return CLI_SHOWUSAGE;
04070       rtpdebug = 0;
04071       ast_cli(a->fd, "RTP Debugging Disabled\n");
04072    } else {
04073       if (strncasecmp(a->argv[2], "ip", 2))
04074          return CLI_SHOWUSAGE;
04075       return rtp_do_debug_ip(a);
04076    }
04077 
04078    return CLI_SUCCESS;
04079 }

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

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

04082 {
04083    switch (cmd) {
04084    case CLI_INIT:
04085       e->command = "rtp set debug {on|off|ip}";
04086       e->usage =
04087          "Usage: rtp set debug {on|off|ip host[:port]}\n"
04088          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
04089          "       specified, limit the dumped packets to those to and from\n"
04090          "       the specified 'host' with optional port.\n";
04091       return NULL;
04092    case CLI_GENERATE:
04093       return NULL;
04094    }
04095 
04096    if (a->argc == e->args) { /* set on or off */
04097       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
04098          rtpdebug = 1;
04099          memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
04100          ast_cli(a->fd, "RTP Debugging Enabled\n");
04101          return CLI_SUCCESS;
04102       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
04103          rtpdebug = 0;
04104          ast_cli(a->fd, "RTP Debugging Disabled\n");
04105          return CLI_SUCCESS;
04106       }
04107    } else if (a->argc == e->args +1) { /* ip */
04108       return rtp_do_debug_ip(a);
04109    }
04110 
04111    return CLI_SHOWUSAGE;   /* default, failure */
04112 }

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

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

04233 {
04234    switch (cmd) {
04235    case CLI_INIT:
04236       e->command = "stun debug [off]";
04237       e->usage =
04238          "Usage: stun debug [off]\n"
04239          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04240          "       debugging\n";
04241       return NULL;
04242    case CLI_GENERATE:
04243       return NULL;
04244    }
04245 
04246    if (a->argc < 2 || a->argc > 3)
04247       return CLI_SHOWUSAGE;
04248    if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
04249       return CLI_SHOWUSAGE;
04250 
04251    stundebug = (a->argc == 3) ? 0 : 1;
04252    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04253    return CLI_SUCCESS;
04254 }

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

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

04257 {
04258    switch (cmd) {
04259    case CLI_INIT:
04260       e->command = "stun set debug {on|off}";
04261       e->usage =
04262          "Usage: stun set debug {on|off}\n"
04263          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
04264          "       debugging\n";
04265       return NULL;
04266    case CLI_GENERATE:
04267       return NULL;
04268    }
04269 
04270    if (a->argc != e->args)
04271       return CLI_SHOWUSAGE;
04272 
04273    if (!strncasecmp(a->argv[e->args-1], "on", 2))
04274       stundebug = 1;
04275    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
04276       stundebug = 0;
04277    else
04278       return CLI_SHOWUSAGE;
04279 
04280    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
04281    return CLI_SUCCESS;
04282 }

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

03627 {
03628    ast_channel_lock(chan);
03629 
03630    /* Remove the callback from the IO context */
03631    ast_io_remove(rtp->io, iod[0]);
03632 
03633    /* Restore file descriptors */
03634    chan->fds[0] = ast_rtp_fd(rtp);
03635    ast_channel_unlock(chan);
03636 
03637    /* Restore callback mode if previously used */
03638    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03639       rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp);
03640 
03641    return 0;
03642 }

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

P2P RTP Callback.

Definition at line 3619 of file rtp.c.

Referenced by bridge_p2p_loop().

03620 {
03621    return 0;
03622 }

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

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

Referenced by bridge_p2p_loop().

03646 {
03647    rtp_bridge_lock(rtp0);
03648    rtp0->bridged = rtp1;
03649    rtp_bridge_unlock(rtp0);
03650 }

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

Definition at line 844 of file rtp.c.

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

Referenced by ast_rtp_read().

00845 {
00846    unsigned int event;
00847    char resp = 0;
00848    struct ast_frame *f = NULL;
00849    unsigned char seq;
00850    unsigned int flags;
00851    unsigned int power;
00852 
00853    /* We should have at least 4 bytes in RTP data */
00854    if (len < 4)
00855       return f;
00856 
00857    /* The format of Cisco RTP DTMF packet looks like next:
00858       +0          - sequence number of DTMF RTP packet (begins from 1,
00859                     wrapped to 0)
00860       +1          - set of flags
00861       +1 (bit 0)     - flaps by different DTMF digits delimited by audio
00862                     or repeated digit without audio???
00863       +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
00864                     then falls to 0 at its end)
00865       +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
00866       Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
00867       by each new packet and thus provides some redudancy.
00868       
00869       Sample of Cisco RTP DTMF packet is (all data in hex):
00870          19 07 00 02 12 02 20 02
00871       showing end of DTMF digit '2'.
00872 
00873       The packets
00874          27 07 00 02 0A 02 20 02
00875          28 06 20 02 00 02 0A 02
00876       shows begin of new digit '2' with very short pause (20 ms) after
00877       previous digit '2'. Bit +1.0 flips at begin of new digit.
00878       
00879       Cisco RTP DTMF packets comes as replacement of audio RTP packets
00880       so its uses the same sequencing and timestamping rules as replaced
00881       audio packets. Repeat interval of DTMF packets is 20 ms and not rely
00882       on audio framing parameters. Marker bit isn't used within stream of
00883       DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
00884       are not sequential at borders between DTMF and audio streams,
00885    */
00886 
00887    seq = data[0];
00888    flags = data[1];
00889    power = data[2];
00890    event = data[3] & 0x1f;
00891 
00892    if (option_debug > 2 || rtpdebug)
00893       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);
00894    if (event < 10) {
00895       resp = '0' + event;
00896    } else if (event < 11) {
00897       resp = '*';
00898    } else if (event < 12) {
00899       resp = '#';
00900    } else if (event < 16) {
00901       resp = 'A' + (event - 12);
00902    } else if (event < 17) {
00903       resp = 'X';
00904    }
00905    if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
00906       rtp->resp = resp;
00907       /* Why we should care on DTMF compensation at reception? */
00908       if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
00909          f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
00910          rtp->dtmfsamples = 0;
00911       }
00912    } else if ((rtp->resp == resp) && !power) {
00913       f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00914       f->samples = rtp->dtmfsamples * 8;
00915       rtp->resp = 0;
00916    } else if (rtp->resp == resp)
00917       rtp->dtmfsamples += 20 * 8;
00918    rtp->dtmf_timeout = dtmftimeout;
00919    return f;
00920 }

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

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

Referenced by ast_rtp_read().

00935 {
00936    unsigned int event;
00937    unsigned int event_end;
00938    unsigned int samples;
00939    char resp = 0;
00940    struct ast_frame *f = NULL;
00941 
00942    /* Figure out event, event end, and samples */
00943    event = ntohl(*((unsigned int *)(data)));
00944    event >>= 24;
00945    event_end = ntohl(*((unsigned int *)(data)));
00946    event_end <<= 8;
00947    event_end >>= 24;
00948    samples = ntohl(*((unsigned int *)(data)));
00949    samples &= 0xFFFF;
00950 
00951    /* Print out debug if turned on */
00952    if (rtpdebug || option_debug > 2)
00953       ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
00954 
00955    /* Figure out what digit was pressed */
00956    if (event < 10) {
00957       resp = '0' + event;
00958    } else if (event < 11) {
00959       resp = '*';
00960    } else if (event < 12) {
00961       resp = '#';
00962    } else if (event < 16) {
00963       resp = 'A' + (event - 12);
00964    } else if (event < 17) {   /* Event 16: Hook flash */
00965       resp = 'X'; 
00966    } else {
00967       /* Not a supported event */
00968       ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
00969       return &ast_null_frame;
00970    }
00971 
00972    if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
00973       if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
00974          rtp->resp = resp;
00975          rtp->dtmf_timeout = 0;
00976          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00977          f->len = 0;
00978          rtp->lastevent = timestamp;
00979       }
00980    } else {
00981       /*  The duration parameter measures the complete
00982           duration of the event (from the beginning) - RFC2833.
00983           Account for the fact that duration is only 16 bits long
00984           (about 8 seconds at 8000 Hz) and can wrap is digit
00985           is hold for too long. */
00986       unsigned int new_duration = rtp->dtmf_duration;
00987       unsigned int last_duration = new_duration & 0xFFFF;
00988 
00989       if (last_duration > 64000 && samples < last_duration)
00990          new_duration += 0xFFFF + 1;
00991       new_duration = (new_duration & ~0xFFFF) | samples;
00992 
00993       if (event_end & 0x80) {
00994          /* End event */
00995          if ((rtp->lastevent != seqno) && rtp->resp) {
00996             rtp->dtmf_duration = new_duration;
00997             f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00998             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
00999             rtp->resp = 0;
01000             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01001          }
01002       } else {
01003          /* Begin/continuation */
01004 
01005          if (rtp->resp && rtp->resp != resp) {
01006             /* Another digit already began. End it */
01007             f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01008             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
01009             rtp->resp = 0;
01010             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01011          }
01012 
01013 
01014          if (rtp->resp) {
01015             /* Digit continues */
01016             rtp->dtmf_duration = new_duration;
01017          } else {
01018             /* New digit began */
01019             rtp->resp = resp;
01020             f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
01021             rtp->dtmf_duration = samples;
01022          }
01023 
01024          rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
01025       }
01026 
01027       rtp->lastevent = seqno;
01028    }
01029 
01030    rtp->dtmfsamples = samples;
01031 
01032    return f;
01033 }

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 1041 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_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_read().

01042 {
01043    struct ast_frame *f = NULL;
01044    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
01045       totally help us out becuase we don't have an engine to keep it going and we are not
01046       guaranteed to have it every 20ms or anything */
01047    if (rtpdebug)
01048       ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
01049 
01050    if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
01051       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
01052          ast_inet_ntoa(rtp->them.sin_addr));
01053       ast_set_flag(rtp, FLAG_3389_WARNING);
01054    }
01055    
01056    /* Must have at least one byte */
01057    if (!len)
01058       return NULL;
01059    if (len < 24) {
01060       rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
01061       rtp->f.datalen = len - 1;
01062       rtp->f.offset = AST_FRIENDLY_OFFSET;
01063       memcpy(rtp->f.data, data + 1, len - 1);
01064    } else {
01065       rtp->f.data = NULL;
01066       rtp->f.offset = 0;
01067       rtp->f.datalen = 0;
01068    }
01069    rtp->f.frametype = AST_FRAME_CNG;
01070    rtp->f.subclass = data[0] & 0x7f;
01071    rtp->f.datalen = len - 1;
01072    rtp->f.samples = 0;
01073    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
01074    f = &rtp->f;
01075    return f;
01076 }

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

Definition at line 830 of file rtp.c.

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

00831 {
00832    if (rtcpdebug == 0)
00833       return 0;
00834    if (rtcpdebugaddr.sin_addr.s_addr) {
00835       if (((ntohs(rtcpdebugaddr.sin_port) != 0)
00836            && (rtcpdebugaddr.sin_port != addr->sin_port))
00837           || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00838          return 0;
00839    }
00840    return 1;
00841 }

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

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

04017 {
04018    struct hostent *hp;
04019    struct ast_hostent ahp;
04020    int port = 0;
04021    char *p, *arg;
04022 
04023    arg = a->argv[3];
04024    p = strstr(arg, ":");
04025    if (p) {
04026       *p = '\0';
04027       p++;
04028       port = atoi(p);
04029    }
04030    hp = ast_gethostbyname(arg, &ahp);
04031    if (hp == NULL) {
04032       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04033       return CLI_FAILURE;
04034    }
04035    rtcpdebugaddr.sin_family = AF_INET;
04036    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
04037    rtcpdebugaddr.sin_port = htons(port);
04038    if (port == 0)
04039       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
04040    else
04041       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
04042    rtcpdebug = 1;
04043    return CLI_SUCCESS;
04044 }

static void rtp_bridge_lock ( struct ast_rtp rtp  )  [static]

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

00777 {
00778 #ifdef P2P_INTENSE
00779    ast_mutex_lock(&rtp->bridge_lock);
00780 #endif
00781    return;
00782 }

static void rtp_bridge_unlock ( struct ast_rtp rtp  )  [static]

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

00785 {
00786 #ifdef P2P_INTENSE
00787    ast_mutex_unlock(&rtp->bridge_lock);
00788 #endif
00789    return;
00790 }

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

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

00818 {
00819    if (rtpdebug == 0)
00820       return 0;
00821    if (rtpdebugaddr.sin_addr.s_addr) {
00822       if (((ntohs(rtpdebugaddr.sin_port) != 0)
00823            && (rtpdebugaddr.sin_port != addr->sin_port))
00824           || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00825          return 0;
00826    }
00827    return 1;
00828 }

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

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

03987 {
03988    struct hostent *hp;
03989    struct ast_hostent ahp;
03990    int port = 0;
03991    char *p, *arg;
03992 
03993    arg = a->argv[3];
03994    p = strstr(arg, ":");
03995    if (p) {
03996       *p = '\0';
03997       p++;
03998       port = atoi(p);
03999    }
04000    hp = ast_gethostbyname(arg, &ahp);
04001    if (hp == NULL) {
04002       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
04003       return CLI_FAILURE;
04004    }
04005    rtpdebugaddr.sin_family = AF_INET;
04006    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
04007    rtpdebugaddr.sin_port = htons(port);
04008    if (port == 0)
04009       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
04010    else
04011       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
04012    rtpdebug = 1;
04013    return CLI_SUCCESS;
04014 }

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

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

Definition at line 2218 of file rtp.c.

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

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

02219 {
02220    int s = socket(AF_INET, SOCK_DGRAM, 0);
02221    if (s < 0) {
02222       if (type == NULL)
02223          type = "RTP/RTCP";
02224       ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
02225    } else {
02226       long flags = fcntl(s, F_GETFL);
02227       fcntl(s, F_SETFL, flags | O_NONBLOCK);
02228 #ifdef SO_NO_CHECK
02229       if (nochecksums)
02230          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
02231 #endif
02232    }
02233    return s;
02234 }

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

Definition at line 1078 of file rtp.c.

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

Referenced by p2p_callback_disable().

01079 {
01080    struct ast_rtp *rtp = cbdata;
01081    struct ast_frame *f;
01082    f = ast_rtp_read(rtp);
01083    if (f) {
01084       if (rtp->callback)
01085          rtp->callback(rtp, f, rtp->data);
01086    }
01087    return 1;
01088 }

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

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

00793 {
00794    if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
00795         (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
00796       ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
00797       rtp->resp = 0;
00798       rtp->dtmfsamples = 0;
00799       return &ast_null_frame;
00800    }
00801    ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
00802    if (rtp->resp == 'X') {
00803       rtp->f.frametype = AST_FRAME_CONTROL;
00804       rtp->f.subclass = AST_CONTROL_FLASH;
00805    } else {
00806       rtp->f.frametype = type;
00807       rtp->f.subclass = rtp->resp;
00808    }
00809    rtp->f.datalen = 0;
00810    rtp->f.samples = 0;
00811    rtp->f.mallocd = 0;
00812    rtp->f.src = "RTP";
00813    return &rtp->f;
00814    
00815 }

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

helper function to print attribute names

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

00347 {
00348    switch (msg) {
00349    case STUN_MAPPED_ADDRESS:
00350       return "Mapped Address";
00351    case STUN_RESPONSE_ADDRESS:
00352       return "Response Address";
00353    case STUN_CHANGE_REQUEST:
00354       return "Change Request";
00355    case STUN_SOURCE_ADDRESS:
00356       return "Source Address";
00357    case STUN_CHANGED_ADDRESS:
00358       return "Changed Address";
00359    case STUN_USERNAME:
00360       return "Username";
00361    case STUN_PASSWORD:
00362       return "Password";
00363    case STUN_MESSAGE_INTEGRITY:
00364       return "Message Integrity";
00365    case STUN_ERROR_CODE:
00366       return "Error Code";
00367    case STUN_UNKNOWN_ATTRIBUTES:
00368       return "Unknown Attributes";
00369    case STUN_REFLECTED_FROM:
00370       return "Reflected From";
00371    }
00372    return "Non-RFC3489 Attribute";
00373 }

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

00564 {
00565    struct stun_addr *addr = (struct stun_addr *)(attr + 1);
00566    struct sockaddr_in *sa = (struct sockaddr_in *)arg;
00567 
00568    if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
00569       return 1;   /* not us. */
00570    sa->sin_port = addr->port;
00571    sa->sin_addr.s_addr = addr->addr;
00572    return 0;
00573 }

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

00467 {
00468    struct stun_header *hdr = (struct stun_header *)data;
00469    struct stun_attr *attr;
00470    struct stun_state st;
00471    int ret = STUN_IGNORE;  
00472    int x;
00473 
00474    /* On entry, 'len' is the length of the udp payload. After the
00475     * initial checks it becomes the size of unprocessed options,
00476     * while 'data' is advanced accordingly.
00477     */
00478    if (len < sizeof(struct stun_header)) {
00479       ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
00480       return -1;
00481    }
00482    len -= sizeof(struct stun_header);
00483    data += sizeof(struct stun_header);
00484    x = ntohs(hdr->msglen); /* len as advertised in the message */
00485    if (stundebug)
00486       ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
00487    if (x > len) {
00488       ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
00489    } else
00490       len = x;
00491    memset(&st, 0, sizeof(st));
00492    while (len) {
00493       if (len < sizeof(struct stun_attr)) {
00494          ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
00495          break;
00496       }
00497       attr = (struct stun_attr *)data;
00498       /* compute total attribute length */
00499       x = ntohs(attr->len) + sizeof(struct stun_attr);
00500       if (x > len) {
00501          ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
00502          break;
00503       }
00504       if (stun_cb)
00505          stun_cb(attr, arg);
00506       if (stun_process_attr(&st, attr)) {
00507          ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
00508          break;
00509       }
00510       /* Clear attribute id: in case previous entry was a string,
00511        * this will act as the terminator for the string.
00512        */
00513       attr->attr = 0;
00514       data += x;
00515       len -= x;
00516    }
00517    /* Null terminate any string.
00518     * XXX NOTE, we write past the size of the buffer passed by the
00519     * caller, so this is potentially dangerous. The only thing that
00520     * saves us is that usually we read the incoming message in a
00521     * much larger buffer in the struct ast_rtp
00522     */
00523    *data = '\0';
00524 
00525    /* Now prepare to generate a reply, which at the moment is done
00526     * only for properly formed (len == 0) STUN_BINDREQ messages.
00527     */
00528    if (len == 0) {
00529       unsigned char respdata[1024];
00530       struct stun_header *resp = (struct stun_header *)respdata;
00531       int resplen = 0;  /* len excluding header */
00532       int respleft = sizeof(respdata) - sizeof(struct stun_header);
00533 
00534       resp->id = hdr->id;
00535       resp->msgtype = 0;
00536       resp->msglen = 0;
00537       attr = (struct stun_attr *)resp->ies;
00538       switch (ntohs(hdr->msgtype)) {
00539       case STUN_BINDREQ:
00540          if (stundebug)
00541             ast_verbose("STUN Bind Request, username: %s\n", 
00542                    st.username ? st.username : "<none>");
00543          if (st.username)
00544             append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
00545          append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
00546          resp->msglen = htons(resplen);
00547          resp->msgtype = htons(STUN_BINDRESP);
00548          stun_send(s, src, resp);
00549          ret = STUN_ACCEPT;
00550          break;
00551       default:
00552          if (stundebug)
00553             ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
00554       }
00555    }
00556    return ret;
00557 }

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

helper function to print message names

Definition at line 326 of file rtp.c.

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

Referenced by stun_handle_packet().

00327 {
00328    switch (msg) {
00329    case STUN_BINDREQ:
00330       return "Binding Request";
00331    case STUN_BINDRESP:
00332       return "Binding Response";
00333    case STUN_BINDERR:
00334       return "Binding Error Response";
00335    case STUN_SECREQ:
00336       return "Shared Secret Request";
00337    case STUN_SECRESP:
00338       return "Shared Secret Response";
00339    case STUN_SECERR:
00340       return "Shared Secret Error Response";
00341    }
00342    return "Non-RFC3489 Message";
00343 }

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

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

00382 {
00383    if (stundebug)
00384       ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
00385              stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00386    switch (ntohs(attr->attr)) {
00387    case STUN_USERNAME:
00388       state->username = (const char *) (attr->value);
00389       break;
00390    case STUN_PASSWORD:
00391       state->password = (const char *) (attr->value);
00392       break;
00393    default:
00394       if (stundebug)
00395          ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 
00396                 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00397    }
00398    return 0;
00399 }

static void stun_req_id ( struct stun_header req  )  [static]

helper function to generate a random request id

Definition at line 442 of file rtp.c.

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

Referenced by ast_stun_request().

00443 {
00444    int x;
00445    for (x = 0; x < 4; x++)
00446       req->id.id[x] = ast_random();
00447 }

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

wrapper to send an STUN message

Definition at line 435 of file rtp.c.

References stun_header::msglen.

Referenced by ast_stun_request(), and stun_handle_packet().

00436 {
00437    return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00438             (struct sockaddr *)dst, sizeof(*dst));
00439 }

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

Definition at line 663 of file rtp.c.

References sec.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

00664 {
00665    unsigned int sec, usec, frac;
00666    sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
00667    usec = tv.tv_usec;
00668    frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
00669    *msw = sec;
00670    *lsw = frac;
00671 }


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

struct ast_cli_entry cli_rtp[] [static]

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

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

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

struct sockaddr_in rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 77 of file rtp.c.

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 74 of file rtp.c.

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 73 of file rtp.c.

int rtpdebug [static]

Are we debugging?

Definition at line 71 of file rtp.c.

struct sockaddr_in rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 76 of file rtp.c.

int rtpend = 31000 [static]

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

Definition at line 70 of file rtp.c.

int rtpstart = 5000 [static]

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

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

int stundebug [static]

Are we debugging stun?

Definition at line 75 of file rtp.c.

char* subtype

Definition at line 1703 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 1702 of file rtp.c.

Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), amixer_max(), ast_call_forward(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), eventhandler(), find_subscription_type(), g723_len(), h264_decap(), load_module(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), osp_lookup(), parse_information(), parse_setup(), parse_uri(), setamixer(), sla_load_config(), subscription_type2str(), and yyparse().


Generated on Thu Jul 9 13:41:31 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7