Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:46 2007

Asterisk developer's documentation :: Codename Pineapple


rtp.c File Reference


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.

#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.The value of each payload format mapping:. 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 unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
static int ast_rtcp_write (void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (void *data)
 Send RTCP recipient's report.
static int ast_rtcp_write_sr (void *data)
 Send RTCP sender's report.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
enum ast_bridge_result ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 The RTP bridge.
int ast_rtp_codec_getformat (int pt)
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 *c0, struct ast_channel *c1)
 If possible, create an early bridge directly between the devices without having to send a re-invite later.
int ast_rtp_fd (struct ast_rtp *rtp)
ast_rtpast_rtp_get_bridged (struct ast_rtp *rtp)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
 Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
int ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
char * ast_rtp_get_quality (struct ast_rtp *rtp)
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)
 Return RTCP quality string.
int ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code)
 Looks up an RTP code out of our *static* outbound list.
char * ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options)
 Build a string of MIME subtype names from a capability list.
const char * ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code, enum ast_rtp_options options)
 Mapping an Asterisk code into a MIME subtype (string):.
rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
 Mapping between RTP payload format codes and Asterisk codes:.
int ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media)
ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
void ast_rtp_new_init (struct ast_rtp *rtp)
 Initialize a new RTP structure.
ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
 Initializate a RTP session using an in_addr structure.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register an RTP channel client.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister an RTP channel client.
void ast_rtp_pt_clear (struct ast_rtp *rtp)
 Setting RTP payload types from lines in a SDP description:.
void ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src)
 Copy payload types between RTP structures.
void ast_rtp_pt_default (struct ast_rtp *rtp)
 Set payload types to defaults.
static int ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec)
 Write RTP packet with audio or video media frames into UDP packet.
ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
static int ast_rtp_senddigit_continuation (struct ast_rtp *rtp)
 Send continuation frame for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 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
void 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)
 Send STUN request (??).
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
static AST_RWLIST_HEAD_STATIC (protos, ast_rtp_protocol)
 List of current sessions.
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 **iod)
 Helper function to switch a channel and RTP stream out of callback mode.
static int p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
 P2P RTP Callback.
static void p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1)
 Helper function that sets what an RTP structure is bridged to.
static struct ast_frameprocess_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len)
static struct ast_frameprocess_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno)
 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_ip (int fd, int argc, char *argv[])
static int rtcp_do_stats (int fd, int argc, char *argv[])
static int rtcp_no_debug (int fd, int argc, char *argv[])
static int rtcp_no_stats (int fd, int argc, char *argv[])
static void rtp_bridge_lock (struct ast_rtp *rtp)
static void rtp_bridge_unlock (struct ast_rtp *rtp)
static int rtp_debug_test_addr (struct sockaddr_in *addr)
static 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)
 Open RTP or RTCP socket for a session.
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 const char debug_usage []
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
struct {
   int   alarm
   const char *   description
   unsigned int   event_log:1
   char *   ext
   char *   mtype
   char *   name
   const char *   name
   rtpPayloadType   payloadType
   unsigned int   queue_log:1
   char *   subtype
   char *   type
   int   val
mimeTypes []
static const char no_debug_usage []
stun_addr packed
stun_attr packed
stun_header packed
static const char rtcp_debug_usage []
static const char rtcp_no_debug_usage []
static const char rtcp_no_stats_usage []
static const 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 const char stun_debug_usage []
static const char stun_no_debug_usage []
static int stundebug


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

Referenced by process_rfc3389().

#define FLAG_CALLBACK_MODE   (1 << 6)
 

Definition at line 195 of file rtp.c.

Referenced by p2p_callback_disable().

#define FLAG_DTMF_COMPENSATE   (1 << 7)
 

Definition at line 196 of file rtp.c.

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

#define FLAG_HAS_DTMF   (1 << 3)
 

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

Referenced by ast_rtp_setstun().

#define FLAG_NAT_ACTIVE   (3 << 1)
 

Definition at line 189 of file rtp.c.

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

#define FLAG_NAT_INACTIVE   (0 << 1)
 

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

Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().

#define FLAG_P2P_SENT_MARK   (1 << 4)
 

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

Referenced by ast_rtp_read(), and stun_handle_packet().

#define STUN_BINDERR   0x0111
 

Definition at line 265 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_BINDREQ   0x0001
 

Definition at line 263 of file rtp.c.

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

#define STUN_BINDRESP   0x0101
 

Definition at line 264 of file rtp.c.

Referenced by stun_handle_packet(), and stun_msg2str().

#define STUN_CHANGE_REQUEST   0x0003
 

Definition at line 272 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005
 

Definition at line 274 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009
 

Definition at line 278 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_IGNORE   (0)
 

Definition at line 260 of file rtp.c.

Referenced by stun_handle_packet().

#define STUN_MAPPED_ADDRESS   0x0001
 

Definition at line 270 of file rtp.c.

Referenced by stun_attr2str(), and stun_handle_packet().

#define STUN_MESSAGE_INTEGRITY   0x0008
 

Definition at line 277 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007
 

Definition at line 276 of file rtp.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b
 

Definition at line 280 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002
 

Definition at line 271 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112
 

Definition at line 268 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002
 

Definition at line 266 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102
 

Definition at line 267 of file rtp.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004
 

Definition at line 273 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a
 

Definition at line 279 of file rtp.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006
 

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

References stun_addr::addr.

Referenced by stun_handle_packet().

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

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

Definition at line 355 of file rtp.c.

Referenced by ast_rtp_stun_request(), and stun_handle_packet().

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

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

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

int ast_rtcp_fd struct ast_rtp rtp  ) 
 

Definition at line 519 of file rtp.c.

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

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

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

static struct ast_rtcp* ast_rtcp_new void   )  [static]
 

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

Definition at line 1873 of file rtp.c.

References ast_calloc, ast_log(), free, LOG_WARNING, rtp_socket(), and ast_rtcp::s.

Referenced by ast_rtp_new_with_bindaddr().

01874 {
01875    struct ast_rtcp *rtcp;
01876 
01877    if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
01878       return NULL;
01879    rtcp->s = rtp_socket();
01880    rtcp->us.sin_family = AF_INET;
01881    rtcp->them.sin_family = AF_INET;
01882 
01883    if (rtcp->s < 0) {
01884       free(rtcp);
01885       ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
01886       return NULL;
01887    }
01888 
01889    return rtcp;
01890 }

struct ast_frame* ast_rtcp_read struct ast_rtp rtp  ) 
 

Definition at line 888 of file rtp.c.

References ast_rtcp::accumulated_transit, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), CRASH, ast_frame::datalen, ast_rtp::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().

00889 {
00890    socklen_t len;
00891    int position, i, packetwords;
00892    int res;
00893    struct sockaddr_in sin;
00894    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
00895    unsigned int *rtcpheader;
00896    int pt;
00897    struct timeval now;
00898    unsigned int length;
00899    int rc;
00900    double rtt = 0;
00901    double a;
00902    double dlsr;
00903    double lsr;
00904    unsigned int msw;
00905    unsigned int lsw;
00906    unsigned int comp;
00907    struct ast_frame *f = &ast_null_frame;
00908    
00909    if (!rtp || !rtp->rtcp)
00910       return &ast_null_frame;
00911 
00912    len = sizeof(sin);
00913    
00914    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
00915                0, (struct sockaddr *)&sin, &len);
00916    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
00917    
00918    if (res < 0) {
00919       if (errno != EAGAIN)
00920          ast_log(LOG_WARNING, "RTCP Read error: %s\n", strerror(errno));
00921       if (errno == EBADF)
00922          CRASH;
00923       return &ast_null_frame;
00924    }
00925 
00926    packetwords = res / 4;
00927    
00928    if (rtp->nat) {
00929       /* Send to whoever sent to us */
00930       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00931           (rtp->rtcp->them.sin_port != sin.sin_port)) {
00932          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00933          if (option_debug || rtpdebug)
00934             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));
00935       }
00936    }
00937 
00938    if (option_debug)
00939       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00940 
00941    /* Process a compound packet */
00942    position = 0;
00943    while (position < packetwords) {
00944       i = position;
00945       length = ntohl(rtcpheader[i]);
00946       pt = (length & 0xff0000) >> 16;
00947       rc = (length & 0x1f000000) >> 24;
00948       length &= 0xffff;
00949     
00950       if ((i + length) > packetwords) {
00951          ast_log(LOG_WARNING, "RTCP Read too short\n");
00952          return &ast_null_frame;
00953       }
00954       
00955       if (rtcp_debug_test_addr(&sin)) {
00956          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00957          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
00958          ast_verbose("Reception reports: %d\n", rc);
00959          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
00960       }
00961     
00962       i += 2; /* Advance past header and ssrc */
00963       
00964       switch (pt) {
00965       case RTCP_PT_SR:
00966          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
00967          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
00968          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
00969          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff) >> 16); /* Going to LSR in RR*/
00970     
00971          if (rtcp_debug_test_addr(&sin)) {
00972             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
00973             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
00974             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
00975          }
00976          i += 5;
00977          if (rc < 1)
00978             break;
00979          /* Intentional fall through */
00980       case RTCP_PT_RR:
00981          /* This is the place to calculate RTT */
00982          /* Don't handle multiple reception reports (rc > 1) yet */
00983          gettimeofday(&now, NULL);
00984          timeval2ntp(now, &msw, &lsw);
00985          /* Use the one we sent them in our SR instead, rtcp->txlsr could have been rewritten if the dlsr is large */
00986          if (ntohl(rtcpheader[i + 4])) { /* We must have the LSR */
00987             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
00988             a = (double)((comp & 0xffff0000) >> 16) + (double)((double)(comp & 0xffff)/1000000.);
00989             lsr = (double)((ntohl(rtcpheader[i + 4]) & 0xffff0000) >> 16) + (double)((double)(ntohl(rtcpheader[i + 4]) & 0xffff) / 1000000.);
00990             dlsr = (double)(ntohl(rtcpheader[i + 5])/65536.);
00991             rtt = a - dlsr - lsr;
00992             rtp->rtcp->accumulated_transit += rtt;
00993             rtp->rtcp->rtt = rtt;
00994             if (rtp->rtcp->maxrtt<rtt)
00995                rtp->rtcp->maxrtt = rtt;
00996             if (rtp->rtcp->minrtt>rtt)
00997             rtp->rtcp->minrtt = rtt;
00998          }
00999          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01000          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01001          if (rtcp_debug_test_addr(&sin)) {
01002             ast_verbose("Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01003             ast_verbose("Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01004             ast_verbose("Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01005             ast_verbose("Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01006             ast_verbose("Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01007             ast_verbose("Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01008             ast_verbose("DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01009             if (rtt)
01010                ast_verbose("RTT: %f(sec)\n", rtt);
01011          }
01012          break;
01013       case RTCP_PT_FUR:
01014          if (rtcp_debug_test_addr(&sin))
01015             ast_verbose("Received an RTCP Fast Update Request\n");
01016          rtp->f.frametype = AST_FRAME_CONTROL;
01017          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
01018          rtp->f.datalen = 0;
01019          rtp->f.samples = 0;
01020          rtp->f.mallocd = 0;
01021          rtp->f.src = "RTP";
01022          f = &rtp->f;
01023          break;
01024       case RTCP_PT_SDES:
01025          if (rtcp_debug_test_addr(&sin))
01026             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01027          break;
01028       case RTCP_PT_BYE:
01029          if (rtcp_debug_test_addr(&sin))
01030             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01031          break;
01032       default:
01033          if (option_debug)
01034             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));
01035          break;
01036       }
01037       position += (length + 1);
01038    }
01039          
01040    return f;
01041 }

int ast_rtcp_send_h261fur void *  data  ) 
 

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

Definition at line 2329 of file rtp.c.

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

02330 {
02331    struct ast_rtp *rtp = data;
02332    int res;
02333 
02334    rtp->rtcp->sendfur = 1;
02335    res = ast_rtcp_write(data);
02336    
02337    return res;
02338 }

static int ast_rtcp_write 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 2554 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().

02555 {
02556    struct ast_rtp *rtp = data;
02557    int res;
02558    
02559    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
02560       res = ast_rtcp_write_sr(data);
02561    else
02562       res = ast_rtcp_write_rr(data);
02563    
02564    return res;
02565 }

static int ast_rtcp_write_rr void *  data  )  [static]
 

Send RTCP recipient's report.

Note:
Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos it can change mid call, and SDES can't)

Definition at line 2455 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, 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().

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

static int ast_rtcp_write_sr void *  data  )  [static]
 

Send RTCP sender's report.

Definition at line 2341 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, 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().

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

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

Referenced by process_sdp().

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

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

The RTP bridge.

Definition at line 3259 of file rtp.c.

References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, 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(), 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, option_debug, option_verbose, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

03260 {
03261    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03262    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03263    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03264    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03265    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03266    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03267    int codec0 = 0, codec1 = 0;
03268    void *pvt0 = NULL, *pvt1 = NULL;
03269 
03270    /* Lock channels */
03271    ast_channel_lock(c0);
03272    while (ast_channel_trylock(c1)) {
03273       ast_channel_unlock(c0);
03274       usleep(1);
03275       ast_channel_lock(c0);
03276    }
03277 
03278    /* Find channel driver interfaces */
03279    if (!(pr0 = get_proto(c0))) {
03280       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03281       ast_channel_unlock(c0);
03282       ast_channel_unlock(c1);
03283       return AST_BRIDGE_FAILED;
03284    }
03285    if (!(pr1 = get_proto(c1))) {
03286       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03287       ast_channel_unlock(c0);
03288       ast_channel_unlock(c1);
03289       return AST_BRIDGE_FAILED;
03290    }
03291 
03292    /* Get channel specific interface structures */
03293    pvt0 = c0->tech_pvt;
03294    pvt1 = c1->tech_pvt;
03295 
03296    /* Get audio and video interface (if native bridge is possible) */
03297    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03298    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03299    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03300    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03301 
03302    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03303    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03304       audio_p0_res = AST_RTP_GET_FAILED;
03305    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03306       audio_p1_res = AST_RTP_GET_FAILED;
03307 
03308    /* Check if a bridge is possible (partial/native) */
03309    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03310       /* Somebody doesn't want to play... */
03311       ast_channel_unlock(c0);
03312       ast_channel_unlock(c1);
03313       return AST_BRIDGE_FAILED_NOWARN;
03314    }
03315 
03316    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03317    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03318       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03319       audio_p0_res = AST_RTP_TRY_PARTIAL;
03320    }
03321 
03322    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03323       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03324       audio_p1_res = AST_RTP_TRY_PARTIAL;
03325    }
03326 
03327    /* If both sides are not using the same method of DTMF transmission 
03328     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03329     * --------------------------------------------------
03330     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03331     * |-----------|------------|-----------------------|
03332     * | Inband    | False      | True                  |
03333     * | RFC2833   | True       | True                  |
03334     * | SIP INFO  | False      | False                 |
03335     * --------------------------------------------------
03336     * However, if DTMF from both channels is being monitored by the core, then
03337     * we can still do packet-to-packet bridging, because passing through the 
03338     * core will handle DTMF mode translation.
03339     */
03340    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03341        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03342       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03343          ast_channel_unlock(c0);
03344          ast_channel_unlock(c1);
03345          return AST_BRIDGE_FAILED_NOWARN;
03346       }
03347       audio_p0_res = AST_RTP_TRY_PARTIAL;
03348       audio_p1_res = AST_RTP_TRY_PARTIAL;
03349    }
03350 
03351    /* Get codecs from both sides */
03352    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03353    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03354    if (codec0 && codec1 && !(codec0 & codec1)) {
03355       /* Hey, we can't do native bridging if both parties speak different codecs */
03356       if (option_debug > 2)
03357          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03358       ast_channel_unlock(c0);
03359       ast_channel_unlock(c1);
03360       return AST_BRIDGE_FAILED_NOWARN;
03361    }
03362 
03363    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03364    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03365       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03366       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03367          if (option_debug)
03368             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03369          ast_channel_unlock(c0);
03370          ast_channel_unlock(c1);
03371          return AST_BRIDGE_FAILED_NOWARN;
03372       }
03373       if (option_verbose > 2)
03374          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03375       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03376    } else {
03377       if (option_verbose > 2) 
03378          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03379       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03380    }
03381 
03382    return res;
03383 }

int ast_rtp_codec_getformat int  pt  ) 
 

get format from predefined dynamic payload format

Definition at line 2711 of file rtp.c.

References rtpPayloadType::code, MAX_RTP_PT, and static_RTP_PT.

02712 {
02713    if (pt < 0 || pt > MAX_RTP_PT)
02714       return 0; /* bogus payload type */
02715 
02716    if (static_RTP_PT[pt].isAstFormat)
02717       return static_RTP_PT[pt].code;
02718    else
02719       return 0;
02720 }

struct ast_codec_pref* ast_rtp_codec_getpref struct ast_rtp rtp  ) 
 

Get codec preference

Definition at line 2706 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp().

02707 {
02708    return &rtp->pref;
02709 }

int ast_rtp_codec_setpref struct ast_rtp rtp,
struct ast_codec_pref prefs
 

Set codec preference

Definition at line 2693 of file rtp.c.

References ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, and prefs.

Referenced by __oh323_rtp_create(), check_peer_ok(), check_user_full(), check_user_ok(), create_addr_from_peer(), register_verify(), set_peer_capabilities(), start_rtp(), transmit_response_with_attachment(), and transmit_response_with_sdp().

02694 {
02695    int x;
02696    for (x = 0; x < 32; x++) {  /* Ugly way */
02697       rtp->pref.order[x] = prefs->order[x];
02698       rtp->pref.framing[x] = prefs->framing[x];
02699    }
02700    if (rtp->smoother)
02701       ast_smoother_free(rtp->smoother);
02702    rtp->smoother = NULL;
02703    return 0;
02704 }

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

Destroy RTP session

Definition at line 2111 of file rtp.c.

References ast_io_remove(), ast_mutex_destroy(), ast_sched_del(), ast_smoother_free(), ast_verbose(), 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(), rtcpstats, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtp::s, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.

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

02112 {
02113    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02114       /*Print some info on the call here */
02115       ast_verbose("  RTP-stats\n");
02116       ast_verbose("* Our Receiver:\n");
02117       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02118       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02119       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02120       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02121       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02122       ast_verbose("  RR-count:    %u\n", rtp->rtcp->rr_count);
02123       ast_verbose("* Our Sender:\n");
02124       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02125       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02126       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->reported_lost);
02127       ast_verbose("  Jitter:      %u\n", rtp->rtcp->reported_jitter);
02128       ast_verbose("  SR-count:    %u\n", rtp->rtcp->sr_count);
02129       ast_verbose("  RTT:      %f\n", rtp->rtcp->rtt);
02130    }
02131 
02132    if (rtp->smoother)
02133       ast_smoother_free(rtp->smoother);
02134    if (rtp->ioid)
02135       ast_io_remove(rtp->io, rtp->ioid);
02136    if (rtp->s > -1)
02137       close(rtp->s);
02138    if (rtp->rtcp) {
02139       if (rtp->rtcp->schedid > 0)
02140          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02141       close(rtp->rtcp->s);
02142       free(rtp->rtcp);
02143       rtp->rtcp=NULL;
02144    }
02145 #ifdef P2P_INTENSE
02146    ast_mutex_destroy(&rtp->bridge_lock);
02147 #endif
02148    free(rtp);
02149 }

int ast_rtp_early_bridge struct ast_channel c0,
struct ast_channel c1
 

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

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

01523 {
01524    // dest = c0, src = c1
01525    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01526    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01527    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01528    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01529    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
01530    int srccodec, nat_active = 0;
01531 
01532    /* Lock channels */
01533    ast_channel_lock(c0);
01534    if (c1) {
01535       while (ast_channel_trylock(c1)) {
01536          ast_channel_unlock(c0);
01537          usleep(1);
01538          ast_channel_lock(c0);
01539       }
01540    }
01541 
01542    /* Find channel driver interfaces */
01543    destpr = get_proto(c0);
01544    if (c1)
01545       srcpr = get_proto(c1);
01546    if (!destpr) {
01547       if (option_debug)
01548          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", c0->name);
01549       ast_channel_unlock(c0);
01550       if (c1)
01551          ast_channel_unlock(c1);
01552       return -1;
01553    }
01554    if (!srcpr) {
01555       if (option_debug)
01556          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
01557       ast_channel_unlock(c0);
01558       if (c1)
01559          ast_channel_unlock(c1);
01560       return -1;
01561    }
01562 
01563    /* Get audio and video interface (if native bridge is possible) */
01564    audio_dest_res = destpr->get_rtp_info(c0, &destp);
01565    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
01566    if (srcpr) {
01567       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
01568       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
01569    }
01570 
01571    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01572    if (audio_dest_res != AST_RTP_TRY_NATIVE) {
01573       /* Somebody doesn't want to play... */
01574       ast_channel_unlock(c0);
01575       if (c1)
01576          ast_channel_unlock(c1);
01577       return -1;
01578    }
01579    if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec)
01580       srccodec = srcpr->get_codec(c1);
01581    else
01582       srccodec = 0;
01583    /* Consider empty media as non-existant */
01584    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
01585       srcp = NULL;
01586    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01587       nat_active = 1;
01588    /* Bridge media early */
01589    if (destpr->set_rtp_peer(c0, srcp, vsrcp, srccodec, nat_active))
01590       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
01591    ast_channel_unlock(c0);
01592    if (c1)
01593       ast_channel_unlock(c1);
01594    if (option_debug)
01595       ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
01596    return 0;
01597 }

int ast_rtp_fd struct ast_rtp rtp  ) 
 

Definition at line 514 of file rtp.c.

References ast_rtp::s.

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

00515 {
00516    return rtp->s;
00517 }

struct ast_rtp* ast_rtp_get_bridged struct ast_rtp rtp  ) 
 

Definition at line 2045 of file rtp.c.

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

Referenced by ast_rtp_read(), and check_rtp_timeout().

02046 {
02047    struct ast_rtp *bridged = NULL;
02048 
02049    rtp_bridge_lock(rtp);
02050    bridged = rtp->bridged;
02051    rtp_bridge_unlock(rtp);
02052 
02053    return bridged;
02054 }

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

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

Referenced by process_sdp().

01713 {
01714    int pt;
01715    
01716    rtp_bridge_lock(rtp);
01717    
01718    *astFormats = *nonAstFormats = 0;
01719    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01720       if (rtp->current_RTP_PT[pt].isAstFormat) {
01721          *astFormats |= rtp->current_RTP_PT[pt].code;
01722       } else {
01723          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01724       }
01725    }
01726 
01727    rtp_bridge_unlock(rtp);
01728    
01729    return;
01730 }

int ast_rtp_get_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 2027 of file rtp.c.

References ast_rtp::them.

Referenced by add_sdp(), bridge_native_loop(), check_rtp_timeout(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().

02028 {
02029    if ((them->sin_family != AF_INET) ||
02030       (them->sin_port != rtp->them.sin_port) ||
02031       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02032       them->sin_family = AF_INET;
02033       them->sin_port = rtp->them.sin_port;
02034       them->sin_addr = rtp->them.sin_addr;
02035       return 1;
02036    }
02037    return 0;
02038 }

char* ast_rtp_get_quality struct ast_rtp rtp  ) 
 

Definition at line 2093 of file rtp.c.

References ast_rtcp::expected_prior, ast_rtcp::quality, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by handle_request_bye(), and sip_hangup().

02094 {
02095    /*
02096    *ssrc          our ssrc
02097    *themssrc      their ssrc
02098    *lp            lost packets
02099    *rxjitter      our calculated jitter(rx)
02100    *rxcount       no. received packets
02101    *txjitter      reported jitter of the other end
02102    *txcount       transmitted packets
02103    *rlp           remote lost packets
02104    */
02105    
02106    snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt);
02107    
02108    return rtp->rtcp->quality;
02109 }

int ast_rtp_get_rtpholdtimeout struct ast_rtp rtp  ) 
 

Get rtp hold timeout.

Definition at line 569 of file rtp.c.

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

Referenced by check_rtp_timeout().

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

int ast_rtp_get_rtpkeepalive struct ast_rtp rtp  ) 
 

Get RTP keepalive interval.

Definition at line 577 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00578 {
00579    return rtp->rtpkeepalive;
00580 }

int ast_rtp_get_rtptimeout struct ast_rtp rtp  ) 
 

Get rtp timeout.

Definition at line 561 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

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

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 2040 of file rtp.c.

References ast_rtp::us.

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

02041 {
02042    *us = rtp->us;
02043 }

int ast_rtp_getnat struct ast_rtp rtp  ) 
 

Definition at line 597 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init void   ) 
 

Return RTCP quality string.

Definition at line 3664 of file rtp.c.

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

03665 {
03666    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03667    ast_rtp_reload();
03668 }

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

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

Referenced by add_codec_to_answer(), add_codec_to_sdp(), add_noncodec_to_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), and bridge_p2p_rtp_write().

01755 {
01756    int pt = 0;
01757 
01758    rtp_bridge_lock(rtp);
01759 
01760    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
01761       code == rtp->rtp_lookup_code_cache_code) {
01762       /* Use our cached mapping, to avoid the overhead of the loop below */
01763       pt = rtp->rtp_lookup_code_cache_result;
01764       rtp_bridge_unlock(rtp);
01765       return pt;
01766    }
01767 
01768    /* Check the dynamic list first */
01769    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01770       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
01771          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01772          rtp->rtp_lookup_code_cache_code = code;
01773          rtp->rtp_lookup_code_cache_result = pt;
01774          rtp_bridge_unlock(rtp);
01775          return pt;
01776       }
01777    }
01778 
01779    /* Then the static list */
01780    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01781       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
01782          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01783          rtp->rtp_lookup_code_cache_code = code;
01784          rtp->rtp_lookup_code_cache_result = pt;
01785          rtp_bridge_unlock(rtp);
01786          return pt;
01787       }
01788    }
01789 
01790    rtp_bridge_unlock(rtp);
01791 
01792    return -1;
01793 }

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

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

01816 {
01817    int format;
01818    unsigned len;
01819    char *end = buf;
01820    char *start = buf;
01821 
01822    if (!buf || !size)
01823       return NULL;
01824 
01825    snprintf(end, size, "0x%x (", capability);
01826 
01827    len = strlen(end);
01828    end += len;
01829    size -= len;
01830    start = end;
01831 
01832    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01833       if (capability & format) {
01834          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01835 
01836          snprintf(end, size, "%s|", name);
01837          len = strlen(end);
01838          end += len;
01839          size -= len;
01840       }
01841    }
01842 
01843    if (start == end)
01844       snprintf(start, size, "nothing)"); 
01845    else if (size > 1)
01846       *(end -1) = ')';
01847    
01848    return buf;
01849 }

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

01797 {
01798    unsigned int i;
01799 
01800    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01801       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01802          if (isAstFormat &&
01803              (code == AST_FORMAT_G726_AAL2) &&
01804              (options & AST_RTP_OPT_G726_NONSTANDARD))
01805             return "G726-32";
01806          else
01807             return mimeTypes[i].subtype;
01808       }
01809    }
01810 
01811    return "";
01812 }

struct rtpPayloadType ast_rtp_lookup_pt struct ast_rtp rtp,
int  pt
 

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1732 of file rtp.c.

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

01733 {
01734    struct rtpPayloadType result;
01735 
01736    result.isAstFormat = result.code = 0;
01737 
01738    if (pt < 0 || pt > MAX_RTP_PT) 
01739       return result; /* bogus payload type */
01740 
01741    /* Start with negotiated codecs */
01742    rtp_bridge_lock(rtp);
01743    result = rtp->current_RTP_PT[pt];
01744    rtp_bridge_unlock(rtp);
01745 
01746    /* If it doesn't exist, check our static RTP type list, just in case */
01747    if (!result.code) 
01748       result = static_RTP_PT[pt];
01749 
01750    return result;
01751 }

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

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

01600 {
01601    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01602    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01603    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01604    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01605    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 
01606    int srccodec;
01607 
01608    /* Lock channels */
01609    ast_channel_lock(dest);
01610    while (ast_channel_trylock(src)) {
01611       ast_channel_unlock(dest);
01612       usleep(1);
01613       ast_channel_lock(dest);
01614    }
01615 
01616    /* Find channel driver interfaces */
01617    if (!(destpr = get_proto(dest))) {
01618       if (option_debug)
01619          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01620       ast_channel_unlock(dest);
01621       ast_channel_unlock(src);
01622       return 0;
01623    }
01624    if (!(srcpr = get_proto(src))) {
01625       if (option_debug)
01626          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
01627       ast_channel_unlock(dest);
01628       ast_channel_unlock(src);
01629       return 0;
01630    }
01631 
01632    /* Get audio and video interface (if native bridge is possible) */
01633    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01634    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01635    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01636    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01637 
01638    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01639    if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE) {
01640       /* Somebody doesn't want to play... */
01641       ast_channel_unlock(dest);
01642       ast_channel_unlock(src);
01643       return 0;
01644    }
01645    ast_rtp_pt_copy(destp, srcp);
01646    if (vdestp && vsrcp)
01647       ast_rtp_pt_copy(vdestp, vsrcp);
01648    if (srcpr->get_codec)
01649       srccodec = srcpr->get_codec(src);
01650    else
01651       srccodec = 0;
01652    if (media) {
01653       /* Bridge early */
01654       if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01655          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
01656    }
01657    ast_channel_unlock(dest);
01658    ast_channel_unlock(src);
01659    if (option_debug)
01660       ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
01661    return 1;
01662 }

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

Initializate a RTP session.

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

Definition at line 1999 of file rtp.c.

References ast_rtp_new_with_bindaddr(), io, and sched.

02000 {
02001    struct in_addr ia;
02002 
02003    memset(&ia, 0, sizeof(ia));
02004    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02005 }

void ast_rtp_new_init struct ast_rtp rtp  ) 
 

Initialize a new RTP structure.

reload rtp configuration

Definition at line 1896 of file rtp.c.

References ast_mutex_init(), ast_random(), ast_set_flag, 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().

01897 {
01898 #ifdef P2P_INTENSE
01899    ast_mutex_init(&rtp->bridge_lock);
01900 #endif
01901 
01902    rtp->them.sin_family = AF_INET;
01903    rtp->us.sin_family = AF_INET;
01904    rtp->ssrc = ast_random();
01905    rtp->seqno = ast_random() & 0xffff;
01906    ast_set_flag(rtp, FLAG_HAS_DTMF);
01907 
01908    return;
01909 }

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

Initializate a RTP session using an in_addr structure.

This fuction gets called by ast_rtp_new().

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

Definition at line 1911 of file rtp.c.

References ast_calloc, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), free, LOG_ERROR, rtp_socket(), rtpend, rtpstart, and sched.

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

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

int ast_rtp_proto_register struct ast_rtp_protocol proto  ) 
 

Register an RTP channel client.

Definition at line 2809 of file rtp.c.

References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, protos, and ast_rtp_protocol::type.

Referenced by load_module(), and register_rtp_and_udptl().

02810 {
02811    struct ast_rtp_protocol *cur;
02812 
02813    AST_RWLIST_WRLOCK(&protos);
02814    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
02815       if (!strcmp(cur->type, proto->type)) {
02816          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02817          AST_RWLIST_UNLOCK(&protos);
02818          return -1;
02819       }
02820    }
02821    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
02822    AST_RWLIST_UNLOCK(&protos);
02823    
02824    return 0;
02825 }

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

Unregister an RTP channel client.

Definition at line 2801 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and protos.

Referenced by load_module(), unload_module(), and unregister_rtp_and_udptl().

02802 {
02803    AST_RWLIST_WRLOCK(&protos);
02804    AST_RWLIST_REMOVE(&protos, proto, list);
02805    AST_RWLIST_UNLOCK(&protos);
02806 }

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

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

Definition at line 1446 of file rtp.c.

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

Referenced by process_sdp().

01447 {
01448    int i;
01449 
01450    if (!rtp)
01451       return;
01452 
01453    rtp_bridge_lock(rtp);
01454 
01455    for (i = 0; i < MAX_RTP_PT; ++i) {
01456       rtp->current_RTP_PT[i].isAstFormat = 0;
01457       rtp->current_RTP_PT[i].code = 0;
01458    }
01459 
01460    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01461    rtp->rtp_lookup_code_cache_code = 0;
01462    rtp->rtp_lookup_code_cache_result = 0;
01463 
01464    rtp_bridge_unlock(rtp);
01465 }

void ast_rtp_pt_copy struct ast_rtp dest,
struct ast_rtp src
 

Copy payload types between RTP structures.

Definition at line 1486 of file rtp.c.

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

Referenced by ast_rtp_make_compatible().

01487 {
01488    unsigned int i;
01489 
01490    rtp_bridge_lock(dest);
01491    rtp_bridge_lock(src);
01492 
01493    for (i=0; i < MAX_RTP_PT; ++i) {
01494       dest->current_RTP_PT[i].isAstFormat = 
01495          src->current_RTP_PT[i].isAstFormat;
01496       dest->current_RTP_PT[i].code = 
01497          src->current_RTP_PT[i].code; 
01498    }
01499    dest->rtp_lookup_code_cache_isAstFormat = 0;
01500    dest->rtp_lookup_code_cache_code = 0;
01501    dest->rtp_lookup_code_cache_result = 0;
01502 
01503    rtp_bridge_unlock(src);
01504    rtp_bridge_unlock(dest);
01505 }

void ast_rtp_pt_default struct ast_rtp rtp  ) 
 

Set payload types to defaults.

Definition at line 1467 of file rtp.c.

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

01468 {
01469    int i;
01470 
01471    rtp_bridge_lock(rtp);
01472 
01473    /* Initialize to default payload types */
01474    for (i = 0; i < MAX_RTP_PT; ++i) {
01475       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01476       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01477    }
01478 
01479    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01480    rtp->rtp_lookup_code_cache_code = 0;
01481    rtp->rtp_lookup_code_cache_result = 0;
01482 
01483    rtp_bridge_unlock(rtp);
01484 }

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

Write RTP packet with audio or video media frames into UDP packet.

Definition at line 2603 of file rtp.c.

References AST_FORMAT_MAX_AUDIO, 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, ast_rtp::f, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_frame::has_timing_info, 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(), rtpdebug, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, ast_rtp::them, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

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

struct ast_frame* ast_rtp_read struct ast_rtp rtp  ) 
 

Definition at line 1144 of file rtp.c.

References ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, 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, CRASH, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, event, ext, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_frame::has_timing_info, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len, ast_frame::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_rtp::them, ast_rtcp::them, ast_rtp::themssrc, and ast_frame::ts.

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

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

int ast_rtp_reload void   ) 
 

Initialize RTP subsystem

Definition at line 3599 of file rtp.c.

References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, dtmftimeout, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, s, and VERBOSE_PREFIX_2.

Referenced by ast_rtp_init().

03600 {
03601    struct ast_config *cfg;
03602    const char *s;
03603 
03604    rtpstart = 5000;
03605    rtpend = 31000;
03606    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03607    cfg = ast_config_load("rtp.conf");
03608    if (cfg) {
03609       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03610          rtpstart = atoi(s);
03611          if (rtpstart < 1024)
03612             rtpstart = 1024;
03613          if (rtpstart > 65535)
03614             rtpstart = 65535;
03615       }
03616       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03617          rtpend = atoi(s);
03618          if (rtpend < 1024)
03619             rtpend = 1024;
03620          if (rtpend > 65535)
03621             rtpend = 65535;
03622       }
03623       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03624          rtcpinterval = atoi(s);
03625          if (rtcpinterval == 0)
03626             rtcpinterval = 0; /* Just so we're clear... it's zero */
03627          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03628             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03629          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03630             rtcpinterval = RTCP_MAX_INTERVALMS;
03631       }
03632       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03633 #ifdef SO_NO_CHECK
03634          if (ast_false(s))
03635             nochecksums = 1;
03636          else
03637             nochecksums = 0;
03638 #else
03639          if (ast_false(s))
03640             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03641 #endif
03642       }
03643       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03644          dtmftimeout = atoi(s);
03645          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03646             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03647                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03648             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03649          };
03650       }
03651       ast_config_destroy(cfg);
03652    }
03653    if (rtpstart >= rtpend) {
03654       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03655       rtpstart = 5000;
03656       rtpend = 31000;
03657    }
03658    if (option_verbose > 1)
03659       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03660    return 0;
03661 }

void ast_rtp_reset struct ast_rtp rtp  ) 
 

Definition at line 2073 of file rtp.c.

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

02074 {
02075    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02076    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02077    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02078    rtp->lastts = 0;
02079    rtp->lastdigitts = 0;
02080    rtp->lastrxts = 0;
02081    rtp->lastividtimestamp = 0;
02082    rtp->lastovidtimestamp = 0;
02083    rtp->lasteventseqn = 0;
02084    rtp->lasteventendseqn = 0;
02085    rtp->lasttxformat = 0;
02086    rtp->lastrxformat = 0;
02087    rtp->dtmfcount = 0;
02088    rtp->dtmfsamples = 0;
02089    rtp->seqno = 0;
02090    rtp->rxseqno = 0;
02091 }

int ast_rtp_sendcng struct ast_rtp rtp,
int  level
 

generate comfort noice (CNG)

Definition at line 2568 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, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by check_rtp_timeout().

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

int ast_rtp_senddigit_begin struct ast_rtp rtp,
char  digit
 

Send begin frames for DTMF.

Definition at line 2171 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_duration, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by oh323_digit_begin(), and sip_senddigit_begin().

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

static int ast_rtp_senddigit_continuation struct ast_rtp rtp  )  [static]
 

Send continuation frame for DTMF.

Definition at line 2235 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_verbose(), 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().

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

int ast_rtp_senddigit_end struct ast_rtp rtp,
char  digit
 

Send end packets for DTMF.

Definition at line 2272 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by oh323_digit_end(), and sip_senddigit_end().

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

void ast_rtp_set_callback struct ast_rtp rtp,
ast_rtp_callback  callback
 

Definition at line 587 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data struct ast_rtp rtp,
void *  data
 

Definition at line 582 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

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

Definition at line 1668 of file rtp.c.

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

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

01669 {
01670    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01671       return; /* bogus payload type */
01672 
01673    rtp_bridge_lock(rtp);
01674    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01675    rtp_bridge_unlock(rtp);
01676 } 

void ast_rtp_set_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 2016 of file rtp.c.

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

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

02017 {
02018    rtp->them.sin_port = them->sin_port;
02019    rtp->them.sin_addr = them->sin_addr;
02020    if (rtp->rtcp) {
02021       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02022       rtp->rtcp->them.sin_addr = them->sin_addr;
02023    }
02024    rtp->rxseqno = 0;
02025 }

void ast_rtp_set_rtpholdtimeout struct ast_rtp rtp,
int  timeout
 

Set rtp hold timeout.

Definition at line 549 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

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

void ast_rtp_set_rtpkeepalive struct ast_rtp rtp,
int  period
 

set RTP keepalive interval

Definition at line 555 of file rtp.c.

References ast_rtp::rtpkeepalive.

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

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

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

Definition at line 1681 of file rtp.c.

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

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

01684 {
01685    unsigned int i;
01686 
01687    if (pt < 0 || pt > MAX_RTP_PT) 
01688       return; /* bogus payload type */
01689    
01690    rtp_bridge_lock(rtp);
01691 
01692    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01693       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01694           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01695          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01696          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01697              mimeTypes[i].payloadType.isAstFormat &&
01698              (options & AST_RTP_OPT_G726_NONSTANDARD))
01699             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01700          break;
01701       }
01702    }
01703 
01704    rtp_bridge_unlock(rtp);
01705 
01706    return;
01707 } 

void ast_rtp_set_rtptimeout struct ast_rtp rtp,
int  timeout
 

Set rtp timeout.

Definition at line 543 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold struct ast_rtp rtp  ) 
 

Definition at line 536 of file rtp.c.

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

Referenced by handle_response_answer(), and handle_response_invite().

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

void ast_rtp_setdtmf struct ast_rtp rtp,
int  dtmf
 

Indicate whether this RTP session is carrying DTMF or not.

Definition at line 602 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_DTMF.

Referenced by create_addr_from_peer(), dialog_activate_media(), handle_request_invite(), and sip_alloc().

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

void ast_rtp_setdtmfcompensate struct ast_rtp rtp,
int  compensate
 

Compensate for devices that send RFC2833 packets all at once.

Definition at line 607 of file rtp.c.

References ast_set2_flag, and FLAG_DTMF_COMPENSATE.

Referenced by create_addr_from_peer(), dialog_activate_media(), handle_request_invite(), and sip_alloc().

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

void ast_rtp_setnat struct ast_rtp rtp,
int  nat
 

Definition at line 592 of file rtp.c.

References ast_rtp::nat.

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

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

void ast_rtp_setstun struct ast_rtp rtp,
int  stun_enable
 

Enable STUN capability.

Definition at line 612 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

int ast_rtp_settos struct ast_rtp rtp,
int  tos
 

Definition at line 2007 of file rtp.c.

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

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

02008 {
02009    int res;
02010 
02011    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
02012       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
02013    return res;
02014 }

void ast_rtp_stop struct ast_rtp rtp  ) 
 

Stop RTP session, do not destroy structure

Definition at line 2056 of file rtp.c.

References ast_clear_flag, ast_sched_del(), FLAG_P2P_SENT_MARK, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::them, and ast_rtcp::them.

Referenced by setup_rtp_connection(), and stop_media_flows().

02057 {
02058    if (rtp->rtcp && rtp->rtcp->schedid > 0) {
02059       ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02060       rtp->rtcp->schedid = -1;
02061    }
02062 
02063    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02064    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02065    if (rtp->rtcp) {
02066       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02067       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02068    }
02069    
02070    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02071 }

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

Send STUN request (??).

Definition at line 404 of file rtp.c.

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

Referenced by gtalk_update_stun(), and jingle_update_stun().

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

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame _f
 

Bug:
XXX this might never be free'd. Why do we do this?

Definition at line 2722 of file rtp.c.

References ast_codec_pref_getsize(), AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_getformatname(),