Sun Dec 18 20:55:54 2011

Asterisk developer's documentation


rtp.c File Reference

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

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"

Include dependency graph for rtp.c:

Go to the source code of this file.

Data Structures

struct  __attribute__
struct  ast_rtcp
 Structure defining an RTCP session. More...
struct  ast_rtp
 RTP session description. More...
struct  rtpPayloadType
 Structure representing a RTP session. More...
struct  stun_addr
struct  stun_attr
struct  stun_header
struct  stun_state

Defines

#define DEFAULT_DTMF_TIMEOUT   3000
#define FLAG_3389_WARNING   (1 << 0)
#define FLAG_CALLBACK_MODE   (1 << 6)
#define FLAG_DTMF_COMPENSATE   (1 << 7)
#define FLAG_HAS_DTMF   (1 << 3)
#define FLAG_HAS_STUN   (1 << 8)
#define FLAG_NAT_ACTIVE   (3 << 1)
#define FLAG_NAT_INACTIVE   (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
#define FLAG_P2P_NEED_DTMF   (1 << 5)
#define FLAG_P2P_SENT_MARK   (1 << 4)
#define MAX_TIMESTAMP_SKEW   640
#define RTCP_DEFAULT_INTERVALMS   5000
#define RTCP_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
#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
#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

Functions

static void append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
static void append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
static AST_LIST_HEAD_STATIC (protos, ast_rtp_protocol)
 List of current sessions.
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
struct ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Public function: Send an H.261 fast update request, some devices need this rather than SIP XML.
static int ast_rtcp_write (const void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (const void *data)
 Send RTCP recepient's report.
static int ast_rtcp_write_sr (const void *data)
 Send RTCP sender's report.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
enum ast_bridge_result ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
int ast_rtp_codec_getformat (int pt)
struct ast_codec_prefast_rtp_codec_getpref (struct ast_rtp *rtp)
int ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs)
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_early_bridge (struct ast_channel *dest, struct ast_channel *src)
 If possible, create an early bridge directly between the devices without having to send a re-invite later.
int ast_rtp_fd (struct ast_rtp *rtp)
struct ast_rtpast_rtp_get_bridged (struct ast_rtp *rtp)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
 Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
int ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
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):.
struct rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
 Mapping between RTP payload format codes and Asterisk codes:.
int ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media)
struct ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
void ast_rtp_new_init (struct ast_rtp *rtp)
 Initialize a new RTP structure.
void ast_rtp_new_source (struct ast_rtp *rtp)
struct ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
 Initializate a RTP session using an in_addr structure.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register interface to channel driver.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister interface to channel driver.
void ast_rtp_pt_clear (struct ast_rtp *rtp)
 Setting RTP payload types from lines in a SDP description:.
void ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src)
 Copy payload types between RTP structures.
void ast_rtp_pt_default (struct ast_rtp *rtp)
 Set payload types to defaults.
static int ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec)
struct ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
static int ast_rtp_senddigit_continuation (struct ast_rtp *rtp)
 Send continuation frame for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
void ast_rtp_set_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)
 Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_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)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 remove setting from payload type list if the rtpmap header indicates an unknown media type
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
static 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_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 int p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, 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 *fds, 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 int rtcp_do_debug (int fd, int argc, char *argv[])
static int rtcp_do_debug_deprecated (int fd, int argc, char *argv[])
static int rtcp_do_debug_ip (int fd, int argc, char *argv[])
static int rtcp_do_debug_ip_deprecated (int fd, int argc, char *argv[])
static int rtcp_do_stats (int fd, int argc, char *argv[])
static int rtcp_do_stats_deprecated (int fd, int argc, char *argv[])
static int rtcp_no_debug (int fd, int argc, char *argv[])
static int rtcp_no_debug_deprecated (int fd, int argc, char *argv[])
static int rtcp_no_stats (int fd, int argc, char *argv[])
static int rtcp_no_stats_deprecated (int fd, int argc, char *argv[])
static int rtp_debug_test_addr (struct sockaddr_in *addr)
static int rtp_do_debug (int fd, int argc, char *argv[])
static int rtp_do_debug_ip (int fd, int argc, char *argv[])
static int rtp_no_debug (int fd, int argc, char *argv[])
static int rtp_socket (void)
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)
static int stun_do_debug (int fd, int argc, char *argv[])
static int stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len)
static const char * stun_msg2str (int msg)
static int stun_no_debug (int fd, int argc, char *argv[])
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
static void stun_req_id (struct stun_header *req)
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)

Variables

static struct ast_cli_entry cli_rtp []
static struct ast_cli_entry cli_rtp_no_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated
static struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated
static struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated
static struct ast_cli_entry cli_rtp_rtcp_stats_deprecated
static struct ast_cli_entry cli_stun_no_debug_deprecated
static char debug_usage []
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
struct {
   struct rtpPayloadType   payloadType
   char *   subtype
   char *   type
mimeTypes []
static char no_debug_usage []
struct stun_header packed
static char rtcp_debug_usage []
static char rtcp_no_debug_usage []
static char rtcp_no_stats_usage []
static char rtcp_stats_usage []
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
static int rtpstart
static struct rtpPayloadType static_RTP_PT [MAX_RTP_PT]
static char stun_debug_usage []
static char stun_no_debug_usage []
static int stundebug


Detailed Description

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

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

Definition in file rtp.c.


Define Documentation

#define DEFAULT_DTMF_TIMEOUT   3000

samples

Definition at line 76 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 187 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)

Definition at line 194 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)

Definition at line 195 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 189 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 190 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 193 of file rtp.c.

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)

Definition at line 192 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 60 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 63 of file rtp.c.

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

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

Referenced by ast_rtp_reload().

#define RTCP_PT_APP   204

Definition at line 72 of file rtp.c.

#define RTCP_PT_BYE   203

Definition at line 71 of file rtp.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

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

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

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

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 74 of file rtp.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 62 of file rtp.c.

Referenced by ast_rtp_read().

#define STUN_ACCEPT   (1)

Definition at line 260 of file rtp.c.

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111

Definition at line 264 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001

Definition at line 262 of file rtp.c.

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

#define STUN_BINDRESP   0x0101

Definition at line 263 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 273 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)

Definition at line 259 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001

Definition at line 269 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 275 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 279 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 267 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 274 of file rtp.c.

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


Function Documentation

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

Definition at line 367 of file rtp.c.

References stun_addr::addr, stun_addr::family, stun_addr::port, and stun_addr::unused.

Referenced by stun_handle_packet().

00368 {
00369    int size = sizeof(**attr) + 8;
00370    struct stun_addr *addr;
00371    if (*left > size) {
00372       (*attr)->attr = htons(attrval);
00373       (*attr)->len = htons(8);
00374       addr = (struct stun_addr *)((*attr)->value);
00375       addr->unused = 0;
00376       addr->family = 0x01;
00377       addr->port = sin->sin_port;
00378       addr->addr = sin->sin_addr.s_addr;
00379       (*attr) = (struct stun_attr *)((*attr)->value + 8);
00380       *len += size;
00381       *left -= size;
00382    }
00383 }

static void append_attr_string ( struct stun_attr **  attr,
int  attrval,
const char *  s,
int *  len,
int *  left 
) [static]

Definition at line 354 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

00355 {
00356    int size = sizeof(**attr) + strlen(s);
00357    if (*left > size) {
00358       (*attr)->attr = htons(attrval);
00359       (*attr)->len = htons(strlen(s));
00360       memcpy((*attr)->value, s, strlen(s));
00361       (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
00362       *len += size;
00363       *left -= size;
00364    }
00365 }

static AST_LIST_HEAD_STATIC ( protos  ,
ast_rtp_protocol   
) [static]

List of current sessions.

unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Todo:
XXX Do a more reasonable calculation on this one Look in RFC 3550 Section A.7 for an example

Definition at line 525 of file rtp.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00526 {
00527    unsigned int interval;
00528    /*! \todo XXX Do a more reasonable calculation on this one
00529    * Look in RFC 3550 Section A.7 for an example*/
00530    interval = rtcpinterval;
00531    return interval;
00532 }

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 518 of file rtp.c.

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

Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), sip_new(), and start_rtp().

00519 {
00520    if (rtp->rtcp)
00521       return rtp->rtcp->s;
00522    return -1;
00523 }

static struct ast_rtcp* ast_rtcp_new ( void   )  [static, read]

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1858 of file rtp.c.

References ast_calloc, ast_log(), errno, free, LOG_WARNING, rtp_socket(), ast_rtcp::s, ast_rtcp::schedid, ast_rtcp::them, and ast_rtcp::us.

Referenced by ast_rtp_new_with_bindaddr().

01859 {
01860    struct ast_rtcp *rtcp;
01861 
01862    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01863       return NULL;
01864    rtcp->s = rtp_socket();
01865    rtcp->us.sin_family = AF_INET;
01866    rtcp->them.sin_family = AF_INET;
01867    rtcp->schedid = -1;
01868 
01869    if (rtcp->s < 0) {
01870       free(rtcp);
01871       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01872       return NULL;
01873    }
01874 
01875    return rtcp;
01876 }

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

Definition at line 826 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, ast_rtp::f, f, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, 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(), and skinny_rtp_read().

00827 {
00828    socklen_t len;
00829    int position, i, packetwords;
00830    int res;
00831    struct sockaddr_in sin;
00832    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
00833    unsigned int *rtcpheader;
00834    int pt;
00835    struct timeval now;
00836    unsigned int length;
00837    int rc;
00838    double rttsec;
00839    uint64_t rtt = 0;
00840    unsigned int dlsr;
00841    unsigned int lsr;
00842    unsigned int msw;
00843    unsigned int lsw;
00844    unsigned int comp;
00845    struct ast_frame *f = &ast_null_frame;
00846    
00847    if (!rtp || !rtp->rtcp)
00848       return &ast_null_frame;
00849 
00850    len = sizeof(sin);
00851    
00852    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
00853                0, (struct sockaddr *)&sin, &len);
00854    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
00855    
00856    if (res < 0) {
00857       ast_assert(errno != EBADF);
00858       if (errno != EAGAIN) {
00859          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
00860          return NULL;
00861       }
00862       return &ast_null_frame;
00863    }
00864 
00865    packetwords = res / 4;
00866    
00867    if (rtp->nat) {
00868       /* Send to whoever sent to us */
00869       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00870           (rtp->rtcp->them.sin_port != sin.sin_port)) {
00871          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00872          if (option_debug || rtpdebug)
00873             ast_log(LOG_DEBUG, "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));
00874       }
00875    }
00876 
00877    if (option_debug)
00878       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00879 
00880    /* Process a compound packet */
00881    position = 0;
00882    while (position < packetwords) {
00883       i = position;
00884       length = ntohl(rtcpheader[i]);
00885       pt = (length & 0xff0000) >> 16;
00886       rc = (length & 0x1f000000) >> 24;
00887       length &= 0xffff;
00888     
00889       if ((i + length) > packetwords) {
00890          ast_log(LOG_WARNING, "RTCP Read too short\n");
00891          return &ast_null_frame;
00892       }
00893       
00894       if (rtcp_debug_test_addr(&sin)) {
00895          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00896          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
00897          ast_verbose("Reception reports: %d\n", rc);
00898          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
00899       }
00900     
00901       i += 2; /* Advance past header and ssrc */
00902       
00903       switch (pt) {
00904       case RTCP_PT_SR:
00905          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
00906          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
00907          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
00908          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
00909     
00910          if (rtcp_debug_test_addr(&sin)) {
00911             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
00912             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
00913             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
00914          }
00915          i += 5;
00916          if (rc < 1)
00917             break;
00918          /* Intentional fall through */
00919       case RTCP_PT_RR:
00920          /* Don't handle multiple reception reports (rc > 1) yet */
00921          /* Calculate RTT per RFC */
00922          gettimeofday(&now, NULL);
00923          timeval2ntp(now, &msw, &lsw);
00924          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
00925             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
00926             lsr = ntohl(rtcpheader[i + 4]);
00927             dlsr = ntohl(rtcpheader[i + 5]);
00928             rtt = comp - lsr - dlsr;
00929 
00930             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
00931                sess->ee_delay = (eedelay * 1000) / 65536; */
00932             if (rtt < 4294) {
00933                 rtt = (rtt * 1000000) >> 16;
00934             } else {
00935                 rtt = (rtt * 1000) >> 16;
00936                 rtt *= 1000;
00937             }
00938             rtt = rtt / 1000.;
00939             rttsec = rtt / 1000.;
00940 
00941             if (comp - dlsr >= lsr) {
00942                rtp->rtcp->accumulated_transit += rttsec;
00943                rtp->rtcp->rtt = rttsec;
00944                if (rtp->rtcp->maxrtt<rttsec)
00945                   rtp->rtcp->maxrtt = rttsec;
00946                if (rtp->rtcp->minrtt>rttsec)
00947                   rtp->rtcp->minrtt = rttsec;
00948             } else if (rtcp_debug_test_addr(&sin)) {
00949                ast_verbose("Internal RTCP NTP clock skew detected: "
00950                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
00951                         "diff=%d\n",
00952                         lsr, comp, dlsr, dlsr / 65536,
00953                         (dlsr % 65536) * 1000 / 65536,
00954                         dlsr - (comp - lsr));
00955             }
00956          }
00957 
00958          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
00959          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
00960          if (rtcp_debug_test_addr(&sin)) {
00961             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
00962             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
00963             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
00964             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
00965             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
00966             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
00967             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
00968             if (rtt)
00969                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
00970          }
00971          break;
00972       case RTCP_PT_FUR:
00973          if (rtcp_debug_test_addr(&sin))
00974             ast_verbose("Received an RTCP Fast Update Request\n");
00975          rtp->f.frametype = AST_FRAME_CONTROL;
00976          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
00977          rtp->f.datalen = 0;
00978          rtp->f.samples = 0;
00979          rtp->f.mallocd = 0;
00980          rtp->f.src = "RTP";
00981          f = &rtp->f;
00982          break;
00983       case RTCP_PT_SDES:
00984          if (rtcp_debug_test_addr(&sin))
00985             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00986          break;
00987       case RTCP_PT_BYE:
00988          if (rtcp_debug_test_addr(&sin))
00989             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00990          break;
00991       default:
00992          if (option_debug)
00993             ast_log(LOG_DEBUG, "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));
00994          break;
00995       }
00996       position += (length + 1);
00997    }
00998          
00999    return f;
01000 }

int ast_rtcp_send_h261fur ( void *  data  ) 

Public function: Send an H.261 fast update request, some devices need this rather than SIP XML.

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

Definition at line 2340 of file rtp.c.

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

02341 {
02342    struct ast_rtp *rtp = data;
02343    int res;
02344 
02345    rtp->rtcp->sendfur = 1;
02346    res = ast_rtcp_write(data);
02347    
02348    return res;
02349 }

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

02558 {
02559    struct ast_rtp *rtp = (struct ast_rtp *)data;
02560    int res;
02561    
02562    if (!rtp || !rtp->rtcp)
02563       return 0;
02564 
02565    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02566       res = ast_rtcp_write_sr(data);
02567    else
02568       res = ast_rtcp_write_rr(data);
02569    
02570    return res;
02571 }

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

Send RTCP recepient'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 2462 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, and ast_rtp::themssrc.

Referenced by ast_rtcp_write().

02463 {
02464    struct ast_rtp *rtp = (struct ast_rtp *)data;
02465    int res;
02466    int len = 32;
02467    unsigned int lost;
02468    unsigned int extended;
02469    unsigned int expected;
02470    unsigned int expected_interval;
02471    unsigned int received_interval;
02472    int lost_interval;
02473    struct timeval now;
02474    unsigned int *rtcpheader;
02475    char bdata[1024];
02476    struct timeval dlsr;
02477    int fraction;
02478 
02479    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
02480       return 0;
02481      
02482    if (!rtp->rtcp->them.sin_addr.s_addr) {
02483       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
02484       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02485       return 0;
02486    }
02487 
02488    extended = rtp->cycles + rtp->lastrxseqno;
02489    expected = extended - rtp->seedrxseqno + 1;
02490    lost = expected - rtp->rxcount;
02491    expected_interval = expected - rtp->rtcp->expected_prior;
02492    rtp->rtcp->expected_prior = expected;
02493    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02494    rtp->rtcp->received_prior = rtp->rxcount;
02495    lost_interval = expected_interval - received_interval;
02496    if (expected_interval == 0 || lost_interval <= 0)
02497       fraction = 0;
02498    else
02499       fraction = (lost_interval << 8) / expected_interval;
02500    gettimeofday(&now, NULL);
02501    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02502    rtcpheader = (unsigned int *)bdata;
02503    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
02504    rtcpheader[1] = htonl(rtp->ssrc);
02505    rtcpheader[2] = htonl(rtp->themssrc);
02506    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02507    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02508    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02509    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
02510    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02511 
02512    if (rtp->rtcp->sendfur) {
02513       rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
02514       rtcpheader[9] = htonl(rtp->ssrc);               /* Our SSRC */
02515       len += 8;
02516       rtp->rtcp->sendfur = 0;
02517    }
02518 
02519    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
02520    it can change mid call, and SDES can't) */
02521    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02522    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02523    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
02524    len += 12;
02525    
02526    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02527 
02528    if (res < 0) {
02529       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
02530       /* Remove the scheduler */
02531       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02532       return 0;
02533    }
02534 
02535    rtp->rtcp->rr_count++;
02536 
02537    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02538       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
02539          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 
02540          "  IA jitter: %.4f\n" 
02541          "  Their last SR: %u\n" 
02542          "  DLSR: %4.4f (sec)\n\n",
02543          ast_inet_ntoa(rtp->rtcp->them.sin_addr),
02544          ntohs(rtp->rtcp->them.sin_port),
02545          rtp->ssrc, rtp->themssrc, fraction, lost,
02546          rtp->rxjitter,
02547          rtp->rtcp->themrxlsr,
02548          (double)(ntohl(rtcpheader[7])/65536.0));
02549    }
02550 
02551    return res;
02552 }

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

Send RTCP sender's report.

Definition at line 2352 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, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len, LOG_ERROR, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.

Referenced by ast_rtcp_write().

02353 {
02354    struct ast_rtp *rtp = (struct ast_rtp *)data;
02355    int res;
02356    int len = 0;
02357    struct timeval now;
02358    unsigned int now_lsw;
02359    unsigned int now_msw;
02360    unsigned int *rtcpheader;
02361    unsigned int lost;
02362    unsigned int extended;
02363    unsigned int expected;
02364    unsigned int expected_interval;
02365    unsigned int received_interval;
02366    int lost_interval;
02367    int fraction;
02368    struct timeval dlsr;
02369    char bdata[512];
02370 
02371    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
02372    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
02373       return 0;
02374    
02375    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
02376       ast_verbose("RTCP SR transmission error, rtcp halted\n");
02377       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02378       return 0;
02379    }
02380 
02381    gettimeofday(&now, NULL);
02382    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
02383    rtcpheader = (unsigned int *)bdata;
02384    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
02385    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
02386    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
02387    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
02388    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
02389    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
02390    len += 28;
02391    
02392    extended = rtp->cycles + rtp->lastrxseqno;
02393    expected = extended - rtp->seedrxseqno + 1;
02394    if (rtp->rxcount > expected) 
02395       expected += rtp->rxcount - expected;
02396    lost = expected - rtp->rxcount;
02397    expected_interval = expected - rtp->rtcp->expected_prior;
02398    rtp->rtcp->expected_prior = expected;
02399    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
02400    rtp->rtcp->received_prior = rtp->rxcount;
02401    lost_interval = expected_interval - received_interval;
02402    if (expected_interval == 0 || lost_interval <= 0)
02403       fraction = 0;
02404    else
02405       fraction = (lost_interval << 8) / expected_interval;
02406    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
02407    rtcpheader[7] = htonl(rtp->themssrc);
02408    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
02409    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
02410    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
02411    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
02412    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
02413    len += 24;
02414    
02415    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
02416 
02417    if (rtp->rtcp->sendfur) {
02418       rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
02419       rtcpheader[14] = htonl(rtp->ssrc);               /* Our SSRC */
02420       len += 8;
02421       rtp->rtcp->sendfur = 0;
02422    }
02423    
02424    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 
02425    /* it can change mid call, and SDES can't) */
02426    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
02427    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
02428    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
02429    len += 12;
02430    
02431    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
02432    if (res < 0) {
02433       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));
02434       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02435       return 0;
02436    }
02437    
02438    /* FIXME Don't need to get a new one */
02439    gettimeofday(&rtp->rtcp->txlsr, NULL);
02440    rtp->rtcp->sr_count++;
02441 
02442    rtp->rtcp->lastsrtxcount = rtp->txcount;  
02443    
02444    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
02445       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
02446       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
02447       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
02448       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
02449       ast_verbose("  Sent packets: %u\n", rtp->txcount);
02450       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
02451       ast_verbose("  Report block:\n");
02452       ast_verbose("  Fraction lost: %u\n", fraction);
02453       ast_verbose("  Cumulative loss: %u\n", lost);
02454       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
02455       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
02456       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
02457    }
02458    return res;
02459 }

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

Referenced by process_sdp().

00399 {
00400    return sizeof(struct ast_rtp);
00401 }

enum ast_bridge_result ast_rtp_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
)

Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.

Definition at line 3278 of file rtp.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), 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_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

03279 {
03280    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03281    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03282    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03283    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03284    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03285    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03286    int codec0 = 0, codec1 = 0;
03287    void *pvt0 = NULL, *pvt1 = NULL;
03288 
03289    /* Lock channels */
03290    ast_channel_lock(c0);
03291    while(ast_channel_trylock(c1)) {
03292       ast_channel_unlock(c0);
03293       usleep(1);
03294       ast_channel_lock(c0);
03295    }
03296 
03297    /* Ensure neither channel got hungup during lock avoidance */
03298    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03299       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
03300       ast_channel_unlock(c0);
03301       ast_channel_unlock(c1);
03302       return AST_BRIDGE_FAILED;
03303    }
03304       
03305    /* Find channel driver interfaces */
03306    if (!(pr0 = get_proto(c0))) {
03307       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03308       ast_channel_unlock(c0);
03309       ast_channel_unlock(c1);
03310       return AST_BRIDGE_FAILED;
03311    }
03312    if (!(pr1 = get_proto(c1))) {
03313       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03314       ast_channel_unlock(c0);
03315       ast_channel_unlock(c1);
03316       return AST_BRIDGE_FAILED;
03317    }
03318 
03319    /* Get channel specific interface structures */
03320    pvt0 = c0->tech_pvt;
03321    pvt1 = c1->tech_pvt;
03322 
03323    /* Get audio and video interface (if native bridge is possible) */
03324    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03325    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03326    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03327    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03328 
03329    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03330    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03331       audio_p0_res = AST_RTP_GET_FAILED;
03332    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03333       audio_p1_res = AST_RTP_GET_FAILED;
03334 
03335    /* Check if a bridge is possible (partial/native) */
03336    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03337       /* Somebody doesn't want to play... */
03338       ast_channel_unlock(c0);
03339       ast_channel_unlock(c1);
03340       return AST_BRIDGE_FAILED_NOWARN;
03341    }
03342 
03343    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03344    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03345       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03346       audio_p0_res = AST_RTP_TRY_PARTIAL;
03347    }
03348 
03349    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03350       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03351       audio_p1_res = AST_RTP_TRY_PARTIAL;
03352    }
03353 
03354    /* If both sides are not using the same method of DTMF transmission 
03355     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03356     * --------------------------------------------------
03357     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03358     * |-----------|------------|-----------------------|
03359     * | Inband    | False      | True                  |
03360     * | RFC2833   | True       | True                  |
03361     * | SIP INFO  | False      | False                 |
03362     * --------------------------------------------------
03363     * However, if DTMF from both channels is being monitored by the core, then
03364     * we can still do packet-to-packet bridging, because passing through the 
03365     * core will handle DTMF mode translation.
03366     */
03367    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03368        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03369       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03370          ast_channel_unlock(c0);
03371          ast_channel_unlock(c1);
03372          return AST_BRIDGE_FAILED_NOWARN;
03373       }
03374       audio_p0_res = AST_RTP_TRY_PARTIAL;
03375       audio_p1_res = AST_RTP_TRY_PARTIAL;
03376    }
03377 
03378    /* If we need to feed frames into the core don't do a P2P bridge */
03379    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
03380        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
03381       ast_channel_unlock(c0);
03382       ast_channel_unlock(c1);
03383       return AST_BRIDGE_FAILED_NOWARN;
03384    }
03385 
03386    /* Get codecs from both sides */
03387    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03388    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03389    if (codec0 && codec1 && !(codec0 & codec1)) {
03390       /* Hey, we can't do native bridging if both parties speak different codecs */
03391       if (option_debug)
03392          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03393       ast_channel_unlock(c0);
03394       ast_channel_unlock(c1);
03395       return AST_BRIDGE_FAILED_NOWARN;
03396    }
03397 
03398    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03399    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03400       struct ast_format_list fmt0, fmt1;
03401 
03402       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03403       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03404          if (option_debug)
03405             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03406          ast_channel_unlock(c0);
03407          ast_channel_unlock(c1);
03408          return AST_BRIDGE_FAILED_NOWARN;
03409       }
03410       /* They must also be using the same packetization */
03411       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
03412       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
03413       if (fmt0.cur_ms != fmt1.cur_ms) {
03414          if (option_debug)
03415             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n");
03416          ast_channel_unlock(c0);
03417          ast_channel_unlock(c1);
03418          return AST_BRIDGE_FAILED_NOWARN;
03419       }
03420 
03421       if (option_verbose > 2)
03422          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03423       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03424    } else {
03425       if (option_verbose > 2) 
03426          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03427       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03428    }
03429 
03430    return res;
03431 }

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2722 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp().

02723 {
02724    if (pt < 0 || pt > MAX_RTP_PT)
02725       return 0; /* bogus payload type */
02726 
02727    if (static_RTP_PT[pt].isAstFormat)
02728       return static_RTP_PT[pt].code;
02729    else
02730       return 0;
02731 }

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

Definition at line 2717 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02718 {
02719    return &rtp->pref;
02720 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2704 of file rtp.c.

References ast_smoother_free(), ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, and ast_rtp::smoother.

Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

02705 {
02706    int x;
02707    for (x = 0; x < 32; x++) {  /* Ugly way */
02708       rtp->pref.order[x] = prefs->order[x];
02709       rtp->pref.framing[x] = prefs->framing[x];
02710    }
02711    if (rtp->smoother)
02712       ast_smoother_free(rtp->smoother);
02713    rtp->smoother = NULL;
02714    return 0;
02715 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 2123 of file rtp.c.

References ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose(), ast_rtp::bridge_lock, ast_rtcp::expected_prior, free, ast_rtp::io, ast_rtp::ioid, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by __oh323_destroy(), __sip_destroy(), check_user_full(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().

02124 {
02125    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02126       /*Print some info on the call here */
02127       ast_verbose("  RTP-stats\n");
02128       ast_verbose("* Our Receiver:\n");
02129       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02130       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02131       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02132       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02133       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02134       ast_verbose("  RR-count:    %u\n", rtp->rtcp->rr_count);
02135       ast_verbose("* Our Sender:\n");
02136       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02137       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02138       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->reported_lost);
02139       ast_verbose("  Jitter:      %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0);
02140       ast_verbose("  SR-count:    %u\n", rtp->rtcp->sr_count);
02141       ast_verbose("  RTT:      %f\n", rtp->rtcp->rtt);
02142    }
02143 
02144    if (rtp->smoother)
02145       ast_smoother_free(rtp->smoother);
02146    if (rtp->ioid)
02147       ast_io_remove(rtp->io, rtp->ioid);
02148    if (rtp->s > -1)
02149       close(rtp->s);
02150    if (rtp->rtcp) {
02151       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02152       close(rtp->rtcp->s);
02153       free(rtp->rtcp);
02154       rtp->rtcp=NULL;
02155    }
02156 
02157    ast_mutex_destroy(&rtp->bridge_lock);
02158 
02159    free(rtp);
02160 }

int ast_rtp_early_bridge ( struct ast_channel dest,
struct ast_channel src 
)

If possible, create an early bridge directly between the devices without having to send a re-invite later.

Definition at line 1475 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, 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_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.

Referenced by wait_for_answer().

01476 {
01477    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01478    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01479    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01480    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01481    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
01482    int srccodec, destcodec, nat_active = 0;
01483 
01484    /* Lock channels */
01485    ast_channel_lock(dest);
01486    if (src) {
01487       while(ast_channel_trylock(src)) {
01488          ast_channel_unlock(dest);
01489          usleep(1);
01490          ast_channel_lock(dest);
01491       }
01492    }
01493 
01494    /* Find channel driver interfaces */
01495    destpr = get_proto(dest);
01496    if (src)
01497       srcpr = get_proto(src);
01498    if (!destpr) {
01499       if (option_debug)
01500          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01501       ast_channel_unlock(dest);
01502       if (src)
01503          ast_channel_unlock(src);
01504       return 0;
01505    }
01506    if (!srcpr) {
01507       if (option_debug)
01508          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>");
01509       ast_channel_unlock(dest);
01510       if (src)
01511          ast_channel_unlock(src);
01512       return 0;
01513    }
01514 
01515    /* Get audio and video interface (if native bridge is possible) */
01516    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01517    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01518    if (srcpr) {
01519       audio_src_res = srcpr->get_rtp_info(src, &srcp);
01520       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01521    }
01522 
01523    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01524    if (audio_dest_res != AST_RTP_TRY_NATIVE) {
01525       /* Somebody doesn't want to play... */
01526       ast_channel_unlock(dest);
01527       if (src)
01528          ast_channel_unlock(src);
01529       return 0;
01530    }
01531    if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec)
01532       srccodec = srcpr->get_codec(src);
01533    else
01534       srccodec = 0;
01535    if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec)
01536       destcodec = destpr->get_codec(dest);
01537    else
01538       destcodec = 0;
01539    /* Ensure we have at least one matching codec */
01540    if (!(srccodec & destcodec)) {
01541       ast_channel_unlock(dest);
01542       if (src)
01543          ast_channel_unlock(src);
01544       return 0;
01545    }
01546    /* Consider empty media as non-existant */
01547    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
01548       srcp = NULL;
01549    /* If the client has NAT stuff turned on then just safe NAT is active */
01550    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01551       nat_active = 1;
01552    /* Bridge media early */
01553    if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active))
01554       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>");
01555    ast_channel_unlock(dest);
01556    if (src)
01557       ast_channel_unlock(src);
01558    if (option_debug)
01559       ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>");
01560    return 1;
01561 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 513 of file rtp.c.

References ast_rtp::s.

Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().

00514 {
00515    return rtp->s;
00516 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  )  [read]

Definition at line 2034 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.

Referenced by __sip_destroy(), and ast_rtp_read().

02035 {
02036    struct ast_rtp *bridged = NULL;
02037 
02038    ast_mutex_lock(&rtp->bridge_lock);
02039    bridged = rtp->bridged;
02040    ast_mutex_unlock(&rtp->bridge_lock);
02041 
02042    return bridged;
02043 }

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

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

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

01699 {
01700    int pt;
01701    
01702    ast_mutex_lock(&rtp->bridge_lock);
01703    
01704    *astFormats = *nonAstFormats = 0;
01705    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01706       if (rtp->current_RTP_PT[pt].isAstFormat) {
01707          *astFormats |= rtp->current_RTP_PT[pt].code;
01708       } else {
01709          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01710       }
01711    }
01712    
01713    ast_mutex_unlock(&rtp->bridge_lock);
01714    
01715    return;
01716 }

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

Definition at line 2016 of file rtp.c.

References ast_rtp::them.

Referenced by add_sdp(), bridge_native_loop(), do_monitor(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), and transmit_modify_with_sdp().

02017 {
02018    if ((them->sin_family != AF_INET) ||
02019       (them->sin_port != rtp->them.sin_port) ||
02020       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02021       them->sin_family = AF_INET;
02022       them->sin_port = rtp->them.sin_port;
02023       them->sin_addr = rtp->them.sin_addr;
02024       return 1;
02025    }
02026    return 0;
02027 }

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

Return RTCP quality string.

Definition at line 2079 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_rtcp::rtt, ast_rtp_quality::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by acf_channel_read(), handle_request_bye(), and sip_hangup().

02080 {
02081    /*
02082    *ssrc          our ssrc
02083    *themssrc      their ssrc
02084    *lp            lost packets
02085    *rxjitter      our calculated jitter(rx)
02086    *rxcount       no. received packets
02087    *txjitter      reported jitter of the other end
02088    *txcount       transmitted packets
02089    *rlp           remote lost packets
02090    *rtt           round trip time
02091    */
02092 
02093    if (qual && rtp) {
02094       qual->local_ssrc = rtp->ssrc;
02095       qual->local_jitter = rtp->rxjitter;
02096       qual->local_count = rtp->rxcount;
02097       qual->remote_ssrc = rtp->themssrc;
02098       qual->remote_count = rtp->txcount;
02099       if (rtp->rtcp) {
02100          qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02101          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02102          qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02103          qual->rtt = rtp->rtcp->rtt;
02104       }
02105    }
02106    if (rtp->rtcp) {
02107       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02108          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02109          rtp->ssrc,
02110          rtp->themssrc,
02111          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02112          rtp->rxjitter,
02113          rtp->rxcount,
02114          (double)rtp->rtcp->reported_jitter / 65536.0,
02115          rtp->txcount,
02116          rtp->rtcp->reported_lost,
02117          rtp->rtcp->rtt);
02118       return rtp->rtcp->quality;
02119    } else
02120       return "<Unknown> - RTP/RTCP has already been destroyed";
02121 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 568 of file rtp.c.

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

Referenced by do_monitor().

00569 {
00570    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00571       return 0;
00572    return rtp->rtpholdtimeout;
00573 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 576 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00577 {
00578    return rtp->rtpkeepalive;
00579 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 560 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

00561 {
00562    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00563       return 0;
00564    return rtp->rtptimeout;
00565 }

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

Definition at line 2029 of file rtp.c.

References ast_rtp::us.

Referenced by add_sdp(), external_rtp_create(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), and oh323_set_rtp_peer().

02030 {
02031    *us = rtp->us;
02032 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 596 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00597 {
00598    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00599 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3816 of file rtp.c.

References ast_cli_register_multiple(), and ast_rtp_reload().

Referenced by main().

03817 {
03818    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03819    ast_rtp_reload();
03820 }

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

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), and bridge_p2p_rtp_write().

01741 {
01742    int pt = 0;
01743 
01744    ast_mutex_lock(&rtp->bridge_lock);
01745 
01746    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
01747       code == rtp->rtp_lookup_code_cache_code) {
01748       /* Use our cached mapping, to avoid the overhead of the loop below */
01749       pt = rtp->rtp_lookup_code_cache_result;
01750       ast_mutex_unlock(&rtp->bridge_lock);
01751       return pt;
01752    }
01753 
01754    /* Check the dynamic list first */
01755    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01756       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
01757          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01758          rtp->rtp_lookup_code_cache_code = code;
01759          rtp->rtp_lookup_code_cache_result = pt;
01760          ast_mutex_unlock(&rtp->bridge_lock);
01761          return pt;
01762       }
01763    }
01764 
01765    /* Then the static list */
01766    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01767       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
01768          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01769          rtp->rtp_lookup_code_cache_code = code;
01770          rtp->rtp_lookup_code_cache_result = pt;
01771          ast_mutex_unlock(&rtp->bridge_lock);
01772          return pt;
01773       }
01774    }
01775 
01776    ast_mutex_unlock(&rtp->bridge_lock);
01777 
01778    return -1;
01779 }

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

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

Referenced by process_sdp().

01802 {
01803    int format;
01804    unsigned len;
01805    char *end = buf;
01806    char *start = buf;
01807 
01808    if (!buf || !size)
01809       return NULL;
01810 
01811    snprintf(end, size, "0x%x (", capability);
01812 
01813    len = strlen(end);
01814    end += len;
01815    size -= len;
01816    start = end;
01817 
01818    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01819       if (capability & format) {
01820          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01821 
01822          snprintf(end, size, "%s|", name);
01823          len = strlen(end);
01824          end += len;
01825          size -= len;
01826       }
01827    }
01828 
01829    if (start == end)
01830       snprintf(start, size, "nothing)"); 
01831    else if (size > 1)
01832       *(end -1) = ')';
01833    
01834    return buf;
01835 }

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

References 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(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().

01783 {
01784    unsigned int i;
01785 
01786    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01787       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01788          if (isAstFormat &&
01789              (code == AST_FORMAT_G726_AAL2) &&
01790              (options & AST_RTP_OPT_G726_NONSTANDARD))
01791             return "G726-32";
01792          else
01793             return mimeTypes[i].subtype;
01794       }
01795    }
01796 
01797    return "";
01798 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
) [read]

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1718 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

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

01719 {
01720    struct rtpPayloadType result;
01721 
01722    result.isAstFormat = result.code = 0;
01723 
01724    if (pt < 0 || pt > MAX_RTP_PT) 
01725       return result; /* bogus payload type */
01726 
01727    /* Start with negotiated codecs */
01728    ast_mutex_lock(&rtp->bridge_lock);
01729    result = rtp->current_RTP_PT[pt];
01730    ast_mutex_unlock(&rtp->bridge_lock);
01731 
01732    /* If it doesn't exist, check our static RTP type list, just in case */
01733    if (!result.code) 
01734       result = static_RTP_PT[pt];
01735 
01736    return result;
01737 }

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

Definition at line 1563 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, 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_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.

Referenced by wait_for_answer().

01564 {
01565    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01566    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01567    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01568    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01569    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 
01570    int srccodec, destcodec;
01571 
01572    /* Lock channels */
01573    ast_channel_lock(dest);
01574    while(ast_channel_trylock(src)) {
01575       ast_channel_unlock(dest);
01576       usleep(1);
01577       ast_channel_lock(dest);
01578    }
01579 
01580    /* Find channel driver interfaces */
01581    if (!(destpr = get_proto(dest))) {
01582       if (option_debug)
01583          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01584       ast_channel_unlock(dest);
01585       ast_channel_unlock(src);
01586       return 0;
01587    }
01588    if (!(srcpr = get_proto(src))) {
01589       if (option_debug)
01590          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
01591       ast_channel_unlock(dest);
01592       ast_channel_unlock(src);
01593       return 0;
01594    }
01595 
01596    /* Get audio and video interface (if native bridge is possible) */
01597    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01598    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01599    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01600    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01601 
01602    /* Ensure we have at least one matching codec */
01603    if (srcpr->get_codec)
01604       srccodec = srcpr->get_codec(src);
01605    else
01606       srccodec = 0;
01607    if (destpr->get_codec)
01608       destcodec = destpr->get_codec(dest);
01609    else
01610       destcodec = 0;
01611 
01612    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01613    if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) {
01614       /* Somebody doesn't want to play... */
01615       ast_channel_unlock(dest);
01616       ast_channel_unlock(src);
01617       return 0;
01618    }
01619    ast_rtp_pt_copy(destp, srcp);
01620    if (vdestp && vsrcp)
01621       ast_rtp_pt_copy(vdestp, vsrcp);
01622    if (media) {
01623       /* Bridge early */
01624       if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01625          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
01626    }
01627    ast_channel_unlock(dest);
01628    ast_channel_unlock(src);
01629    if (option_debug)
01630       ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
01631    return 1;
01632 }

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

Initializate a RTP session.

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

Definition at line 1982 of file rtp.c.

References ast_rtp_new_with_bindaddr().

01983 {
01984    struct in_addr ia;
01985 
01986    memset(&ia, 0, sizeof(ia));
01987    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01988 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

Definition at line 1882 of file rtp.c.

References ast_mutex_init(), ast_random(), ast_set_flag, ast_rtp::bridge_lock, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, and ast_rtp::us.

Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().

01883 {
01884    ast_mutex_init(&rtp->bridge_lock);
01885 
01886    rtp->them.sin_family = AF_INET;
01887    rtp->us.sin_family = AF_INET;
01888    rtp->ssrc = ast_random();
01889    rtp->seqno = ast_random() & 0xffff;
01890    ast_set_flag(rtp, FLAG_HAS_DTMF);
01891 
01892    return;
01893 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 1999 of file rtp.c.

References ast_rtp::set_marker_bit.

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

02000 {
02001    rtp->set_marker_bit = 1;
02002    return;
02003 }

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

Initializate a RTP session using an in_addr structure.

This fuction gets called by ast_rtp_new().

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

Definition at line 1895 of file rtp.c.

References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, errno, FLAG_CALLBACK_MODE, free, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::us, and ast_rtp::us.

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

01896 {
01897    struct ast_rtp *rtp;
01898    int x;
01899    int first;
01900    int startplace;
01901    
01902    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
01903       return NULL;
01904 
01905    ast_rtp_new_init(rtp);
01906 
01907    rtp->s = rtp_socket();
01908    if (rtp->s < 0) {
01909       free(rtp);
01910       ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
01911       return NULL;
01912    }
01913    if (sched && rtcpenable) {
01914       rtp->sched = sched;
01915       rtp->rtcp = ast_rtcp_new();
01916    }
01917    
01918    /* Select a random port number in the range of possible RTP */
01919    x = (ast_random() % (rtpend-rtpstart)) + rtpstart;
01920    x = x & ~1;
01921    /* Save it for future references. */
01922    startplace = x;
01923    /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
01924    for (;;) {
01925       /* Must be an even port number by RTP spec */
01926       rtp->us.sin_port = htons(x);
01927       rtp->us.sin_addr = addr;
01928       /* If there's rtcp, initialize it as well. */
01929       if (rtp->rtcp) {
01930          rtp->rtcp->us.sin_port = htons(x + 1);
01931          rtp->rtcp->us.sin_addr = addr;
01932       }
01933       /* Try to bind it/them. */
01934       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
01935          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
01936          break;
01937       if (!first) {
01938          /* Primary bind succeeded! Gotta recreate it */
01939          close(rtp->s);
01940          rtp->s = rtp_socket();
01941       }
01942       if (errno != EADDRINUSE) {
01943          /* We got an error that wasn't expected, abort! */
01944          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
01945          close(rtp->s);
01946          if (rtp->rtcp) {
01947             close(rtp->rtcp->s);
01948             free(rtp->rtcp);
01949          }
01950          free(rtp);
01951          return NULL;
01952       }
01953       /* The port was used, increment it (by two). */
01954       x += 2;
01955       /* Did we go over the limit ? */
01956       if (x > rtpend)
01957          /* then, start from the begingig. */
01958          x = (rtpstart + 1) & ~1;
01959       /* Check if we reached the place were we started. */
01960       if (x == startplace) {
01961          /* If so, there's no ports available. */
01962          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
01963          close(rtp->s);
01964          if (rtp->rtcp) {
01965             close(rtp->rtcp->s);
01966             free(rtp->rtcp);
01967          }
01968          free(rtp);
01969          return NULL;
01970       }
01971    }
01972    rtp->sched = sched;
01973    rtp->io = io;
01974    if (callbackmode) {
01975       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
01976       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
01977    }
01978    ast_rtp_pt_default(rtp);
01979    return rtp;
01980 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Definition at line 2833 of file rtp.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, protos, and ast_rtp_protocol::type.

Referenced by load_module().

02834 {
02835    struct ast_rtp_protocol *cur;
02836 
02837    AST_LIST_LOCK(&protos);
02838    AST_LIST_TRAVERSE(&protos, cur, list) {   
02839       if (!strcmp(cur->type, proto->type)) {
02840          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02841          AST_LIST_UNLOCK(&protos);
02842          return -1;
02843       }
02844    }
02845    AST_LIST_INSERT_HEAD(&protos, proto, list);
02846    AST_LIST_UNLOCK(&protos);
02847    
02848    return 0;
02849 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2825 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.

Referenced by load_module(), and unload_module().

02826 {
02827    AST_LIST_LOCK(&protos);
02828    AST_LIST_REMOVE(&protos, proto, list);
02829    AST_LIST_UNLOCK(&protos);
02830 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 1399 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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().

01400 {
01401    int i;
01402 
01403    if (!rtp)
01404       return;
01405 
01406    ast_mutex_lock(&rtp->bridge_lock);
01407 
01408    for (i = 0; i < MAX_RTP_PT; ++i) {
01409       rtp->current_RTP_PT[i].isAstFormat = 0;
01410       rtp->current_RTP_PT[i].code = 0;
01411    }
01412 
01413    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01414    rtp->rtp_lookup_code_cache_code = 0;
01415    rtp->rtp_lookup_code_cache_result = 0;
01416 
01417    ast_mutex_unlock(&rtp->bridge_lock);
01418 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

Definition at line 1439 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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().

01440 {
01441    unsigned int i;
01442 
01443    ast_mutex_lock(&dest->bridge_lock);
01444    ast_mutex_lock(&src->bridge_lock);
01445 
01446    for (i=0; i < MAX_RTP_PT; ++i) {
01447       dest->current_RTP_PT[i].isAstFormat = 
01448          src->current_RTP_PT[i].isAstFormat;
01449       dest->current_RTP_PT[i].code = 
01450          src->current_RTP_PT[i].code; 
01451    }
01452    dest->rtp_lookup_code_cache_isAstFormat = 0;
01453    dest->rtp_lookup_code_cache_code = 0;
01454    dest->rtp_lookup_code_cache_result = 0;
01455 
01456    ast_mutex_unlock(&src->bridge_lock);
01457    ast_mutex_unlock(&dest->bridge_lock);
01458 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 1420 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by ast_rtp_new_with_bindaddr().

01421 {
01422    int i;
01423 
01424    ast_mutex_lock(&rtp->bridge_lock);
01425 
01426    /* Initialize to default payload types */
01427    for (i = 0; i < MAX_RTP_PT; ++i) {
01428       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01429       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01430    }
01431 
01432    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01433    rtp->rtp_lookup_code_cache_code = 0;
01434    rtp->rtp_lookup_code_cache_result = 0;
01435 
01436    ast_mutex_unlock(&rtp->bridge_lock);
01437 }

static int ast_rtp_raw_write ( struct ast_rtp rtp,
struct ast_frame f,
int  codec 
) [static]

Definition at line 2608 of file rtp.c.

References AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_frame::frametype, ast_rtp::lastdigitts, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_DEBUG, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seqno, ast_rtp::set_marker_bit, ast_rtp::ssrc, ast_frame::subclass, ast_rtp::them, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

02609 {
02610    unsigned char *rtpheader;
02611    int hdrlen = 12;
02612    int res;
02613    unsigned int ms;
02614    int pred;
02615    int mark = 0;
02616 
02617    ms = calc_txstamp(rtp, &f->delivery);
02618    /* Default prediction */
02619    if (f->frametype == AST_FRAME_VOICE) {
02620       pred = rtp->lastts + f->samples;
02621 
02622       /* Re-calculate last TS */
02623       rtp->lastts = rtp->lastts + ms * 8;
02624       if (ast_tvzero(f->delivery)) {
02625          /* If this isn't an absolute delivery time, Check if it is close to our prediction, 
02626             and if so, go with our prediction */
02627          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
02628             rtp->lastts = pred;
02629          else {
02630             if (option_debug > 2)
02631                ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
02632             mark = 1;
02633          }
02634       }
02635    } else if (f->frametype == AST_FRAME_VIDEO) {
02636       mark = f->subclass & 0x1;
02637       pred = rtp->lastovidtimestamp + f->samples;
02638       /* Re-calculate last TS */
02639       rtp->lastts = rtp->lastts + ms * 90;
02640       /* If it's close to our prediction, go for it */
02641       if (ast_tvzero(f->delivery)) {
02642          if (abs(rtp->lastts - pred) < 7200) {
02643             rtp->lastts = pred;
02644             rtp->lastovidtimestamp += f->samples;
02645          } else {
02646             if (option_debug > 2)
02647                ast_log(LOG_DEBUG, "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);
02648             rtp->lastovidtimestamp = rtp->lastts;
02649          }
02650       }
02651    }
02652 
02653    /* If we have been explicitly told to set the marker bit do so */
02654    if (rtp->set_marker_bit) {
02655       mark = 1;
02656       rtp->set_marker_bit = 0;
02657    }
02658 
02659    /* If the timestamp for non-digit packets has moved beyond the timestamp
02660       for digits, update the digit timestamp.
02661    */
02662    if (rtp->lastts > rtp->lastdigitts)
02663       rtp->lastdigitts = rtp->lastts;
02664 
02665    if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
02666       rtp->lastts = f->ts * 8;
02667 
02668    /* Get a pointer to the header */
02669    rtpheader = (unsigned char *)(f->data - hdrlen);
02670 
02671    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
02672    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
02673    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
02674 
02675    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02676       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02677       if (res <0) {
02678          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
02679             ast_log(LOG_DEBUG, "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));
02680          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
02681             /* Only give this error message once if we are not RTP debugging */
02682             if (option_debug || rtpdebug)
02683                ast_log(LOG_DEBUG, "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));
02684             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
02685          }
02686       } else {
02687          rtp->txcount++;
02688          rtp->txoctetcount +=(res - hdrlen);
02689          
02690          if (rtp->rtcp && rtp->rtcp->schedid < 1) 
02691              rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
02692       }
02693             
02694       if (rtp_debug_test_addr(&rtp->them))
02695          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02696                ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
02697    }
02698 
02699    rtp->seqno++;
02700 
02701    return 0;
02702 }

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

Definition at line 1104 of file rtp.c.

References ast_assert, ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, event, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, len, LOG_DEBUG, 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::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, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtcp::them, ast_rtp::them, ast_rtp::themssrc, and ast_frame::ts.

Referenced by gtalk_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().

01105 {
01106    int res;
01107    struct sockaddr_in sin;
01108    socklen_t len;
01109    unsigned int seqno;
01110    int version;
01111    int payloadtype;
01112    int hdrlen = 12;
01113    int padding;
01114    int mark;
01115    int ext;
01116    int cc;
01117    unsigned int ssrc;
01118    unsigned int timestamp;
01119    unsigned int *rtpheader;
01120    struct rtpPayloadType rtpPT;
01121    struct ast_rtp *bridged = NULL;
01122    
01123    /* If time is up, kill it */
01124    if (rtp->sending_digit)
01125       ast_rtp_senddigit_continuation(rtp);
01126 
01127    len = sizeof(sin);
01128    
01129    /* Cache where the header will go */
01130    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
01131                0, (struct sockaddr *)&sin, &len);
01132 
01133    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
01134    if (res < 0) {
01135       ast_assert(errno != EBADF);
01136       if (errno != EAGAIN) {
01137          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up.\n", strerror(errno));
01138          return NULL;
01139       }
01140       return &ast_null_frame;
01141    }
01142    
01143    if (res < hdrlen) {
01144       ast_log(LOG_WARNING, "RTP Read too short\n");
01145       return &ast_null_frame;
01146    }
01147 
01148    /* Get fields */
01149    seqno = ntohl(rtpheader[0]);
01150 
01151    /* Check RTP version */
01152    version = (seqno & 0xC0000000) >> 30;
01153    if (!version) {
01154       if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) &&
01155          (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
01156          memcpy(&rtp->them, &sin, sizeof(rtp->them));
01157       }
01158       return &ast_null_frame;
01159    }
01160 
01161 #if 0 /* Allow to receive RTP stream with closed transmission path */
01162    /* If we don't have the other side's address, then ignore this */
01163    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
01164       return &ast_null_frame;
01165 #endif
01166 
01167    /* Send to whoever send to us if NAT is turned on */
01168    if (rtp->nat) {
01169       if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01170           (rtp->them.sin_port != sin.sin_port)) {
01171          rtp->them = sin;
01172          if (rtp->rtcp) {
01173             memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01174             rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1);
01175          }
01176          rtp->rxseqno = 0;
01177          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01178          if (option_debug || rtpdebug)
01179             ast_log(LOG_DEBUG, "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));
01180       }
01181    }
01182 
01183    /* If we are bridged to another RTP stream, send direct */
01184    if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
01185       return &ast_null_frame;
01186 
01187    if (version != 2)
01188       return &ast_null_frame;
01189 
01190    payloadtype = (seqno & 0x7f0000) >> 16;
01191    padding = seqno & (1 << 29);
01192    mark = seqno & (1 << 23);
01193    ext = seqno & (1 << 28);
01194    cc = (seqno & 0xF000000) >> 24;
01195    seqno &= 0xffff;
01196    timestamp = ntohl(rtpheader[1]);
01197    ssrc = ntohl(rtpheader[2]);
01198    
01199    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
01200       if (option_debug || rtpdebug)
01201          ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n");
01202       mark = 1;
01203    }
01204 
01205    rtp->rxssrc = ssrc;
01206    
01207    if (padding) {
01208       /* Remove padding bytes */
01209       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01210    }
01211    
01212    if (cc) {
01213       /* CSRC fields present */
01214       hdrlen += cc*4;
01215    }
01216 
01217    if (ext) {
01218       /* RTP Extension present */
01219       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
01220       hdrlen += 4;
01221    }
01222 
01223    if (res < hdrlen) {
01224       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
01225       return &ast_null_frame;
01226    }
01227 
01228    rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
01229 
01230    if (rtp->rxcount==1) {
01231       /* This is the first RTP packet successfully received from source */
01232       rtp->seedrxseqno = seqno;
01233    }
01234 
01235    /* Do not schedule RR if RTCP isn't run */
01236    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
01237       /* Schedule transmission of Receiver Report */
01238       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01239    }
01240    if ( (int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
01241       rtp->cycles += RTP_SEQ_MOD;
01242 
01243    rtp->lastrxseqno = seqno;
01244    
01245    if (rtp->themssrc==0)
01246       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
01247    
01248    if (rtp_debug_test_addr(&sin))
01249       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01250          ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
01251 
01252    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
01253    if (!rtpPT.isAstFormat) {
01254       struct ast_frame *f = NULL;
01255 
01256       /* This is special in-band data that's not one of our codecs */
01257       if (rtpPT.code == AST_RTP_DTMF) {
01258          /* It's special -- rfc2833 process it */
01259          if (rtp_debug_test_addr(&sin)) {
01260             unsigned char *data;
01261             unsigned int event;
01262             unsigned int event_end;
01263             unsigned int duration;
01264             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
01265             event = ntohl(*((unsigned int *)(data)));
01266             event >>= 24;
01267             event_end = ntohl(*((unsigned int *)(data)));
01268             event_end <<= 8;
01269             event_end >>= 24;
01270             duration = ntohl(*((unsigned int *)(data)));
01271             duration &= 0xFFFF;
01272             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);
01273          }
01274          f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
01275       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
01276          /* It's really special -- process it the Cisco way */
01277          if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
01278             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01279             rtp->lastevent = seqno;
01280          }
01281       } else if (rtpPT.code == AST_RTP_CN) {
01282          /* Comfort Noise */
01283          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01284       } else {
01285          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
01286       }
01287       return f ? f : &ast_null_frame;
01288    }
01289    rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
01290    rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO;
01291 
01292    if (!rtp->lastrxts)
01293       rtp->lastrxts = timestamp;
01294 
01295    rtp->rxseqno = seqno;
01296 
01297    /* Record received timestamp as last received now */
01298    rtp->lastrxts = timestamp;
01299 
01300    rtp->f.mallocd = 0;
01301    rtp->f.datalen = res - hdrlen;
01302    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
01303    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
01304    rtp->f.seqno = seqno;
01305    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
01306       rtp->f.samples = ast_codec_get_samples(&rtp->f);
01307       if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
01308          ast_frame_byteswap_be(&rtp->f);
01309       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
01310       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
01311       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
01312       rtp->f.ts = timestamp / 8;
01313       rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000);
01314    } else {
01315       /* Video -- samples is # of samples vs. 90000 */
01316       if (!rtp->lastividtimestamp)
01317          rtp->lastividtimestamp = timestamp;
01318       rtp->f.samples = timestamp - rtp->lastividtimestamp;
01319       rtp->lastividtimestamp = timestamp;
01320       rtp->f.delivery.tv_sec = 0;
01321       rtp->f.delivery.tv_usec = 0;
01322       if (mark)
01323          rtp->f.subclass |= 0x1;
01324       
01325    }
01326    rtp->f.src = "RTP";
01327    return &rtp->f;
01328 }

int ast_rtp_reload ( void   ) 

Definition at line 3751 of file rtp.c.

References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and VERBOSE_PREFIX_2.

Referenced by ast_rtp_init().

03752 {
03753    struct ast_config *cfg;
03754    const char *s;
03755 
03756    rtpstart = 5000;
03757    rtpend = 31000;
03758    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03759    cfg = ast_config_load("rtp.conf");
03760    if (cfg) {
03761       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03762          rtpstart = atoi(s);
03763          if (rtpstart < 1024)
03764             rtpstart = 1024;
03765          if (rtpstart > 65535)
03766             rtpstart = 65535;
03767       }
03768       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03769          rtpend = atoi(s);
03770          if (rtpend < 1024)
03771             rtpend = 1024;
03772          if (rtpend > 65535)
03773             rtpend = 65535;
03774       }
03775       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03776          rtcpinterval = atoi(s);
03777          if (rtcpinterval == 0)
03778             rtcpinterval = 0; /* Just so we're clear... it's zero */
03779          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03780             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03781          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03782             rtcpinterval = RTCP_MAX_INTERVALMS;
03783       }
03784       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03785 #ifdef SO_NO_CHECK
03786          if (ast_false(s))
03787             nochecksums = 1;
03788          else
03789             nochecksums = 0;
03790 #else
03791          if (ast_false(s))
03792             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03793 #endif
03794       }
03795       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03796          dtmftimeout = atoi(s);
03797          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03798             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03799                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03800             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03801          };
03802       }
03803       ast_config_destroy(cfg);
03804    }
03805    if (rtpstart >= rtpend) {
03806       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03807       rtpstart = 5000;
03808       rtpend = 31000;
03809    }
03810    if (option_verbose > 1)
03811       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03812    return 0;
03813 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2059 of file rtp.c.

References ast_rtp::dtmfcount, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, 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.

02060 {
02061    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02062    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02063    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02064    rtp->lastts = 0;
02065    rtp->lastdigitts = 0;
02066    rtp->lastrxts = 0;
02067    rtp->lastividtimestamp = 0;
02068    rtp->lastovidtimestamp = 0;
02069    rtp->lasteventseqn = 0;
02070    rtp->lastevent = 0;
02071    rtp->lasttxformat = 0;
02072    rtp->lastrxformat = 0;
02073    rtp->dtmfcount = 0;
02074    rtp->dtmfsamples = 0;
02075    rtp->seqno = 0;
02076    rtp->rxseqno = 0;
02077 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2574 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), 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 do_monitor().

02575 {
02576    unsigned int *rtpheader;
02577    int hdrlen = 12;
02578    int res;
02579    int payload;
02580    char data[256];
02581    level = 127 - (level & 0x7f);
02582    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
02583 
02584    /* If we have no peer, return immediately */ 
02585    if (!rtp->them.sin_addr.s_addr)
02586       return 0;
02587 
02588    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02589 
02590    /* Get a pointer to the header */
02591    rtpheader = (unsigned int *)data;
02592    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02593    rtpheader[1] = htonl(rtp->lastts);
02594    rtpheader[2] = htonl(rtp->ssrc); 
02595    data[12] = level;
02596    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02597       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02598       if (res <0) 
02599          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));
02600       if (rtp_debug_test_addr(&rtp->them))
02601          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
02602                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
02603          
02604    }
02605    return 0;
02606 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2182 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, 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().

02183 {
02184    unsigned int *rtpheader;
02185    int hdrlen = 12, res = 0, i = 0, payload = 0;
02186    char data[256];
02187 
02188    if ((digit <= '9') && (digit >= '0'))
02189       digit -= '0';
02190    else if (digit == '*')
02191       digit = 10;
02192    else if (digit == '#')
02193       digit = 11;
02194    else if ((digit >= 'A') && (digit <= 'D'))
02195       digit = digit - 'A' + 12;
02196    else if ((digit >= 'a') && (digit <= 'd'))
02197       digit = digit - 'a' + 12;
02198    else {
02199       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02200       return 0;
02201    }
02202 
02203    /* If we have no peer, return immediately */ 
02204    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02205       return 0;
02206 
02207    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02208 
02209    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02210    rtp->send_duration = 160;
02211    
02212    /* Get a pointer to the header */
02213    rtpheader = (unsigned int *)data;
02214    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02215    rtpheader[1] = htonl(rtp->lastdigitts);
02216    rtpheader[2] = htonl(rtp->ssrc); 
02217 
02218    for (i = 0; i < 2; i++) {
02219       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02220       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02221       if (res < 0) 
02222          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02223             ast_inet_ntoa(rtp->them.sin_addr),
02224             ntohs(rtp->them.sin_port), strerror(errno));
02225       if (rtp_debug_test_addr(&rtp->them))
02226          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02227                 ast_inet_ntoa(rtp->them.sin_addr),
02228                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02229       /* Increment sequence number */
02230       rtp->seqno++;
02231       /* Increment duration */
02232       rtp->send_duration += 160;
02233       /* Clear marker bit and set seqno */
02234       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02235    }
02236 
02237    /* Since we received a begin, we can safely store the digit and disable any compensation */
02238    rtp->sending_digit = 1;
02239    rtp->send_digit = digit;
02240    rtp->send_payload = payload;
02241 
02242    return 0;
02243 }

static int ast_rtp_senddigit_continuation ( struct ast_rtp rtp  )  [static]

Send continuation frame for DTMF.

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

02247 {
02248    unsigned int *rtpheader;
02249    int hdrlen = 12, res = 0;
02250    char data[256];
02251 
02252    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02253       return 0;
02254 
02255    /* Setup packet to send */
02256    rtpheader = (unsigned int *)data;
02257         rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02258         rtpheader[1] = htonl(rtp->lastdigitts);
02259         rtpheader[2] = htonl(rtp->ssrc);
02260         rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
02261    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02262    
02263    /* Transmit */
02264    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02265    if (res < 0)
02266       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02267          ast_inet_ntoa(rtp->them.sin_addr),
02268          ntohs(rtp->them.sin_port), strerror(errno));
02269    if (rtp_debug_test_addr(&rtp->them))
02270       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02271              ast_inet_ntoa(rtp->them.sin_addr),
02272              ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02273 
02274    /* Increment sequence number */
02275    rtp->seqno++;
02276    /* Increment duration */
02277    rtp->send_duration += 160;
02278 
02279    return 0;
02280 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 2283 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, 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().

02284 {
02285    unsigned int *rtpheader;
02286    int hdrlen = 12, res = 0, i = 0;
02287    char data[256];
02288    
02289    /* If no address, then bail out */
02290    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02291       return 0;
02292    
02293    if ((digit <= '9') && (digit >= '0'))
02294       digit -= '0';
02295    else if (digit == '*')
02296       digit = 10;
02297    else if (digit == '#')
02298       digit = 11;
02299    else if ((digit >= 'A') && (digit <= 'D'))
02300       digit = digit - 'A' + 12;
02301    else if ((digit >= 'a') && (digit <= 'd'))
02302       digit = digit - 'a' + 12;
02303    else {
02304       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02305       return 0;
02306    }
02307 
02308    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02309 
02310    rtpheader = (unsigned int *)data;
02311    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
02312    rtpheader[1] = htonl(rtp->lastdigitts);
02313    rtpheader[2] = htonl(rtp->ssrc);
02314    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02315    /* Set end bit */
02316    rtpheader[3] |= htonl((1 << 23));
02317    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
02318    /* Send 3 termination packets */
02319    for (i = 0; i < 3; i++) {
02320       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02321       if (res < 0)
02322          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
02323             ast_inet_ntoa(rtp->them.sin_addr),
02324             ntohs(rtp->them.sin_port), strerror(errno));
02325       if (rtp_debug_test_addr(&rtp->them))
02326          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02327                 ast_inet_ntoa(rtp->them.sin_addr),
02328                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02329    }
02330    rtp->sending_digit = 0;
02331    rtp->send_digit = 0;
02332    /* Increment lastdigitts */
02333    rtp->lastdigitts += 960;
02334    rtp->seqno++;
02335 
02336    return res;
02337 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 586 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00587 {
00588    rtp->callback = callback;
00589 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 581 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00582 {
00583    rtp->data = data;
00584 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).

Activate payload type.

Definition at line 1638 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, ast_rtp::current_RTP_PT, and MAX_RTP_PT.

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

01639 {
01640    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01641       return; /* bogus payload type */
01642 
01643    ast_mutex_lock(&rtp->bridge_lock);
01644    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01645    ast_mutex_unlock(&rtp->bridge_lock);
01646 } 

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

Definition at line 2005 of file rtp.c.

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

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

02006 {
02007    rtp->them.sin_port = them->sin_port;
02008    rtp->them.sin_addr = them->sin_addr;
02009    if (rtp->rtcp) {
02010       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02011       rtp->rtcp->them.sin_addr = them->sin_addr;
02012    }
02013    rtp->rxseqno = 0;
02014 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 548 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00549 {
00550    rtp->rtpholdtimeout = timeout;
00551 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 554 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00555 {
00556    rtp->rtpkeepalive = period;
00557 }

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

Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.

Initiate payload type to a known MIME media type for a codec.

Returns:
0 if the MIME type was found and set, -1 if it wasn't found

Definition at line 1665 of file rtp.c.

References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, subtype, and type.

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

01668 {
01669    unsigned int i;
01670    int found = 0;
01671 
01672    if (pt < 0 || pt > MAX_RTP_PT) 
01673       return -1; /* bogus payload type */
01674    
01675    ast_mutex_lock(&rtp->bridge_lock);
01676 
01677    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01678       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01679           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01680          found = 1;
01681          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01682          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01683              mimeTypes[i].payloadType.isAstFormat &&
01684              (options & AST_RTP_OPT_G726_NONSTANDARD))
01685             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01686          break;
01687       }
01688    }
01689 
01690    ast_mutex_unlock(&rtp->bridge_lock);
01691 
01692    return (found ? 0 : -1);
01693 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 542 of file rtp.c.

References ast_rtp::rtptimeout.

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

00543 {
00544    rtp->rtptimeout = timeout;
00545 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 535 of file rtp.c.

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

Referenced by handle_response_invite().

00536 {
00537    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00538    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00539 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00602 {
00603    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00604 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00607 {
00608    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00609 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 591 of file rtp.c.

References ast_rtp::nat.

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

00592 {
00593    rtp->nat = nat;
00594 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 611 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00612 {
00613    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00614 }

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 1990 of file rtp.c.

References ast_log(), LOG_WARNING, and ast_rtp::s.

Referenced by __oh323_rtp_create(), and sip_alloc().

01991 {
01992    int res;
01993 
01994    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
01995       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01996    return res;
01997 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Definition at line 2045 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_rtcp::them, and ast_rtp::them.

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

02046 {
02047    AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02048 
02049    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02050    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02051    if (rtp->rtcp) {
02052       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02053       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02054    }
02055    
02056    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02057 }

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

Definition at line 403 of file rtp.c.

References append_attr_string(), stun_attr::attr, stun_header::ies, stun_header::msglen, stun_header::msgtype, ast_rtp::s, STUN_BINDREQ, stun_req_id(), stun_send(), and STUN_USERNAME.

Referenced by gtalk_update_stun().

00404 {
00405    struct stun_header *req;
00406    unsigned char reqdata[1024];
00407    int reqlen, reqleft;
00408    struct stun_attr *attr;
00409 
00410    req = (struct stun_header *)reqdata;
00411    stun_req_id(req);
00412    reqlen = 0;
00413    reqleft = sizeof(reqdata) - sizeof(struct stun_header);
00414    req->msgtype = 0;
00415    req->msglen = 0;
00416    attr = (struct stun_attr *)req->ies;
00417    if (username)
00418       append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00419    req->msglen = htons(reqlen);
00420    req->msgtype = htons(STUN_BINDREQ);
00421    stun_send(rtp->s, suggestion, req);
00422 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

remove setting from payload type list if the rtpmap header indicates an unknown media type

clear payload type

Definition at line 1650 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by process_sdp().

01651 {
01652    if (pt < 0 || pt > MAX_RTP_PT)
01653       return; /* bogus payload type */
01654 
01655    ast_mutex_lock(&rtp->bridge_lock);
01656    rtp->current_RTP_PT[pt].isAstFormat = 0;
01657    rtp->current_RTP_PT[pt].code = 0;
01658    ast_mutex_unlock(&rtp->bridge_lock);
01659 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

Definition at line 2733 of file rtp.c.

References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_frame::samples, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

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

02734 {
02735    struct ast_frame *f;
02736    int codec;
02737    int hdrlen = 12;
02738    int subclass;
02739    
02740 
02741    /* If we have no peer, return immediately */ 
02742    if (!rtp->them.sin_addr.s_addr)
02743       return 0;
02744 
02745    /* If there is no data length, return immediately */
02746    if (!_f->datalen) 
02747       return 0;
02748    
02749    /* Make sure we have enough space for RTP header */
02750    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02751       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02752       return -1;
02753    }
02754 
02755    subclass = _f->subclass;
02756    if (_f->frametype == AST_FRAME_VIDEO)
02757       subclass &= ~0x1;
02758 
02759    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02760    if (codec < 0) {
02761       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02762       return -1;
02763    }
02764 
02765    if (rtp->lasttxformat != subclass) {
02766       /* New format, reset the smoother */
02767       if (option_debug)
02768          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02769       rtp->lasttxformat = subclass;
02770       if (rtp->smoother)
02771          ast_smoother_free(rtp->smoother);
02772       rtp->smoother = NULL;
02773    }
02774 
02775    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
02776       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02777       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02778          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02779             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));
02780             return -1;
02781          }
02782          if (fmt.flags)
02783             ast_smoother_set_flags(rtp->smoother, fmt.flags);
02784          if (option_debug)
02785             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
02786       }
02787    }
02788    if (rtp->smoother) {
02789       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
02790          ast_smoother_feed_be(rtp->smoother, _f);
02791       } else {
02792          ast_smoother_feed(rtp->smoother, _f);
02793       }
02794 
02795       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
02796          if (f->subclass == AST_FORMAT_G722) {
02797             /* G.722 is silllllllllllllly */
02798             f->samples /= 2;
02799          }
02800 
02801          ast_rtp_raw_write(rtp, f, codec);
02802       }
02803    } else {
02804       /* Don't buffer outgoing frames; send them one-per-packet: */
02805       if (_f->offset < hdrlen) {
02806          f = ast_frdup(_f);
02807       } else {
02808          f = _f;
02809       }
02810       if (f->data) {
02811          if (f->subclass == AST_FORMAT_G722) {
02812             /* G.722 is silllllllllllllly */
02813             f->samples /= 2;
02814          }
02815          ast_rtp_raw_write(rtp, f, codec);
02816       }
02817       if (f != _f)
02818          ast_frfree(f);
02819    }
02820       
02821    return 0;
02822 }

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

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, 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_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_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by ast_rtp_bridge().

02853 {
02854    struct ast_frame *fr = NULL;
02855    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
02856    int oldcodec0 = codec0, oldcodec1 = codec1;
02857    struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
02858    struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
02859    
02860    /* Set it up so audio goes directly between the two endpoints */
02861 
02862    /* Test the first channel */
02863    if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
02864       ast_rtp_get_peer(p1, &ac1);
02865       if (vp1)
02866          ast_rtp_get_peer(vp1, &vac1);
02867    } else
02868       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
02869    
02870    /* Test the second channel */
02871    if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
02872       ast_rtp_get_peer(p0, &ac0);
02873       if (vp0)
02874          ast_rtp_get_peer(vp0, &vac0);
02875    } else
02876       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
02877 
02878    /* Now we can unlock and move into our loop */
02879    ast_channel_unlock(c0);
02880    ast_channel_unlock(c1);
02881 
02882    /* Throw our channels into the structure and enter the loop */
02883    cs[0] = c0;
02884    cs[1] = c1;
02885    cs[2] = NULL;
02886    for (;;) {
02887       /* Check if anything changed */
02888       if ((c0->tech_pvt != pvt0) ||
02889           (c1->tech_pvt != pvt1) ||
02890           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
02891           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
02892          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
02893          if (c0->tech_pvt == pvt0)
02894             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02895                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02896          if (c1->tech_pvt == pvt1)
02897             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02898                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02899          return AST_BRIDGE_RETRY;
02900       }
02901 
02902       /* Check if they have changed their address */
02903       ast_rtp_get_peer(p1, &t1);
02904       if (vp1)
02905          ast_rtp_get_peer(vp1, &vt1);
02906       if (pr1->get_codec)
02907          codec1 = pr1->get_codec(c1);
02908       ast_rtp_get_peer(p0, &t0);
02909       if (vp0)
02910          ast_rtp_get_peer(vp0, &vt0);
02911       if (pr0->get_codec)
02912          codec0 = pr0->get_codec(c0);
02913       if ((inaddrcmp(&t1, &ac1)) ||
02914           (vp1 && inaddrcmp(&vt1, &vac1)) ||
02915           (codec1 != oldcodec1)) {
02916          if (option_debug > 1) {
02917             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02918                c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
02919             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
02920                c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
02921             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02922                c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
02923             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02924                c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
02925          }
02926          if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
02927             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
02928          memcpy(&ac1, &t1, sizeof(ac1));
02929          memcpy(&vac1, &vt1, sizeof(vac1));
02930          oldcodec1 = codec1;
02931       }
02932       if ((inaddrcmp(&t0, &ac0)) ||
02933           (vp0 && inaddrcmp(&vt0, &vac0))) {
02934          if (option_debug > 1) {
02935             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
02936                c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
02937             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
02938                c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
02939          }
02940          if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
02941             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
02942          memcpy(&ac0, &t0, sizeof(ac0));
02943          memcpy(&vac0, &vt0, sizeof(vac0));
02944          oldcodec0 = codec0;
02945       }
02946 
02947       /* Wait for frame to come in on the channels */
02948       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
02949          if (!timeoutms) {
02950             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02951                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02952             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02953                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02954             return AST_BRIDGE_RETRY;
02955          }
02956          if (option_debug)
02957             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
02958          if (ast_check_hangup(c0) || ast_check_hangup(c1))
02959             break;
02960          continue;
02961       }
02962       fr = ast_read(who);
02963       other = (who == c0) ? c1 : c0;
02964       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
02965              (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
02966               ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
02967          /* Break out of bridge */
02968          *fo = fr;
02969          *rc = who;
02970          if (option_debug)
02971             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
02972          if (c0->tech_pvt == pvt0)
02973             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
02974                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
02975          if (c1->tech_pvt == pvt1)
02976             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
02977                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
02978          return AST_BRIDGE_COMPLETE;
02979       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02980          if ((fr->subclass == AST_CONTROL_HOLD) ||
02981              (fr->subclass == AST_CONTROL_UNHOLD) ||
02982              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
02983              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
02984             if (fr->subclass == AST_CONTROL_HOLD) {
02985                /* If we someone went on hold we want the other side to reinvite back to us */
02986                if (who == c0)
02987                   pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
02988                else
02989                   pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
02990             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
02991                /* If they went off hold they should go back to being direct */
02992                if (who == c0)
02993                   pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
02994                else
02995                   pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
02996             }
02997             /* Update local address information */
02998             ast_rtp_get_peer(p0, &t0);
02999             memcpy(&ac0, &t0, sizeof(ac0));
03000             ast_rtp_get_peer(p1, &t1);
03001             memcpy(&ac1, &t1, sizeof(ac1));
03002             /* Update codec information */
03003             if (pr0->get_codec && c0->tech_pvt)
03004                oldcodec0 = codec0 = pr0->get_codec(c0);
03005             if (pr1->get_codec && c1->tech_pvt)
03006                oldcodec1 = codec1 = pr1->get_codec(c1);
03007             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03008             ast_frfree(fr);
03009          } else {
03010             *fo = fr;
03011             *rc = who;
03012             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03013             return AST_BRIDGE_COMPLETE;
03014          }
03015       } else {
03016          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03017              (fr->frametype == AST_FRAME_DTMF_END) ||
03018              (fr->frametype == AST_FRAME_VOICE) ||
03019              (fr->frametype == AST_FRAME_VIDEO) ||
03020              (fr->frametype == AST_FRAME_IMAGE) ||
03021              (fr->frametype == AST_FRAME_HTML) ||
03022              (fr->frametype == AST_FRAME_MODEM) ||
03023              (fr->frametype == AST_FRAME_TEXT)) {
03024             ast_write(other, fr);
03025          }
03026          ast_frfree(fr);
03027       }
03028       /* Swap priority */
03029       cs[2] = cs[0];
03030       cs[0] = cs[1];
03031       cs[1] = cs[2];
03032    }
03033 
03034    if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
03035       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
03036    if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
03037       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
03038 
03039    return AST_BRIDGE_FAILED;
03040 }

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

Definition at line 3138 of file rtp.c.

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

Referenced by ast_rtp_bridge().

03139 {
03140    struct ast_frame *fr = NULL;
03141    struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
03142    int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
03143    int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
03144    int p0_callback = 0, p1_callback = 0;
03145    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03146 
03147    /* Okay, setup each RTP structure to do P2P forwarding */
03148    ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03149    p2p_set_bridge(p0, p1);
03150    ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03151    p2p_set_bridge(p1, p0);
03152 
03153    /* Activate callback modes if possible */
03154    p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03155    p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03156 
03157    /* Now let go of the channel locks and be on our way */
03158    ast_channel_unlock(c0);
03159    ast_channel_unlock(c1);
03160 
03161    /* Go into a loop forwarding frames until we don't need to anymore */
03162    cs[0] = c0;
03163    cs[1] = c1;
03164    cs[2] = NULL;
03165    for (;;) {
03166       /* If the underlying formats have changed force this bridge to break */
03167       if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
03168          ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n");
03169          res = AST_BRIDGE_FAILED_NOWARN;
03170          break;
03171       }
03172       /* Check if anything changed */
03173       if ((c0->tech_pvt != pvt0) ||
03174           (c1->tech_pvt != pvt1) ||
03175           (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
03176           (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
03177          ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
03178          if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
03179             ast_frfree(fr);
03180          if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
03181             ast_frfree(fr);
03182          res = AST_BRIDGE_RETRY;
03183          break;
03184       }
03185       /* Wait on a channel to feed us a frame */
03186       if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
03187          if (!timeoutms) {
03188             res = AST_BRIDGE_RETRY;
03189             break;
03190          }
03191          if (option_debug)
03192             ast_log(LOG_NOTICE, "Ooh, empty read...\n");
03193          if (ast_check_hangup(c0) || ast_check_hangup(c1))
03194             break;
03195          continue;
03196       }
03197       /* Read in frame from channel */
03198       fr = ast_read(who);
03199       other = (who == c0) ? c1 : c0;
03200       /* Dependong on the frame we may need to break out of our bridge */
03201       if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
03202              ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
03203              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
03204          /* Record received frame and who */
03205          *fo = fr;
03206          *rc = who;
03207          if (option_debug)
03208             ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
03209          res = AST_BRIDGE_COMPLETE;
03210          break;
03211       } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03212          if ((fr->subclass == AST_CONTROL_HOLD) ||
03213              (fr->subclass == AST_CONTROL_UNHOLD) ||
03214              (fr->subclass == AST_CONTROL_VIDUPDATE) ||
03215              (fr->subclass == AST_CONTROL_SRCUPDATE)) {
03216             /* If we are going on hold, then break callback mode and P2P bridging */
03217             if (fr->subclass == AST_CONTROL_HOLD) {
03218                if (p0_callback)
03219                   p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03220                if (p1_callback)
03221                   p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03222                p2p_set_bridge(p0, NULL);
03223                p2p_set_bridge(p1, NULL);
03224             } else if (fr->subclass == AST_CONTROL_UNHOLD) {
03225                /* If we are off hold, then go back to callback mode and P2P bridging */
03226                ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
03227                p2p_set_bridge(p0, p1);
03228                ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
03229                p2p_set_bridge(p1, p0);
03230                p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
03231                p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
03232             }
03233             ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
03234             ast_frfree(fr);
03235          } else {
03236             *fo = fr;
03237             *rc = who;
03238             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
03239             res = AST_BRIDGE_COMPLETE;
03240             break;
03241          }
03242       } else {
03243          if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
03244              (fr->frametype == AST_FRAME_DTMF_END) ||
03245              (fr->frametype == AST_FRAME_VOICE) ||
03246              (fr->frametype == AST_FRAME_VIDEO) ||
03247              (fr->frametype == AST_FRAME_IMAGE) ||
03248              (fr->frametype == AST_FRAME_HTML) ||
03249              (fr->frametype == AST_FRAME_MODEM) ||
03250              (fr->frametype == AST_FRAME_TEXT)) {
03251             ast_write(other, fr);
03252          }
03253 
03254          ast_frfree(fr);
03255       }
03256       /* Swap priority */
03257       cs[2] = cs[0];
03258       cs[0] = cs[1];
03259       cs[1] = cs[2];
03260    }
03261 
03262    /* If we are totally avoiding the core, then restore our link to it */
03263    if (p0_callback)
03264       p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
03265    if (p1_callback)
03266       p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
03267 
03268    /* Break out of the direct bridge */
03269    p2p_set_bridge(p0, NULL);
03270    p2p_set_bridge(p1, NULL);
03271 
03272    return res;
03273 }

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

References ast_inet_ntoa(), ast_log(), 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, LOG_DEBUG, ast_rtp::nat, option_debug, reconstruct(), rtp_debug_test_addr(), ast_rtp::s, and ast_rtp::them.

Referenced by ast_rtp_read().

01052 {
01053    int res = 0, payload = 0, bridged_payload = 0, mark;
01054    struct rtpPayloadType rtpPT;
01055    int reconstruct = ntohl(rtpheader[0]);
01056 
01057    /* Get fields from packet */
01058    payload = (reconstruct & 0x7f0000) >> 16;
01059    mark = (((reconstruct & 0x800000) >> 23) != 0);
01060 
01061    /* Check what the payload value should be */
01062    rtpPT = ast_rtp_lookup_pt(rtp, payload);
01063 
01064    /* 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 */
01065    if (!bridged->current_RTP_PT[payload].code)
01066       return -1;
01067 
01068    /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
01069    if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
01070       return -1;
01071 
01072    /* Otherwise adjust bridged payload to match */
01073    bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
01074 
01075    /* If the mark bit has not been sent yet... do it now */
01076    if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
01077       mark = 1;
01078       ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
01079    }
01080 
01081    /* Reconstruct part of the packet */
01082    reconstruct &= 0xFF80FFFF;
01083    reconstruct |= (bridged_payload << 16);
01084    reconstruct |= (mark << 23);
01085    rtpheader[0] = htonl(reconstruct);
01086 
01087    /* Send the packet back out */
01088    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
01089    if (res < 0) {
01090       if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01091          ast_log(LOG_DEBUG, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno));
01092       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01093          if (option_debug || rtpdebug)
01094             ast_log(LOG_DEBUG, "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));
01095          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01096       }
01097       return 0;
01098    } else if (rtp_debug_test_addr(&bridged->them))
01099          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);
01100 
01101    return 0;
01102 }

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

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

01003 {
01004    struct timeval now;
01005    double transit;
01006    double current_time;
01007    double d;
01008    double dtv;
01009    double prog;
01010    
01011    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01012       gettimeofday(&rtp->rxcore, NULL);
01013       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01014       /* map timestamp to a real time */
01015       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01016       rtp->rxcore.tv_sec -= timestamp / 8000;
01017       rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
01018       /* Round to 0.1ms for nice, pretty timestamps */
01019       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01020       if (rtp->rxcore.tv_usec < 0) {
01021          /* Adjust appropriately if necessary */
01022          rtp->rxcore.tv_usec += 1000000;
01023          rtp->rxcore.tv_sec -= 1;
01024       }
01025    }
01026 
01027    gettimeofday(&now,NULL);
01028    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01029    tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
01030    tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
01031    if (tv->tv_usec >= 1000000) {
01032       tv->tv_usec -= 1000000;
01033       tv->tv_sec += 1;
01034    }
01035    prog = (double)((timestamp-rtp->seedrxts)/8000.);
01036    dtv = (double)rtp->drxcore + (double)(prog);
01037    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01038    transit = current_time - dtv;
01039    d = transit - rtp->rxtransit;
01040    rtp->rxtransit = transit;
01041    if (d<0)
01042       d=-d;
01043    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01044    if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
01045       rtp->rtcp->maxrxjitter = rtp->rxjitter;
01046    if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01047       rtp->rtcp->minrxjitter = rtp->rxjitter;
01048 }

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

Definition at line 2162 of file rtp.c.

References ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

02163 {
02164    struct timeval t;
02165    long ms;
02166    if (ast_tvzero(rtp->txcore)) {
02167       rtp->txcore = ast_tvnow();
02168       /* Round to 20ms for nice, pretty timestamps */
02169       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
02170    }
02171    /* Use previous txcore if available */
02172    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
02173    ms = ast_tvdiff_ms(t, rtp->txcore);
02174    if (ms < 0)
02175       ms = 0;
02176    /* Use what we just got for next time */
02177    rtp->txcore = t;
02178    return (unsigned int) ms;
02179 }

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

Get channel driver interface structure.

Definition at line 1461 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, protos, 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().

01462 {
01463    struct ast_rtp_protocol *cur = NULL;
01464 
01465    AST_LIST_LOCK(&protos);
01466    AST_LIST_TRAVERSE(&protos, cur, list) {
01467       if (cur->type == chan->tech->type)
01468          break;
01469    }
01470    AST_LIST_UNLOCK(&protos);
01471 
01472    return cur;
01473 }

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

Helper function to switch a channel and RTP stream out of callback mode.

Definition at line 3109 of file rtp.c.

References ast_channel_lock, ast_channel_unlock, ast_io_add(), AST_IO_IN, ast_io_remove(), ast_test_flag, ast_channel::fds, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, rtpread(), and ast_rtp::s.

Referenced by bridge_p2p_loop().

03110 {
03111    ast_channel_lock(chan);
03112 
03113    /* Remove the callback from the IO context */
03114    ast_io_remove(rtp->io, iod[0]);
03115 
03116    /* Restore file descriptors */
03117    chan->fds[0] = fds[0];
03118    ast_channel_unlock(chan);
03119 
03120    /* Restore callback mode if previously used */
03121    if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
03122       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
03123 
03124    return 0;
03125 }

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

P2P RTP Callback.

Definition at line 3102 of file rtp.c.

Referenced by bridge_p2p_loop().

03103 {
03104    return 0;
03105 }

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

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.

Referenced by bridge_p2p_loop().

03129 {
03130    ast_mutex_lock(&rtp0->bridge_lock);
03131    rtp0->bridged = rtp1;
03132    ast_mutex_unlock(&rtp0->bridge_lock);
03133 
03134    return;
03135 }

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

Definition at line 670 of file rtp.c.

References AST_FRAME_DTMF_END, ast_log(), ast_rtp::dtmfcount, event, f, LOG_DEBUG, option_debug, ast_rtp::resp, and send_dtmf().

Referenced by ast_rtp_read().

00671 {
00672    unsigned int event;
00673    char resp = 0;
00674    struct ast_frame *f = NULL;
00675    event = ntohl(*((unsigned int *)(data)));
00676    event &= 0x001F;
00677    if (option_debug > 2 || rtpdebug)
00678       ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len);
00679    if (event < 10) {
00680       resp = '0' + event;
00681    } else if (event < 11) {
00682       resp = '*';
00683    } else if (event < 12) {
00684       resp = '#';
00685    } else if (event < 16) {
00686       resp = 'A' + (event - 12);
00687    } else if (event < 17) {
00688       resp = 'X';
00689    }
00690    if (rtp->resp && (rtp->resp != resp)) {
00691       f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00692    }
00693    rtp->resp = resp;
00694    rtp->dtmfcount = dtmftimeout;
00695    return f;
00696 }

static struct ast_frame* process_rfc2833 ( struct ast_rtp rtp,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp 
) [static, read]

Process RTP DTMF and events according to RFC 2833.

RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".

Parameters:
rtp 
data 
len 
seqno 
Returns:

Definition at line 709 of file rtp.c.

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

Referenced by ast_rtp_read().

00710 {
00711    unsigned int event;
00712    unsigned int event_end;
00713    unsigned int samples;
00714    char resp = 0;
00715    struct ast_frame *f = NULL;
00716 
00717    /* Figure out event, event end, and samples */
00718    event = ntohl(*((unsigned int *)(data)));
00719    event >>= 24;
00720    event_end = ntohl(*((unsigned int *)(data)));
00721    event_end <<= 8;
00722    event_end >>= 24;
00723    samples = ntohl(*((unsigned int *)(data)));
00724    samples &= 0xFFFF;
00725 
00726    /* Print out debug if turned on */
00727    if (rtpdebug || option_debug > 2)
00728       ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
00729 
00730    /* Figure out what digit was pressed */
00731    if (event < 10) {
00732       resp = '0' + event;
00733    } else if (event < 11) {
00734       resp = '*';
00735    } else if (event < 12) {
00736       resp = '#';
00737    } else if (event < 16) {
00738       resp = 'A' + (event - 12);
00739    } else if (event < 17) {   /* Event 16: Hook flash */
00740       resp = 'X'; 
00741    } else {
00742       /* Not a supported event */
00743       ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
00744       return &ast_null_frame;
00745    }
00746 
00747    if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
00748       if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
00749          rtp->resp = resp;
00750          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00751          f->len = 0;
00752          rtp->lastevent = timestamp;
00753       }
00754    } else {
00755       if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) {
00756          rtp->resp = resp;
00757          f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
00758       } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) {
00759          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
00760          f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
00761          rtp->resp = 0;
00762          rtp->lastevent = seqno;
00763       }
00764    }
00765 
00766    rtp->dtmfcount = dtmftimeout;
00767    rtp->dtmfsamples = samples;
00768 
00769    return f;
00770 }

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

Process Comfort Noise RTP.

This is incomplete at the moment.

Definition at line 778 of file rtp.c.

References 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_DEBUG, LOG_NOTICE, ast_frame::offset, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_read().

00779 {
00780    struct ast_frame *f = NULL;
00781    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
00782       totally help us out becuase we don't have an engine to keep it going and we are not
00783       guaranteed to have it every 20ms or anything */
00784    if (rtpdebug)
00785       ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
00786 
00787    if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
00788       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
00789          ast_inet_ntoa(rtp->them.sin_addr));
00790       ast_set_flag(rtp, FLAG_3389_WARNING);
00791    }
00792 
00793    /* Must have at least one byte */
00794    if (!len)
00795       return NULL;
00796    if (len < 24) {
00797       rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
00798       rtp->f.datalen = len - 1;
00799       rtp->f.offset = AST_FRIENDLY_OFFSET;
00800       memcpy(rtp->f.data, data + 1, len - 1);
00801    } else {
00802       rtp->f.data = NULL;
00803       rtp->f.offset = 0;
00804       rtp->f.datalen = 0;
00805    }
00806    rtp->f.frametype = AST_FRAME_CNG;
00807    rtp->f.subclass = data[0] & 0x7f;
00808    rtp->f.samples = 0;
00809    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
00810    f = &rtp->f;
00811    return f;
00812 }

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

Definition at line 656 of file rtp.c.

References rtcpdebugaddr.

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

00657 {
00658    if (rtcpdebug == 0)
00659       return 0;
00660    if (rtcpdebugaddr.sin_addr.s_addr) {
00661       if (((ntohs(rtcpdebugaddr.sin_port) != 0)
00662          && (rtcpdebugaddr.sin_port != addr->sin_port))
00663          || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00664       return 0;
00665    }
00666    return 1;
00667 }

static int rtcp_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3548 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtcp_do_debug_ip(), and rtcpdebugaddr.

03548                                                          {
03549    if (argc != 2) {
03550       if (argc != 4)
03551          return RESULT_SHOWUSAGE;
03552       return rtcp_do_debug_ip(fd, argc, argv);
03553    }
03554    rtcpdebug = 1;
03555    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03556    ast_cli(fd, "RTCP Debugging Enabled\n");
03557    return RESULT_SUCCESS;
03558 }

static int rtcp_do_debug_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3536 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtcp_do_debug_ip_deprecated(), and rtcpdebugaddr.

03536                                                                     {
03537    if (argc != 3) {
03538       if (argc != 5)
03539          return RESULT_SHOWUSAGE;
03540       return rtcp_do_debug_ip_deprecated(fd, argc, argv);
03541    }
03542    rtcpdebug = 1;
03543    memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
03544    ast_cli(fd, "RTCP Debugging Enabled\n");
03545    return RESULT_SUCCESS;
03546 }

static int rtcp_do_debug_ip ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3493 of file rtp.c.

References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcpdebugaddr.

Referenced by rtcp_do_debug().

03494 {
03495    struct hostent *hp;
03496    struct ast_hostent ahp;
03497    int port = 0;
03498    char *p, *arg;
03499    if (argc != 4)
03500       return RESULT_SHOWUSAGE;
03501 
03502    arg = argv[3];
03503    p = strstr(arg, ":");
03504    if (p) {
03505       *p = '\0';
03506       p++;
03507       port = atoi(p);
03508    }
03509    hp = ast_gethostbyname(arg, &ahp);
03510    if (hp == NULL)
03511       return RESULT_SHOWUSAGE;
03512    rtcpdebugaddr.sin_family = AF_INET;
03513    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03514    rtcpdebugaddr.sin_port = htons(port);
03515    if (port == 0)
03516       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03517    else
03518       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03519    rtcpdebug = 1;
03520    return RESULT_SUCCESS;
03521 }

static int rtcp_do_debug_ip_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3463 of file rtp.c.

References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcpdebugaddr.

Referenced by rtcp_do_debug_deprecated().

03464 {
03465    struct hostent *hp;
03466    struct ast_hostent ahp;
03467    int port = 0;
03468    char *p, *arg;
03469    if (argc != 5)
03470       return RESULT_SHOWUSAGE;
03471 
03472    arg = argv[4];
03473    p = strstr(arg, ":");
03474    if (p) {
03475       *p = '\0';
03476       p++;
03477       port = atoi(p);
03478    }
03479    hp = ast_gethostbyname(arg, &ahp);
03480    if (hp == NULL)
03481       return RESULT_SHOWUSAGE;
03482    rtcpdebugaddr.sin_family = AF_INET;
03483    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
03484    rtcpdebugaddr.sin_port = htons(port);
03485    if (port == 0)
03486       ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
03487    else
03488       ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
03489    rtcpdebug = 1;
03490    return RESULT_SUCCESS;
03491 }

static int rtcp_do_stats ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3569 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03569                                                          {
03570    if (argc != 2) {
03571       return RESULT_SHOWUSAGE;
03572    }
03573    rtcpstats = 1;
03574    ast_cli(fd, "RTCP Stats Enabled\n");
03575    return RESULT_SUCCESS;
03576 }

static int rtcp_do_stats_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3560 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03560                                                                     {
03561    if (argc != 3) {
03562       return RESULT_SHOWUSAGE;
03563    }
03564    rtcpstats = 1;
03565    ast_cli(fd, "RTCP Stats Enabled\n");
03566    return RESULT_SUCCESS;
03567 }

static int rtcp_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3596 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03597 {
03598    if (argc != 3)
03599       return RESULT_SHOWUSAGE;
03600    rtcpdebug = 0;
03601    ast_cli(fd,"RTCP Debugging Disabled\n");
03602    return RESULT_SUCCESS;
03603 }

static int rtcp_no_debug_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3587 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03588 {
03589    if (argc != 4)
03590       return RESULT_SHOWUSAGE;
03591    rtcpdebug = 0;
03592    ast_cli(fd,"RTCP Debugging Disabled\n");
03593    return RESULT_SUCCESS;
03594 }

static int rtcp_no_stats ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3614 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03615 {
03616    if (argc != 3)
03617       return RESULT_SHOWUSAGE;
03618    rtcpstats = 0;
03619    ast_cli(fd,"RTCP Stats Disabled\n");
03620    return RESULT_SUCCESS;
03621 }

static int rtcp_no_stats_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3605 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03606 {
03607    if (argc != 4)
03608       return RESULT_SHOWUSAGE;
03609    rtcpstats = 0;
03610    ast_cli(fd,"RTCP Stats Disabled\n");
03611    return RESULT_SUCCESS;
03612 }

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

Definition at line 643 of file rtp.c.

References rtpdebugaddr.

Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_senddigit_continuation(), ast_rtp_senddigit_end(), and bridge_p2p_rtp_write().

00644 {
00645    if (rtpdebug == 0)
00646       return 0;
00647    if (rtpdebugaddr.sin_addr.s_addr) {
00648       if (((ntohs(rtpdebugaddr.sin_port) != 0)
00649          && (rtpdebugaddr.sin_port != addr->sin_port))
00650          || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00651       return 0;
00652    }
00653    return 1;
00654 }

static int rtp_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3523 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtp_do_debug_ip(), and rtpdebugaddr.

03524 {
03525    if (argc != 2) {
03526       if (argc != 4)
03527          return RESULT_SHOWUSAGE;
03528       return rtp_do_debug_ip(fd, argc, argv);
03529    }
03530    rtpdebug = 1;
03531    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
03532    ast_cli(fd, "RTP Debugging Enabled\n");
03533    return RESULT_SUCCESS;
03534 }

static int rtp_do_debug_ip ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3433 of file rtp.c.

References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtpdebugaddr.

Referenced by rtp_do_debug().

03434 {
03435    struct hostent *hp;
03436    struct ast_hostent ahp;
03437    int port = 0;
03438    char *p, *arg;
03439 
03440    if (argc != 4)
03441       return RESULT_SHOWUSAGE;
03442    arg = argv[3];
03443    p = strstr(arg, ":");
03444    if (p) {
03445       *p = '\0';
03446       p++;
03447       port = atoi(p);
03448    }
03449    hp = ast_gethostbyname(arg, &ahp);
03450    if (hp == NULL)
03451       return RESULT_SHOWUSAGE;
03452    rtpdebugaddr.sin_family = AF_INET;
03453    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
03454    rtpdebugaddr.sin_port = htons(port);
03455    if (port == 0)
03456       ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
03457    else
03458       ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
03459    rtpdebug = 1;
03460    return RESULT_SUCCESS;
03461 }

static int rtp_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3578 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03579 {
03580    if (argc != 3)
03581       return RESULT_SHOWUSAGE;
03582    rtpdebug = 0;
03583    ast_cli(fd,"RTP Debugging Disabled\n");
03584    return RESULT_SUCCESS;
03585 }

static int rtp_socket ( void   )  [static]

Definition at line 1837 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

01838 {
01839    int s;
01840    long flags;
01841    s = socket(AF_INET, SOCK_DGRAM, 0);
01842    if (s > -1) {
01843       flags = fcntl(s, F_GETFL);
01844       fcntl(s, F_SETFL, flags | O_NONBLOCK);
01845 #ifdef SO_NO_CHECK
01846       if (nochecksums)
01847          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
01848 #endif
01849    }
01850    return s;
01851 }

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

Definition at line 814 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().

00815 {
00816    struct ast_rtp *rtp = cbdata;
00817    struct ast_frame *f;
00818    f = ast_rtp_read(rtp);
00819    if (f) {
00820       if (rtp->callback)
00821          rtp->callback(rtp, f, rtp->data);
00822    }
00823    return 1;
00824 }

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

Definition at line 616 of file rtp.c.

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

Referenced by process_cisco_dtmf(), and process_rfc2833().

00617 {
00618    if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
00619         (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
00620       if (option_debug)
00621          ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
00622       rtp->resp = 0;
00623       rtp->dtmfsamples = 0;
00624       return &ast_null_frame;
00625    }
00626    if (option_debug)
00627       ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
00628    if (rtp->resp == 'X') {
00629       rtp->f.frametype = AST_FRAME_CONTROL;
00630       rtp->f.subclass = AST_CONTROL_FLASH;
00631    } else {
00632       rtp->f.frametype = type;
00633       rtp->f.subclass = rtp->resp;
00634    }
00635    rtp->f.datalen = 0;
00636    rtp->f.samples = 0;
00637    rtp->f.mallocd = 0;
00638    rtp->f.src = "RTP";
00639    return &rtp->f;
00640    
00641 }

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

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

00301 {
00302    switch(msg) {
00303    case STUN_MAPPED_ADDRESS:
00304       return "Mapped Address";
00305    case STUN_RESPONSE_ADDRESS:
00306       return "Response Address";
00307    case STUN_CHANGE_REQUEST:
00308       return "Change Request";
00309    case STUN_SOURCE_ADDRESS:
00310       return "Source Address";
00311    case STUN_CHANGED_ADDRESS:
00312       return "Changed Address";
00313    case STUN_USERNAME:
00314       return "Username";
00315    case STUN_PASSWORD:
00316       return "Password";
00317    case STUN_MESSAGE_INTEGRITY:
00318       return "Message Integrity";
00319    case STUN_ERROR_CODE:
00320       return "Error Code";
00321    case STUN_UNKNOWN_ATTRIBUTES:
00322       return "Unknown Attributes";
00323    case STUN_REFLECTED_FROM:
00324       return "Reflected From";
00325    }
00326    return "Non-RFC3489 Attribute";
00327 }

static int stun_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3623 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03624 {
03625    if (argc != 2) {
03626       return RESULT_SHOWUSAGE;
03627    }
03628    stundebug = 1;
03629    ast_cli(fd, "STUN Debugging Enabled\n");
03630    return RESULT_SUCCESS;
03631 }

static int stun_handle_packet ( int  s,
struct sockaddr_in *  src,
unsigned char *  data,
size_t  len 
) [static]

Definition at line 424 of file rtp.c.

References append_attr_address(), append_attr_string(), ast_log(), ast_verbose(), stun_attr::attr, stun_header::id, stun_header::ies, stun_attr::len, LOG_DEBUG, stun_header::msglen, stun_header::msgtype, option_debug, STUN_ACCEPT, stun_attr2str(), STUN_BINDREQ, STUN_BINDRESP, STUN_IGNORE, STUN_MAPPED_ADDRESS, stun_msg2str(), stun_process_attr(), stun_send(), STUN_USERNAME, and stun_state::username.

Referenced by ast_rtp_read().

00425 {
00426    struct stun_header *resp, *hdr = (struct stun_header *)data;
00427    struct stun_attr *attr;
00428    struct stun_state st;
00429    int ret = STUN_IGNORE;  
00430    unsigned char respdata[1024];
00431    int resplen, respleft;
00432    
00433    if (len < sizeof(struct stun_header)) {
00434       if (option_debug)
00435          ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header));
00436       return -1;
00437    }
00438    if (stundebug)
00439       ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen));
00440    if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) {
00441       if (option_debug)
00442          ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header));
00443    } else
00444       len = ntohs(hdr->msglen);
00445    data += sizeof(struct stun_header);
00446    memset(&st, 0, sizeof(st));
00447    while(len) {
00448       if (len < sizeof(struct stun_attr)) {
00449          if (option_debug)
00450             ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr));
00451          break;
00452       }
00453       attr = (struct stun_attr *)data;
00454       if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) {
00455          if (option_debug)
00456             ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len);
00457          break;
00458       }
00459       if (stun_process_attr(&st, attr)) {
00460          if (option_debug)
00461             ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
00462          break;
00463       }
00464       /* Clear attribute in case previous entry was a string */
00465       attr->attr = 0;
00466       data += ntohs(attr->len) + sizeof(struct stun_attr);
00467       len -= ntohs(attr->len) + sizeof(struct stun_attr);
00468    }
00469    /* Null terminate any string */
00470    *data = '\0';
00471    resp = (struct stun_header *)respdata;
00472    resplen = 0;
00473    respleft = sizeof(respdata) - sizeof(struct stun_header);
00474    resp->id = hdr->id;
00475    resp->msgtype = 0;
00476    resp->msglen = 0;
00477    attr = (struct stun_attr *)resp->ies;
00478    if (!len) {
00479       switch(ntohs(hdr->msgtype)) {
00480       case STUN_BINDREQ:
00481          if (stundebug)
00482             ast_verbose("STUN Bind Request, username: %s\n", 
00483                st.username ? st.username : "<none>");
00484          if (st.username)
00485             append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
00486          append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
00487          resp->msglen = htons(resplen);
00488          resp->msgtype = htons(STUN_BINDRESP);
00489          stun_send(s, src, resp);
00490          ret = STUN_ACCEPT;
00491          break;
00492       default:
00493          if (stundebug)
00494             ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
00495       }
00496    }
00497    return ret;
00498 }

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

Definition at line 281 of file rtp.c.

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

Referenced by stun_handle_packet().

00282 {
00283    switch(msg) {
00284    case STUN_BINDREQ:
00285       return "Binding Request";
00286    case STUN_BINDRESP:
00287       return "Binding Response";
00288    case STUN_BINDERR:
00289       return "Binding Error Response";
00290    case STUN_SECREQ:
00291       return "Shared Secret Request";
00292    case STUN_SECRESP:
00293       return "Shared Secret Response";
00294    case STUN_SECERR:
00295       return "Shared Secret Error Response";
00296    }
00297    return "Non-RFC3489 Message";
00298 }

static int stun_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3633 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03634 {
03635    if (argc != 3)
03636       return RESULT_SHOWUSAGE;
03637    stundebug = 0;
03638    ast_cli(fd, "STUN Debugging Disabled\n");
03639    return RESULT_SUCCESS;
03640 }

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

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

00335 {
00336    if (stundebug)
00337       ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
00338          stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00339    switch(ntohs(attr->attr)) {
00340    case STUN_USERNAME:
00341       state->username = (const char *) (attr->value);
00342       break;
00343    case STUN_PASSWORD:
00344       state->password = (const char *) (attr->value);
00345       break;
00346    default:
00347       if (stundebug)
00348          ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 
00349             stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00350    }
00351    return 0;
00352 }

static void stun_req_id ( struct stun_header req  )  [static]

Definition at line 391 of file rtp.c.

References ast_random(), and stun_header::id.

Referenced by ast_rtp_stun_request().

00392 {
00393    int x;
00394    for (x=0;x<4;x++)
00395       req->id.id[x] = ast_random();
00396 }

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

Definition at line 385 of file rtp.c.

References stun_header::msglen.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

00386 {
00387    return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00388       (struct sockaddr *)dst, sizeof(*dst));
00389 }

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

Definition at line 503 of file rtp.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

00504 {
00505    unsigned int sec, usec, frac;
00506    sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
00507    usec = tv.tv_usec;
00508    frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
00509    *msw = sec;
00510    *lsw = frac;
00511 }


Variable Documentation

struct ast_cli_entry cli_rtp[] [static]

Definition at line 3709 of file rtp.c.

Initial value:

 {
   { "rtp", "no", "debug", NULL },
   rtp_no_debug, NULL,
        NULL }

Definition at line 3674 of file rtp.c.

Initial value:

 {
   { "rtp", "rtcp", "debug", NULL },
   rtcp_do_debug_deprecated, NULL,
        NULL }

Definition at line 3684 of file rtp.c.

Initial value:

 {
   { "rtp", "rtcp", "debug", "ip", NULL },
   rtcp_do_debug_deprecated, NULL,
        NULL }

Definition at line 3679 of file rtp.c.

Initial value:

 {
   { "rtp", "rtcp", "no", "debug", NULL },
   rtcp_no_debug_deprecated, NULL,
        NULL }

Definition at line 3689 of file rtp.c.

Initial value:

 {
   { "rtp", "rtcp", "no", "stats", NULL },
   rtcp_no_stats_deprecated, NULL,
        NULL }

Definition at line 3699 of file rtp.c.

Initial value:

 {
   { "rtp", "rtcp", "stats", NULL },
   rtcp_do_stats_deprecated, NULL,
        NULL }

Definition at line 3694 of file rtp.c.

Initial value:

 {
   { "stun", "no", "debug", NULL },
   stun_no_debug, NULL,
   NULL }

Definition at line 3704 of file rtp.c.

char debug_usage[] [static]

Initial value:

  "Usage: rtp debug [ip host[:port]]\n"
  "       Enable dumping of all RTP packets to and from host.\n"

Definition at line 3642 of file rtp.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 78 of file rtp.c.

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

char no_debug_usage[] [static]

Initial value:

  "Usage: rtp debug off\n"
  "       Disable all RTP debugging\n"

Definition at line 3646 of file rtp.c.

struct stun_addr packed

Definition at line 1333 of file rtp.c.

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

char rtcp_debug_usage[] [static]

Initial value:

  "Usage: rtcp debug [ip host[:port]]\n"
  "       Enable dumping of all RTCP packets to and from host.\n"

Definition at line 3658 of file rtp.c.

char rtcp_no_debug_usage[] [static]

Initial value:

  "Usage: rtcp debug off\n"
  "       Disable all RTCP debugging\n"

Definition at line 3662 of file rtp.c.

char rtcp_no_stats_usage[] [static]

Initial value:

  "Usage: rtcp stats off\n"
  "       Disable all RTCP stats\n"

Definition at line 3670 of file rtp.c.

char rtcp_stats_usage[] [static]

Initial value:

  "Usage: rtcp stats\n"
  "       Enable dumping of RTCP stats.\n"

Definition at line 3666 of file rtp.c.

int rtcpdebug [static]

Are we debugging RTCP?

Definition at line 83 of file rtp.c.

struct sockaddr_in rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 88 of file rtp.c.

Referenced by rtcp_debug_test_addr(), rtcp_do_debug(), rtcp_do_debug_deprecated(), rtcp_do_debug_ip(), and rtcp_do_debug_ip_deprecated().

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 85 of file rtp.c.

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 84 of file rtp.c.

int rtpdebug [static]

Are we debugging?

Definition at line 82 of file rtp.c.

struct sockaddr_in rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 87 of file rtp.c.

Referenced by rtp_debug_test_addr(), rtp_do_debug(), and rtp_do_debug_ip().

int rtpend [static]

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

Definition at line 81 of file rtp.c.

int rtpstart [static]

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

Definition at line 80 of file rtp.c.

struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static]

Definition at line 1367 of file rtp.c.

char stun_debug_usage[] [static]

Initial value:

  "Usage: stun debug\n"
  "       Enable STUN (Simple Traversal of UDP through NATs) debugging\n"

Definition at line 3650 of file rtp.c.

char stun_no_debug_usage[] [static]

Initial value:

  "Usage: stun debug off\n"
  "       Disable STUN debugging\n"

Definition at line 3654 of file rtp.c.

int stundebug [static]

Are we debugging stun?

Definition at line 86 of file rtp.c.

char* subtype

Definition at line 1335 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type


Generated on Sun Dec 18 20:55:54 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6