#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 | AST_LIST_HEAD_STATIC (protos, ast_rtp_protocol) |
List of current sessions. | |
static unsigned int | ast_rtcp_calc_interval (struct ast_rtp *rtp) |
int | ast_rtcp_fd (struct ast_rtp *rtp) |
static struct ast_rtcp * | ast_rtcp_new (void) |
Initialize a new RTCP session. | |
ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
int | ast_rtcp_send_h261fur (void *data) |
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP. | |
static int | ast_rtcp_write (const void *data) |
Write and RTCP packet to the far end. | |
static int | ast_rtcp_write_rr (const void *data) |
Send RTCP recepient's report. | |
static int | ast_rtcp_write_sr (const void *data) |
Send RTCP sender's report. | |
size_t | ast_rtp_alloc_size (void) |
Get the amount of space required to hold an RTP session. | |
enum ast_bridge_result | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk. | |
int | ast_rtp_codec_getformat (int pt) |
ast_codec_pref * | ast_rtp_codec_getpref (struct ast_rtp *rtp) |
int | ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs) |
void | ast_rtp_destroy (struct ast_rtp *rtp) |
int | ast_rtp_early_bridge (struct ast_channel *dest, struct ast_channel *src) |
If possible, create an early bridge directly between the devices without having to send a re-invite later. | |
int | ast_rtp_fd (struct ast_rtp *rtp) |
ast_rtp * | ast_rtp_get_bridged (struct ast_rtp *rtp) |
void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs. | |
int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
char * | ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual) |
Return RTCP quality string. | |
int | ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp) |
Get rtp hold timeout. | |
int | ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp) |
Get RTP keepalive interval. | |
int | ast_rtp_get_rtptimeout (struct ast_rtp *rtp) |
Get rtp timeout. | |
void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
int | ast_rtp_getnat (struct ast_rtp *rtp) |
void | ast_rtp_init (void) |
Initialize the RTP system in Asterisk. | |
int | ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code) |
Looks up an RTP code out of our *static* outbound list. | |
char * | ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options) |
Build a string of MIME subtype names from a capability list. | |
const char * | ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code, enum ast_rtp_options options) |
Mapping an Asterisk code into a MIME subtype (string):. | |
rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
Mapping between RTP payload format codes and Asterisk codes:. | |
int | ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media) |
ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
Initializate a RTP session. | |
void | ast_rtp_new_init (struct ast_rtp *rtp) |
Initialize a new RTP structure. | |
void | ast_rtp_new_source (struct ast_rtp *rtp) |
ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr) |
Initializate a RTP session using an in_addr structure. | |
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
Register interface to channel driver. | |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
Unregister interface to channel driver. | |
void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
Setting RTP payload types from lines in a SDP description:. | |
void | ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src) |
Copy payload types between RTP structures. | |
void | ast_rtp_pt_default (struct ast_rtp *rtp) |
Set payload types to defaults. | |
static int | ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec) |
ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
int | ast_rtp_reload (void) |
void | ast_rtp_reset (struct ast_rtp *rtp) |
int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
generate comfort noice (CNG) | |
int | ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit) |
Send begin frames for DTMF. | |
static int | ast_rtp_senddigit_continuation (struct ast_rtp *rtp) |
Send continuation frame for DTMF. | |
int | ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit) |
Send end packets for DTMF. | |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
Activate payload type. | |
void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
void | ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout) |
Set rtp hold timeout. | |
void | ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period) |
set RTP keepalive interval | |
int | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options) |
Initiate payload type to a known MIME media type for a codec. | |
void | ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout) |
Set rtp timeout. | |
void | ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp) |
void | ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf) |
Indicate whether this RTP session is carrying DTMF or not. | |
void | ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate) |
Compensate for devices that send RFC2833 packets all at once. | |
void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
void | ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable) |
Enable STUN capability. | |
int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
void | ast_rtp_stop (struct ast_rtp *rtp) |
void | ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username) |
void | ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt) |
clear payload type | |
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f) |
static enum ast_bridge_result | bridge_native_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1) |
Bridge loop for true native bridge (reinvite). | |
static enum ast_bridge_result | bridge_p2p_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1) |
Bridge loop for partial native bridge (packet2packet). | |
static int | bridge_p2p_rtp_write (struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen) |
Perform a Packet2Packet RTP write. | |
static void | calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark) |
static unsigned int | calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery) |
static struct ast_rtp_protocol * | get_proto (struct ast_channel *chan) |
Get channel driver interface structure. | |
static int | p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod) |
Helper function to switch a channel and RTP stream out of callback mode. | |
static int | p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod) |
P2P RTP Callback. | |
static void | p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1) |
Helper function that sets what an RTP structure is bridged to. | |
static struct ast_frame * | process_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len) |
static struct ast_frame * | process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp) |
Process RTP DTMF and events according to RFC 2833. | |
static struct ast_frame * | process_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len) |
Process Comfort Noise RTP. | |
static int | rtcp_debug_test_addr (struct sockaddr_in *addr) |
static int | rtcp_do_debug (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_ip (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_ip_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_do_stats (int fd, int argc, char *argv[]) |
static int | rtcp_do_stats_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_no_debug (int fd, int argc, char *argv[]) |
static int | rtcp_no_debug_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_no_stats (int fd, int argc, char *argv[]) |
static int | rtcp_no_stats_deprecated (int fd, int argc, char *argv[]) |
static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
static int | rtp_do_debug (int fd, int argc, char *argv[]) |
static int | rtp_do_debug_ip (int fd, int argc, char *argv[]) |
static int | rtp_no_debug (int fd, int argc, char *argv[]) |
static int | rtp_socket (void) |
static int | rtpread (int *id, int fd, short events, void *cbdata) |
static struct ast_frame * | send_dtmf (struct ast_rtp *rtp, enum ast_frame_type type) |
static const char * | stun_attr2str (int msg) |
static int | stun_do_debug (int fd, int argc, char *argv[]) |
static int | stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len) |
static const char * | stun_msg2str (int msg) |
static int | stun_no_debug (int fd, int argc, char *argv[]) |
static int | stun_process_attr (struct stun_state *state, struct stun_attr *attr) |
static void | stun_req_id (struct stun_header *req) |
static int | stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp) |
static void | timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw) |
Variables | |
static struct ast_cli_entry | cli_rtp [] |
static struct ast_cli_entry | cli_rtp_no_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_debug_ip_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_no_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_no_stats_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_stats_deprecated |
static struct ast_cli_entry | cli_stun_no_debug_deprecated |
static char | debug_usage [] |
static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
struct { | |
rtpPayloadType payloadType | |
char * subtype | |
char * type | |
} | mimeTypes [] |
static char | no_debug_usage [] |
stun_addr | packed |
stun_attr | packed |
stun_header | packed |
static char | rtcp_debug_usage [] |
static char | rtcp_no_debug_usage [] |
static char | rtcp_no_stats_usage [] |
static char | rtcp_stats_usage [] |
static int | rtcpdebug |
static struct sockaddr_in | rtcpdebugaddr |
static int | rtcpinterval = RTCP_DEFAULT_INTERVALMS |
static int | rtcpstats |
static int | rtpdebug |
static struct sockaddr_in | rtpdebugaddr |
static int | rtpend |
static int | rtpstart |
static struct rtpPayloadType | static_RTP_PT [MAX_RTP_PT] |
static char | stun_debug_usage [] |
static char | stun_no_debug_usage [] |
static int | stundebug |
Definition in file rtp.c.
#define DEFAULT_DTMF_TIMEOUT 3000 |
#define FLAG_3389_WARNING (1 << 0) |
#define FLAG_CALLBACK_MODE (1 << 6) |
Definition at line 194 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 195 of file rtp.c.
Referenced by ast_rtp_bridge(), ast_rtp_setdtmfcompensate(), process_rfc2833(), and send_dtmf().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 191 of file rtp.c.
Referenced by ast_rtp_bridge(), ast_rtp_new_init(), and ast_rtp_setdtmf().
#define FLAG_HAS_STUN (1 << 8) |
#define FLAG_NAT_ACTIVE (3 << 1) |
Definition at line 188 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 189 of file rtp.c.
Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().
#define FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
Definition at line 190 of file rtp.c.
Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().
#define FLAG_P2P_NEED_DTMF (1 << 5) |
#define FLAG_P2P_SENT_MARK (1 << 4) |
Definition at line 192 of file rtp.c.
Referenced by ast_rtp_stop(), bridge_p2p_loop(), and bridge_p2p_rtp_write().
#define MAX_TIMESTAMP_SKEW 640 |
Definition at line 60 of file rtp.c.
Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp().
#define RTCP_DEFAULT_INTERVALMS 5000 |
#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_BYE 203 |
#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 |
#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 |
#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) |
#define STUN_BINDERR 0x0111 |
#define STUN_BINDREQ 0x0001 |
Definition at line 262 of file rtp.c.
Referenced by ast_rtp_stun_request(), stun_handle_packet(), and stun_msg2str().
#define STUN_BINDRESP 0x0101 |
#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 |
Definition at line 274 of file rtp.c.
Referenced by ast_rtp_stun_request(), stun_attr2str(), stun_handle_packet(), and stun_process_attr().
static void append_attr_address | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
struct sockaddr_in * | sin, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 367 of file rtp.c.
References stun_addr::addr.
Referenced by stun_handle_packet().
00368 { 00369 int size = sizeof(**attr) + 8; 00370 struct stun_addr *addr; 00371 if (*left > size) { 00372 (*attr)->attr = htons(attrval); 00373 (*attr)->len = htons(8); 00374 addr = (struct stun_addr *)((*attr)->value); 00375 addr->unused = 0; 00376 addr->family = 0x01; 00377 addr->port = sin->sin_port; 00378 addr->addr = sin->sin_addr.s_addr; 00379 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00380 *len += size; 00381 *left -= size; 00382 } 00383 }
static void append_attr_string | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
const char * | s, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 354 of file rtp.c.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00355 { 00356 int size = sizeof(**attr) + strlen(s); 00357 if (*left > size) { 00358 (*attr)->attr = htons(attrval); 00359 (*attr)->len = htons(strlen(s)); 00360 memcpy((*attr)->value, s, strlen(s)); 00361 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00362 *len += size; 00363 *left -= size; 00364 } 00365 }
static AST_LIST_HEAD_STATIC | ( | protos | , | |
ast_rtp_protocol | ||||
) | [static] |
List of current sessions.
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 525 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00526 { 00527 unsigned int interval; 00528 /*! \todo XXX Do a more reasonable calculation on this one 00529 * Look in RFC 3550 Section A.7 for an example*/ 00530 interval = rtcpinterval; 00531 return interval; 00532 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 518 of file rtp.c.
References ast_rtp::rtcp, and ast_rtcp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), sip_new(), and start_rtp().
static struct ast_rtcp* ast_rtcp_new | ( | void | ) | [static] |
Initialize a new RTCP session.
Definition at line 1877 of file rtp.c.
References ast_calloc, ast_log(), errno, free, LOG_WARNING, rtp_socket(), and ast_rtcp::s.
Referenced by ast_rtp_new_with_bindaddr().
01878 { 01879 struct ast_rtcp *rtcp; 01880 01881 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01882 return NULL; 01883 rtcp->s = rtp_socket(); 01884 rtcp->us.sin_family = AF_INET; 01885 rtcp->them.sin_family = AF_INET; 01886 rtcp->schedid = -1; 01887 01888 if (rtcp->s < 0) { 01889 free(rtcp); 01890 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01891 return NULL; 01892 } 01893 01894 return rtcp; 01895 }
Definition at line 827 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, errno, f, 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().
00828 { 00829 socklen_t len; 00830 int position, i, packetwords; 00831 int res; 00832 struct sockaddr_in sin; 00833 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00834 unsigned int *rtcpheader; 00835 int pt; 00836 struct timeval now; 00837 unsigned int length; 00838 int rc; 00839 double rttsec; 00840 uint64_t rtt = 0; 00841 unsigned int dlsr; 00842 unsigned int lsr; 00843 unsigned int msw; 00844 unsigned int lsw; 00845 unsigned int comp; 00846 struct ast_frame *f = &ast_null_frame; 00847 00848 if (!rtp || !rtp->rtcp) 00849 return &ast_null_frame; 00850 00851 len = sizeof(sin); 00852 00853 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00854 0, (struct sockaddr *)&sin, &len); 00855 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00856 00857 if (res < 0) { 00858 if (errno == EBADF) 00859 CRASH; 00860 if (errno != EAGAIN) { 00861 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00862 return NULL; 00863 } 00864 return &ast_null_frame; 00865 } 00866 00867 packetwords = res / 4; 00868 00869 if (rtp->nat) { 00870 /* Send to whoever sent to us */ 00871 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00872 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00873 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00874 if (option_debug || rtpdebug) 00875 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)); 00876 } 00877 } 00878 00879 if (option_debug) 00880 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00881 00882 /* Process a compound packet */ 00883 position = 0; 00884 while (position < packetwords) { 00885 i = position; 00886 length = ntohl(rtcpheader[i]); 00887 pt = (length & 0xff0000) >> 16; 00888 rc = (length & 0x1f000000) >> 24; 00889 length &= 0xffff; 00890 00891 if ((i + length) > packetwords) { 00892 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00893 return &ast_null_frame; 00894 } 00895 00896 if (rtcp_debug_test_addr(&sin)) { 00897 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00898 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00899 ast_verbose("Reception reports: %d\n", rc); 00900 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00901 } 00902 00903 i += 2; /* Advance past header and ssrc */ 00904 00905 switch (pt) { 00906 case RTCP_PT_SR: 00907 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00908 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00909 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00910 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00911 00912 if (rtcp_debug_test_addr(&sin)) { 00913 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00914 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00915 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00916 } 00917 i += 5; 00918 if (rc < 1) 00919 break; 00920 /* Intentional fall through */ 00921 case RTCP_PT_RR: 00922 /* Don't handle multiple reception reports (rc > 1) yet */ 00923 /* Calculate RTT per RFC */ 00924 gettimeofday(&now, NULL); 00925 timeval2ntp(now, &msw, &lsw); 00926 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00927 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00928 lsr = ntohl(rtcpheader[i + 4]); 00929 dlsr = ntohl(rtcpheader[i + 5]); 00930 rtt = comp - lsr - dlsr; 00931 00932 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00933 sess->ee_delay = (eedelay * 1000) / 65536; */ 00934 if (rtt < 4294) { 00935 rtt = (rtt * 1000000) >> 16; 00936 } else { 00937 rtt = (rtt * 1000) >> 16; 00938 rtt *= 1000; 00939 } 00940 rtt = rtt / 1000.; 00941 rttsec = rtt / 1000.; 00942 00943 if (comp - dlsr >= lsr) { 00944 rtp->rtcp->accumulated_transit += rttsec; 00945 rtp->rtcp->rtt = rttsec; 00946 if (rtp->rtcp->maxrtt<rttsec) 00947 rtp->rtcp->maxrtt = rttsec; 00948 if (rtp->rtcp->minrtt>rttsec) 00949 rtp->rtcp->minrtt = rttsec; 00950 } else if (rtcp_debug_test_addr(&sin)) { 00951 ast_verbose("Internal RTCP NTP clock skew detected: " 00952 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 00953 "diff=%d\n", 00954 lsr, comp, dlsr, dlsr / 65536, 00955 (dlsr % 65536) * 1000 / 65536, 00956 dlsr - (comp - lsr)); 00957 } 00958 } 00959 00960 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00961 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00962 if (rtcp_debug_test_addr(&sin)) { 00963 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00964 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00965 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00966 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00967 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00968 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00969 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00970 if (rtt) 00971 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 00972 } 00973 break; 00974 case RTCP_PT_FUR: 00975 if (rtcp_debug_test_addr(&sin)) 00976 ast_verbose("Received an RTCP Fast Update Request\n"); 00977 rtp->f.frametype = AST_FRAME_CONTROL; 00978 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00979 rtp->f.datalen = 0; 00980 rtp->f.samples = 0; 00981 rtp->f.mallocd = 0; 00982 rtp->f.src = "RTP"; 00983 f = &rtp->f; 00984 break; 00985 case RTCP_PT_SDES: 00986 if (rtcp_debug_test_addr(&sin)) 00987 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00988 break; 00989 case RTCP_PT_BYE: 00990 if (rtcp_debug_test_addr(&sin)) 00991 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00992 break; 00993 default: 00994 if (option_debug) 00995 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)); 00996 break; 00997 } 00998 position += (length + 1); 00999 } 01000 01001 return f; 01002 }
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 2360 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02361 { 02362 struct ast_rtp *rtp = data; 02363 int res; 02364 02365 rtp->rtcp->sendfur = 1; 02366 res = ast_rtcp_write(data); 02367 02368 return res; 02369 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2577 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().
02578 { 02579 struct ast_rtp *rtp = (struct ast_rtp *)data; 02580 int res; 02581 02582 if (!rtp || !rtp->rtcp) 02583 return 0; 02584 02585 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02586 res = ast_rtcp_write_sr(data); 02587 else 02588 res = ast_rtcp_write_rr(data); 02589 02590 return res; 02591 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recepient's report.
Definition at line 2482 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), ast_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, len, LOG_ERROR, ast_rtcp::received_prior, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, and ast_rtp::themssrc.
Referenced by ast_rtcp_write().
02483 { 02484 struct ast_rtp *rtp = (struct ast_rtp *)data; 02485 int res; 02486 int len = 32; 02487 unsigned int lost; 02488 unsigned int extended; 02489 unsigned int expected; 02490 unsigned int expected_interval; 02491 unsigned int received_interval; 02492 int lost_interval; 02493 struct timeval now; 02494 unsigned int *rtcpheader; 02495 char bdata[1024]; 02496 struct timeval dlsr; 02497 int fraction; 02498 02499 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02500 return 0; 02501 02502 if (!rtp->rtcp->them.sin_addr.s_addr) { 02503 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02504 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02505 return 0; 02506 } 02507 02508 extended = rtp->cycles + rtp->lastrxseqno; 02509 expected = extended - rtp->seedrxseqno + 1; 02510 lost = expected - rtp->rxcount; 02511 expected_interval = expected - rtp->rtcp->expected_prior; 02512 rtp->rtcp->expected_prior = expected; 02513 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02514 rtp->rtcp->received_prior = rtp->rxcount; 02515 lost_interval = expected_interval - received_interval; 02516 if (expected_interval == 0 || lost_interval <= 0) 02517 fraction = 0; 02518 else 02519 fraction = (lost_interval << 8) / expected_interval; 02520 gettimeofday(&now, NULL); 02521 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02522 rtcpheader = (unsigned int *)bdata; 02523 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02524 rtcpheader[1] = htonl(rtp->ssrc); 02525 rtcpheader[2] = htonl(rtp->themssrc); 02526 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02527 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02528 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02529 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02530 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02531 02532 if (rtp->rtcp->sendfur) { 02533 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02534 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02535 len += 8; 02536 rtp->rtcp->sendfur = 0; 02537 } 02538 02539 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02540 it can change mid call, and SDES can't) */ 02541 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02542 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02543 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02544 len += 12; 02545 02546 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02547 02548 if (res < 0) { 02549 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02550 /* Remove the scheduler */ 02551 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02552 return 0; 02553 } 02554 02555 rtp->rtcp->rr_count++; 02556 02557 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02558 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02559 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02560 " IA jitter: %.4f\n" 02561 " Their last SR: %u\n" 02562 " DLSR: %4.4f (sec)\n\n", 02563 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02564 ntohs(rtp->rtcp->them.sin_port), 02565 rtp->ssrc, rtp->themssrc, fraction, lost, 02566 rtp->rxjitter, 02567 rtp->rtcp->themrxlsr, 02568 (double)(ntohl(rtcpheader[7])/65536.0)); 02569 } 02570 02571 return res; 02572 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2372 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), ast_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len, LOG_ERROR, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.
Referenced by ast_rtcp_write().
02373 { 02374 struct ast_rtp *rtp = (struct ast_rtp *)data; 02375 int res; 02376 int len = 0; 02377 struct timeval now; 02378 unsigned int now_lsw; 02379 unsigned int now_msw; 02380 unsigned int *rtcpheader; 02381 unsigned int lost; 02382 unsigned int extended; 02383 unsigned int expected; 02384 unsigned int expected_interval; 02385 unsigned int received_interval; 02386 int lost_interval; 02387 int fraction; 02388 struct timeval dlsr; 02389 char bdata[512]; 02390 02391 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02392 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02393 return 0; 02394 02395 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02396 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02397 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02398 return 0; 02399 } 02400 02401 gettimeofday(&now, NULL); 02402 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02403 rtcpheader = (unsigned int *)bdata; 02404 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02405 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02406 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02407 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02408 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02409 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02410 len += 28; 02411 02412 extended = rtp->cycles + rtp->lastrxseqno; 02413 expected = extended - rtp->seedrxseqno + 1; 02414 if (rtp->rxcount > expected) 02415 expected += rtp->rxcount - expected; 02416 lost = expected - rtp->rxcount; 02417 expected_interval = expected - rtp->rtcp->expected_prior; 02418 rtp->rtcp->expected_prior = expected; 02419 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02420 rtp->rtcp->received_prior = rtp->rxcount; 02421 lost_interval = expected_interval - received_interval; 02422 if (expected_interval == 0 || lost_interval <= 0) 02423 fraction = 0; 02424 else 02425 fraction = (lost_interval << 8) / expected_interval; 02426 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02427 rtcpheader[7] = htonl(rtp->themssrc); 02428 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02429 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02430 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02431 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02432 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02433 len += 24; 02434 02435 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02436 02437 if (rtp->rtcp->sendfur) { 02438 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02439 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02440 len += 8; 02441 rtp->rtcp->sendfur = 0; 02442 } 02443 02444 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02445 /* it can change mid call, and SDES can't) */ 02446 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02447 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02448 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02449 len += 12; 02450 02451 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02452 if (res < 0) { 02453 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)); 02454 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02455 return 0; 02456 } 02457 02458 /* FIXME Don't need to get a new one */ 02459 gettimeofday(&rtp->rtcp->txlsr, NULL); 02460 rtp->rtcp->sr_count++; 02461 02462 rtp->rtcp->lastsrtxcount = rtp->txcount; 02463 02464 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02465 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02466 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02467 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02468 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02469 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02470 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02471 ast_verbose(" Report block:\n"); 02472 ast_verbose(" Fraction lost: %u\n", fraction); 02473 ast_verbose(" Cumulative loss: %u\n", lost); 02474 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02475 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02476 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02477 } 02478 return res; 02479 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 398 of file rtp.c.
Referenced by process_sdp().
00399 { 00400 return sizeof(struct ast_rtp); 00401 }
enum ast_bridge_result ast_rtp_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
int | timeoutms | |||
) |
Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
Definition at line 3287 of file rtp.c.
References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_DTMF_COMPENSATE, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, option_debug, option_verbose, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
03288 { 03289 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03290 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03291 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03292 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03293 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03294 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03295 int codec0 = 0, codec1 = 0; 03296 void *pvt0 = NULL, *pvt1 = NULL; 03297 03298 /* Lock channels */ 03299 ast_channel_lock(c0); 03300 while(ast_channel_trylock(c1)) { 03301 ast_channel_unlock(c0); 03302 usleep(1); 03303 ast_channel_lock(c0); 03304 } 03305 03306 /* Ensure neither channel got hungup during lock avoidance */ 03307 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03308 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03309 ast_channel_unlock(c0); 03310 ast_channel_unlock(c1); 03311 return AST_BRIDGE_FAILED; 03312 } 03313 03314 /* Find channel driver interfaces */ 03315 if (!(pr0 = get_proto(c0))) { 03316 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03317 ast_channel_unlock(c0); 03318 ast_channel_unlock(c1); 03319 return AST_BRIDGE_FAILED; 03320 } 03321 if (!(pr1 = get_proto(c1))) { 03322 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03323 ast_channel_unlock(c0); 03324 ast_channel_unlock(c1); 03325 return AST_BRIDGE_FAILED; 03326 } 03327 03328 /* Get channel specific interface structures */ 03329 pvt0 = c0->tech_pvt; 03330 pvt1 = c1->tech_pvt; 03331 03332 /* Get audio and video interface (if native bridge is possible) */ 03333 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03334 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03335 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03336 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03337 03338 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03339 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03340 audio_p0_res = AST_RTP_GET_FAILED; 03341 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03342 audio_p1_res = AST_RTP_GET_FAILED; 03343 03344 /* Check if a bridge is possible (partial/native) */ 03345 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03346 /* Somebody doesn't want to play... */ 03347 ast_channel_unlock(c0); 03348 ast_channel_unlock(c1); 03349 return AST_BRIDGE_FAILED_NOWARN; 03350 } 03351 03352 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03353 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03354 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03355 audio_p0_res = AST_RTP_TRY_PARTIAL; 03356 } 03357 03358 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03359 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03360 audio_p1_res = AST_RTP_TRY_PARTIAL; 03361 } 03362 03363 /* If both sides are not using the same method of DTMF transmission 03364 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03365 * -------------------------------------------------- 03366 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03367 * |-----------|------------|-----------------------| 03368 * | Inband | False | True | 03369 * | RFC2833 | True | True | 03370 * | SIP INFO | False | False | 03371 * -------------------------------------------------- 03372 * However, if DTMF from both channels is being monitored by the core, then 03373 * we can still do packet-to-packet bridging, because passing through the 03374 * core will handle DTMF mode translation. 03375 */ 03376 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03377 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03378 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03379 ast_channel_unlock(c0); 03380 ast_channel_unlock(c1); 03381 return AST_BRIDGE_FAILED_NOWARN; 03382 } 03383 audio_p0_res = AST_RTP_TRY_PARTIAL; 03384 audio_p1_res = AST_RTP_TRY_PARTIAL; 03385 } 03386 03387 /* If the core will need to compensate and the P2P bridge will need to feed up DTMF frames then we can not reliably do so yet, so do not P2P bridge */ 03388 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF) && ast_test_flag(p0, FLAG_DTMF_COMPENSATE)) || 03389 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF) && ast_test_flag(p1, FLAG_DTMF_COMPENSATE))) { 03390 ast_channel_unlock(c0); 03391 ast_channel_unlock(c1); 03392 return AST_BRIDGE_FAILED_NOWARN; 03393 } 03394 03395 /* Get codecs from both sides */ 03396 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03397 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03398 if (codec0 && codec1 && !(codec0 & codec1)) { 03399 /* Hey, we can't do native bridging if both parties speak different codecs */ 03400 if (option_debug) 03401 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03402 ast_channel_unlock(c0); 03403 ast_channel_unlock(c1); 03404 return AST_BRIDGE_FAILED_NOWARN; 03405 } 03406 03407 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03408 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03409 struct ast_format_list fmt0, fmt1; 03410 03411 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03412 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03413 if (option_debug) 03414 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03415 ast_channel_unlock(c0); 03416 ast_channel_unlock(c1); 03417 return AST_BRIDGE_FAILED_NOWARN; 03418 } 03419 /* They must also be using the same packetization */ 03420 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03421 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03422 if (fmt0.cur_ms != fmt1.cur_ms) { 03423 if (option_debug) 03424 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03425 ast_channel_unlock(c0); 03426 ast_channel_unlock(c1); 03427 return AST_BRIDGE_FAILED_NOWARN; 03428 } 03429 03430 if (option_verbose > 2) 03431 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03432 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03433 } else { 03434 if (option_verbose > 2) 03435 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03436 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03437 } 03438 03439 return res; 03440 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2742 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp().
02743 { 02744 if (pt < 0 || pt > MAX_RTP_PT) 02745 return 0; /* bogus payload type */ 02746 02747 if (static_RTP_PT[pt].isAstFormat) 02748 return static_RTP_PT[pt].code; 02749 else 02750 return 0; 02751 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Definition at line 2737 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
02738 { 02739 return &rtp->pref; 02740 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2724 of file rtp.c.
References ast_smoother_free(), ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, prefs, and ast_rtp::smoother.
Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp(), register_verify(), set_peer_capabilities(), start_rtp(), and transmit_response_with_sdp().
02725 { 02726 int x; 02727 for (x = 0; x < 32; x++) { /* Ugly way */ 02728 rtp->pref.order[x] = prefs->order[x]; 02729 rtp->pref.framing[x] = prefs->framing[x]; 02730 } 02731 if (rtp->smoother) 02732 ast_smoother_free(rtp->smoother); 02733 rtp->smoother = NULL; 02734 return 0; 02735 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2143 of file rtp.c.
References ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose(), ast_rtp::bridge_lock, ast_rtcp::expected_prior, free, ast_rtp::io, ast_rtp::ioid, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_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_user_full(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().
02144 { 02145 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02146 /*Print some info on the call here */ 02147 ast_verbose(" RTP-stats\n"); 02148 ast_verbose("* Our Receiver:\n"); 02149 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02150 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02151 ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02152 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02153 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02154 ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count); 02155 ast_verbose("* Our Sender:\n"); 02156 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02157 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02158 ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost); 02159 ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0); 02160 ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count); 02161 ast_verbose(" RTT: %f\n", rtp->rtcp->rtt); 02162 } 02163 02164 if (rtp->smoother) 02165 ast_smoother_free(rtp->smoother); 02166 if (rtp->ioid) 02167 ast_io_remove(rtp->io, rtp->ioid); 02168 if (rtp->s > -1) 02169 close(rtp->s); 02170 if (rtp->rtcp) { 02171 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02172 close(rtp->rtcp->s); 02173 free(rtp->rtcp); 02174 rtp->rtcp=NULL; 02175 } 02176 02177 ast_mutex_destroy(&rtp->bridge_lock); 02178 02179 free(rtp); 02180 }
int ast_rtp_early_bridge | ( | struct ast_channel * | dest, | |
struct ast_channel * | src | |||
) |
If possible, create an early bridge directly between the devices without having to send a re-invite later.
Definition at line 1494 of file rtp.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01495 { 01496 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01497 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01498 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01499 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01500 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01501 int srccodec, destcodec, nat_active = 0; 01502 01503 /* Lock channels */ 01504 ast_channel_lock(dest); 01505 if (src) { 01506 while(ast_channel_trylock(src)) { 01507 ast_channel_unlock(dest); 01508 usleep(1); 01509 ast_channel_lock(dest); 01510 } 01511 } 01512 01513 /* Find channel driver interfaces */ 01514 destpr = get_proto(dest); 01515 if (src) 01516 srcpr = get_proto(src); 01517 if (!destpr) { 01518 if (option_debug) 01519 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01520 ast_channel_unlock(dest); 01521 if (src) 01522 ast_channel_unlock(src); 01523 return 0; 01524 } 01525 if (!srcpr) { 01526 if (option_debug) 01527 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01528 ast_channel_unlock(dest); 01529 if (src) 01530 ast_channel_unlock(src); 01531 return 0; 01532 } 01533 01534 /* Get audio and video interface (if native bridge is possible) */ 01535 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01536 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01537 if (srcpr) { 01538 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01539 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01540 } 01541 01542 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01543 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01544 /* Somebody doesn't want to play... */ 01545 ast_channel_unlock(dest); 01546 if (src) 01547 ast_channel_unlock(src); 01548 return 0; 01549 } 01550 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01551 srccodec = srcpr->get_codec(src); 01552 else 01553 srccodec = 0; 01554 if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec) 01555 destcodec = destpr->get_codec(dest); 01556 else 01557 destcodec = 0; 01558 /* Ensure we have at least one matching codec */ 01559 if (!(srccodec & destcodec)) { 01560 ast_channel_unlock(dest); 01561 if (src) 01562 ast_channel_unlock(src); 01563 return 0; 01564 } 01565 /* Consider empty media as non-existant */ 01566 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01567 srcp = NULL; 01568 /* If the client has NAT stuff turned on then just safe NAT is active */ 01569 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01570 nat_active = 1; 01571 /* Bridge media early */ 01572 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01573 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01574 ast_channel_unlock(dest); 01575 if (src) 01576 ast_channel_unlock(src); 01577 if (option_debug) 01578 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01579 return 1; 01580 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 513 of file rtp.c.
References ast_rtp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().
00514 { 00515 return rtp->s; 00516 }
Definition at line 2054 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by __sip_destroy(), and ast_rtp_read().
02055 { 02056 struct ast_rtp *bridged = NULL; 02057 02058 ast_mutex_lock(&rtp->bridge_lock); 02059 bridged = rtp->bridged; 02060 ast_mutex_unlock(&rtp->bridge_lock); 02061 02062 return bridged; 02063 }
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 1716 of file rtp.c.
References ast_mutex_lock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by process_sdp().
01718 { 01719 int pt; 01720 01721 ast_mutex_lock(&rtp->bridge_lock); 01722 01723 *astFormats = *nonAstFormats = 0; 01724 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01725 if (rtp->current_RTP_PT[pt].isAstFormat) { 01726 *astFormats |= rtp->current_RTP_PT[pt].code; 01727 } else { 01728 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01729 } 01730 } 01731 01732 ast_mutex_unlock(&rtp->bridge_lock); 01733 01734 return; 01735 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2036 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), bridge_native_loop(), do_monitor(), gtalk_update_stun(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
02037 { 02038 if ((them->sin_family != AF_INET) || 02039 (them->sin_port != rtp->them.sin_port) || 02040 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02041 them->sin_family = AF_INET; 02042 them->sin_port = rtp->them.sin_port; 02043 them->sin_addr = rtp->them.sin_addr; 02044 return 1; 02045 } 02046 return 0; 02047 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2099 of file rtp.c.
References ast_rtcp::expected_prior, ast_rtp_quality::local_count, ast_rtp_quality::local_jitter, ast_rtp_quality::local_lostpackets, ast_rtp_quality::local_ssrc, ast_rtcp::quality, ast_rtcp::received_prior, ast_rtp_quality::remote_count, ast_rtp_quality::remote_jitter, ast_rtp_quality::remote_lostpackets, ast_rtp_quality::remote_ssrc, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtp_quality::rtt, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.
Referenced by acf_channel_read(), handle_request_bye(), and sip_hangup().
02100 { 02101 /* 02102 *ssrc our ssrc 02103 *themssrc their ssrc 02104 *lp lost packets 02105 *rxjitter our calculated jitter(rx) 02106 *rxcount no. received packets 02107 *txjitter reported jitter of the other end 02108 *txcount transmitted packets 02109 *rlp remote lost packets 02110 *rtt round trip time 02111 */ 02112 02113 if (qual && rtp) { 02114 qual->local_ssrc = rtp->ssrc; 02115 qual->local_jitter = rtp->rxjitter; 02116 qual->local_count = rtp->rxcount; 02117 qual->remote_ssrc = rtp->themssrc; 02118 qual->remote_count = rtp->txcount; 02119 if (rtp->rtcp) { 02120 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02121 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02122 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02123 qual->rtt = rtp->rtcp->rtt; 02124 } 02125 } 02126 if (rtp->rtcp) { 02127 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02128 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02129 rtp->ssrc, 02130 rtp->themssrc, 02131 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02132 rtp->rxjitter, 02133 rtp->rxcount, 02134 (double)rtp->rtcp->reported_jitter / 65536.0, 02135 rtp->txcount, 02136 rtp->rtcp->reported_lost, 02137 rtp->rtcp->rtt); 02138 return rtp->rtcp->quality; 02139 } else 02140 return "<Unknown> - RTP/RTCP has already been destroyed"; 02141 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 568 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by do_monitor().
00569 { 00570 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00571 return 0; 00572 return rtp->rtpholdtimeout; 00573 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 576 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by do_monitor().
00577 { 00578 return rtp->rtpkeepalive; 00579 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 560 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by do_monitor().
00561 { 00562 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00563 return 0; 00564 return rtp->rtptimeout; 00565 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2049 of file rtp.c.
References ast_rtp::us.
Referenced by add_sdp(), external_rtp_create(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), and oh323_set_rtp_peer().
int ast_rtp_getnat | ( | struct ast_rtp * | rtp | ) |
Definition at line 596 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00597 { 00598 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00599 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 3825 of file rtp.c.
References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp.
Referenced by main().
03826 { 03827 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03828 ast_rtp_reload(); 03829 }
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 1759 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by add_codec_to_answer(), add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), and bridge_p2p_rtp_write().
01760 { 01761 int pt = 0; 01762 01763 ast_mutex_lock(&rtp->bridge_lock); 01764 01765 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01766 code == rtp->rtp_lookup_code_cache_code) { 01767 /* Use our cached mapping, to avoid the overhead of the loop below */ 01768 pt = rtp->rtp_lookup_code_cache_result; 01769 ast_mutex_unlock(&rtp->bridge_lock); 01770 return pt; 01771 } 01772 01773 /* Check the dynamic list first */ 01774 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01775 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01776 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01777 rtp->rtp_lookup_code_cache_code = code; 01778 rtp->rtp_lookup_code_cache_result = pt; 01779 ast_mutex_unlock(&rtp->bridge_lock); 01780 return pt; 01781 } 01782 } 01783 01784 /* Then the static list */ 01785 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01786 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01787 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01788 rtp->rtp_lookup_code_cache_code = code; 01789 rtp->rtp_lookup_code_cache_result = pt; 01790 ast_mutex_unlock(&rtp->bridge_lock); 01791 return pt; 01792 } 01793 } 01794 01795 ast_mutex_unlock(&rtp->bridge_lock); 01796 01797 return -1; 01798 }
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 1819 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len, and name.
Referenced by process_sdp().
01821 { 01822 int format; 01823 unsigned len; 01824 char *end = buf; 01825 char *start = buf; 01826 01827 if (!buf || !size) 01828 return NULL; 01829 01830 snprintf(end, size, "0x%x (", capability); 01831 01832 len = strlen(end); 01833 end += len; 01834 size -= len; 01835 start = end; 01836 01837 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01838 if (capability & format) { 01839 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01840 01841 snprintf(end, size, "%s|", name); 01842 len = strlen(end); 01843 end += len; 01844 size -= len; 01845 } 01846 } 01847 01848 if (start == end) 01849 snprintf(start, size, "nothing)"); 01850 else if (size > 1) 01851 *(end -1) = ')'; 01852 01853 return buf; 01854 }
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 1800 of file rtp.c.
References AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, mimeTypes, and payloadType.
Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().
01802 { 01803 unsigned int i; 01804 01805 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01806 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01807 if (isAstFormat && 01808 (code == AST_FORMAT_G726_AAL2) && 01809 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01810 return "G726-32"; 01811 else 01812 return mimeTypes[i].subtype; 01813 } 01814 } 01815 01816 return ""; 01817 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1737 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), MAX_RTP_PT, result, and static_RTP_PT.
Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().
01738 { 01739 struct rtpPayloadType result; 01740 01741 result.isAstFormat = result.code = 0; 01742 01743 if (pt < 0 || pt > MAX_RTP_PT) 01744 return result; /* bogus payload type */ 01745 01746 /* Start with negotiated codecs */ 01747 ast_mutex_lock(&rtp->bridge_lock); 01748 result = rtp->current_RTP_PT[pt]; 01749 ast_mutex_unlock(&rtp->bridge_lock); 01750 01751 /* If it doesn't exist, check our static RTP type list, just in case */ 01752 if (!result.code) 01753 result = static_RTP_PT[pt]; 01754 01755 return result; 01756 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1582 of file rtp.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, ast_rtp_pt_copy(), AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01583 { 01584 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01585 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01586 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01587 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01588 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01589 int srccodec, destcodec; 01590 01591 /* Lock channels */ 01592 ast_channel_lock(dest); 01593 while(ast_channel_trylock(src)) { 01594 ast_channel_unlock(dest); 01595 usleep(1); 01596 ast_channel_lock(dest); 01597 } 01598 01599 /* Find channel driver interfaces */ 01600 if (!(destpr = get_proto(dest))) { 01601 if (option_debug) 01602 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01603 ast_channel_unlock(dest); 01604 ast_channel_unlock(src); 01605 return 0; 01606 } 01607 if (!(srcpr = get_proto(src))) { 01608 if (option_debug) 01609 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01610 ast_channel_unlock(dest); 01611 ast_channel_unlock(src); 01612 return 0; 01613 } 01614 01615 /* Get audio and video interface (if native bridge is possible) */ 01616 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01617 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01618 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01619 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01620 01621 /* Ensure we have at least one matching codec */ 01622 if (srcpr->get_codec) 01623 srccodec = srcpr->get_codec(src); 01624 else 01625 srccodec = 0; 01626 if (destpr->get_codec) 01627 destcodec = destpr->get_codec(dest); 01628 else 01629 destcodec = 0; 01630 01631 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01632 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) { 01633 /* Somebody doesn't want to play... */ 01634 ast_channel_unlock(dest); 01635 ast_channel_unlock(src); 01636 return 0; 01637 } 01638 ast_rtp_pt_copy(destp, srcp); 01639 if (vdestp && vsrcp) 01640 ast_rtp_pt_copy(vdestp, vsrcp); 01641 if (media) { 01642 /* Bridge early */ 01643 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01644 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01645 } 01646 ast_channel_unlock(dest); 01647 ast_channel_unlock(src); 01648 if (option_debug) 01649 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01650 return 1; 01651 }
struct ast_rtp* ast_rtp_new | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode | |||
) |
Initializate a RTP session.
sched | ||
io | ||
rtcpenable | ||
callbackmode |
Definition at line 2001 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
02002 { 02003 struct in_addr ia; 02004 02005 memset(&ia, 0, sizeof(ia)); 02006 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02007 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1901 of file rtp.c.
References ast_mutex_init(), ast_random(), ast_set_flag, ast_rtp::bridge_lock, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, and ast_rtp::us.
Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().
01902 { 01903 ast_mutex_init(&rtp->bridge_lock); 01904 01905 rtp->them.sin_family = AF_INET; 01906 rtp->us.sin_family = AF_INET; 01907 rtp->ssrc = ast_random(); 01908 rtp->seqno = ast_random() & 0xffff; 01909 ast_set_flag(rtp, FLAG_HAS_DTMF); 01910 01911 return; 01912 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2018 of file rtp.c.
References ast_random(), ast_rtp::set_marker_bit, and ast_rtp::ssrc.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), sip_write(), and skinny_indicate().
02019 { 02020 rtp->set_marker_bit = 1; 02021 rtp->ssrc = ast_random(); 02022 return; 02023 }
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().
sched | ||
io | ||
rtcpenable | ||
callbackmode | ||
in |
Definition at line 1914 of file rtp.c.
References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, errno, FLAG_CALLBACK_MODE, free, io, LOG_ERROR, rtp_socket(), rtpread(), and sched.
Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), sip_alloc(), and start_rtp().
01915 { 01916 struct ast_rtp *rtp; 01917 int x; 01918 int first; 01919 int startplace; 01920 01921 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01922 return NULL; 01923 01924 ast_rtp_new_init(rtp); 01925 01926 rtp->s = rtp_socket(); 01927 if (rtp->s < 0) { 01928 free(rtp); 01929 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01930 return NULL; 01931 } 01932 if (sched && rtcpenable) { 01933 rtp->sched = sched; 01934 rtp->rtcp = ast_rtcp_new(); 01935 } 01936 01937 /* Select a random port number in the range of possible RTP */ 01938 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01939 x = x & ~1; 01940 /* Save it for future references. */ 01941 startplace = x; 01942 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01943 for (;;) { 01944 /* Must be an even port number by RTP spec */ 01945 rtp->us.sin_port = htons(x); 01946 rtp->us.sin_addr = addr; 01947 /* If there's rtcp, initialize it as well. */ 01948 if (rtp->rtcp) { 01949 rtp->rtcp->us.sin_port = htons(x + 1); 01950 rtp->rtcp->us.sin_addr = addr; 01951 } 01952 /* Try to bind it/them. */ 01953 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01954 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01955 break; 01956 if (!first) { 01957 /* Primary bind succeeded! Gotta recreate it */ 01958 close(rtp->s); 01959 rtp->s = rtp_socket(); 01960 } 01961 if (errno != EADDRINUSE) { 01962 /* We got an error that wasn't expected, abort! */ 01963 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01964 close(rtp->s); 01965 if (rtp->rtcp) { 01966 close(rtp->rtcp->s); 01967 free(rtp->rtcp); 01968 } 01969 free(rtp); 01970 return NULL; 01971 } 01972 /* The port was used, increment it (by two). */ 01973 x += 2; 01974 /* Did we go over the limit ? */ 01975 if (x > rtpend) 01976 /* then, start from the begingig. */ 01977 x = (rtpstart + 1) & ~1; 01978 /* Check if we reached the place were we started. */ 01979 if (x == startplace) { 01980 /* If so, there's no ports available. */ 01981 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01982 close(rtp->s); 01983 if (rtp->rtcp) { 01984 close(rtp->rtcp->s); 01985 free(rtp->rtcp); 01986 } 01987 free(rtp); 01988 return NULL; 01989 } 01990 } 01991 rtp->sched = sched; 01992 rtp->io = io; 01993 if (callbackmode) { 01994 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01995 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01996 } 01997 ast_rtp_pt_default(rtp); 01998 return rtp; 01999 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2842 of file rtp.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, protos, and ast_rtp_protocol::type.
Referenced by load_module().
02843 { 02844 struct ast_rtp_protocol *cur; 02845 02846 AST_LIST_LOCK(&protos); 02847 AST_LIST_TRAVERSE(&protos, cur, list) { 02848 if (!strcmp(cur->type, proto->type)) { 02849 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02850 AST_LIST_UNLOCK(&protos); 02851 return -1; 02852 } 02853 } 02854 AST_LIST_INSERT_HEAD(&protos, proto, list); 02855 AST_LIST_UNLOCK(&protos); 02856 02857 return 0; 02858 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2834 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.
Referenced by load_module(), and unload_module().
02835 { 02836 AST_LIST_LOCK(&protos); 02837 AST_LIST_REMOVE(&protos, proto, list); 02838 AST_LIST_UNLOCK(&protos); 02839 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1418 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by process_sdp().
01419 { 01420 int i; 01421 01422 if (!rtp) 01423 return; 01424 01425 ast_mutex_lock(&rtp->bridge_lock); 01426 01427 for (i = 0; i < MAX_RTP_PT; ++i) { 01428 rtp->current_RTP_PT[i].isAstFormat = 0; 01429 rtp->current_RTP_PT[i].code = 0; 01430 } 01431 01432 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01433 rtp->rtp_lookup_code_cache_code = 0; 01434 rtp->rtp_lookup_code_cache_result = 0; 01435 01436 ast_mutex_unlock(&rtp->bridge_lock); 01437 }
Copy payload types between RTP structures.
Definition at line 1458 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by ast_rtp_make_compatible(), and process_sdp().
01459 { 01460 unsigned int i; 01461 01462 ast_mutex_lock(&dest->bridge_lock); 01463 ast_mutex_lock(&src->bridge_lock); 01464 01465 for (i=0; i < MAX_RTP_PT; ++i) { 01466 dest->current_RTP_PT[i].isAstFormat = 01467 src->current_RTP_PT[i].isAstFormat; 01468 dest->current_RTP_PT[i].code = 01469 src->current_RTP_PT[i].code; 01470 } 01471 dest->rtp_lookup_code_cache_isAstFormat = 0; 01472 dest->rtp_lookup_code_cache_code = 0; 01473 dest->rtp_lookup_code_cache_result = 0; 01474 01475 ast_mutex_unlock(&src->bridge_lock); 01476 ast_mutex_unlock(&dest->bridge_lock); 01477 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1439 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, ast_rtp::rtp_lookup_code_cache_result, and static_RTP_PT.
Referenced by ast_rtp_new_with_bindaddr().
01440 { 01441 int i; 01442 01443 ast_mutex_lock(&rtp->bridge_lock); 01444 01445 /* Initialize to default payload types */ 01446 for (i = 0; i < MAX_RTP_PT; ++i) { 01447 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01448 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01449 } 01450 01451 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01452 rtp->rtp_lookup_code_cache_code = 0; 01453 rtp->rtp_lookup_code_cache_result = 0; 01454 01455 ast_mutex_unlock(&rtp->bridge_lock); 01456 }
Definition at line 2628 of file rtp.c.
References AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), errno, f, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_rtp::lastdigitts, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_DEBUG, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seqno, ast_rtp::set_marker_bit, ast_rtp::ssrc, ast_rtp::them, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
02629 { 02630 unsigned char *rtpheader; 02631 int hdrlen = 12; 02632 int res; 02633 unsigned int ms; 02634 int pred; 02635 int mark = 0; 02636 02637 ms = calc_txstamp(rtp, &f->delivery); 02638 /* Default prediction */ 02639 if (f->frametype == AST_FRAME_VOICE) { 02640 pred = rtp->lastts + f->samples; 02641 02642 /* Re-calculate last TS */ 02643 rtp->lastts = rtp->lastts + ms * 8; 02644 if (ast_tvzero(f->delivery)) { 02645 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02646 and if so, go with our prediction */ 02647 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02648 rtp->lastts = pred; 02649 else { 02650 if (option_debug > 2) 02651 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02652 mark = 1; 02653 } 02654 } 02655 } else if (f->frametype == AST_FRAME_VIDEO) { 02656 mark = f->subclass & 0x1; 02657 pred = rtp->lastovidtimestamp + f->samples; 02658 /* Re-calculate last TS */ 02659 rtp->lastts = rtp->lastts + ms * 90; 02660 /* If it's close to our prediction, go for it */ 02661 if (ast_tvzero(f->delivery)) { 02662 if (abs(rtp->lastts - pred) < 7200) { 02663 rtp->lastts = pred; 02664 rtp->lastovidtimestamp += f->samples; 02665 } else { 02666 if (option_debug > 2) 02667 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); 02668 rtp->lastovidtimestamp = rtp->lastts; 02669 } 02670 } 02671 } 02672 02673 /* If we have been explicitly told to set the marker bit do so */ 02674 if (rtp->set_marker_bit) { 02675 mark = 1; 02676 rtp->set_marker_bit = 0; 02677 } 02678 02679 /* If the timestamp for non-digit packets has moved beyond the timestamp 02680 for digits, update the digit timestamp. 02681 */ 02682 if (rtp->lastts > rtp->lastdigitts) 02683 rtp->lastdigitts = rtp->lastts; 02684 02685 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 02686 rtp->lastts = f->ts * 8; 02687 02688 /* Get a pointer to the header */ 02689 rtpheader = (unsigned char *)(f->data - hdrlen); 02690 02691 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02692 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02693 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02694 02695 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02696 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02697 if (res <0) { 02698 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02699 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)); 02700 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02701 /* Only give this error message once if we are not RTP debugging */ 02702 if (option_debug || rtpdebug) 02703 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)); 02704 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02705 } 02706 } else { 02707 rtp->txcount++; 02708 rtp->txoctetcount +=(res - hdrlen); 02709 02710 if (rtp->rtcp && rtp->rtcp->schedid < 1) 02711 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02712 } 02713 02714 if (rtp_debug_test_addr(&rtp->them)) 02715 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02716 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02717 } 02718 02719 rtp->seqno++; 02720 02721 return 0; 02722 }
Definition at line 1106 of file rtp.c.
References ast_backtrace(), ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, CRASH, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, event, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len, ast_frame::len, LOG_DEBUG, LOG_ERROR, 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(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().
01107 { 01108 int res; 01109 struct sockaddr_in sin; 01110 socklen_t len; 01111 unsigned int seqno; 01112 int version; 01113 int payloadtype; 01114 int hdrlen = 12; 01115 int padding; 01116 int mark; 01117 int ext; 01118 int cc; 01119 unsigned int ssrc; 01120 unsigned int timestamp; 01121 unsigned int *rtpheader; 01122 struct rtpPayloadType rtpPT; 01123 struct ast_rtp *bridged = NULL; 01124 01125 if( !rtp ) { 01126 ast_log(LOG_ERROR, "ast_rtp_read(): called with rtp == NULL\n"); 01127 ast_backtrace(); 01128 return &ast_null_frame; 01129 } 01130 01131 /* If time is up, kill it */ 01132 if (rtp->sending_digit) 01133 ast_rtp_senddigit_continuation(rtp); 01134 01135 len = sizeof(sin); 01136 01137 /* Cache where the header will go */ 01138 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01139 0, (struct sockaddr *)&sin, &len); 01140 01141 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01142 if (res < 0) { 01143 if (errno == EBADF) 01144 CRASH; 01145 if (errno != EAGAIN) { 01146 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01147 return NULL; 01148 } 01149 return &ast_null_frame; 01150 } 01151 01152 if (res < hdrlen) { 01153 ast_log(LOG_WARNING, "RTP Read too short\n"); 01154 return &ast_null_frame; 01155 } 01156 01157 /* Get fields */ 01158 seqno = ntohl(rtpheader[0]); 01159 01160 /* Check RTP version */ 01161 version = (seqno & 0xC0000000) >> 30; 01162 if (!version) { 01163 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01164 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01165 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01166 } 01167 return &ast_null_frame; 01168 } 01169 01170 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01171 /* If we don't have the other side's address, then ignore this */ 01172 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01173 return &ast_null_frame; 01174 #endif 01175 01176 /* Send to whoever send to us if NAT is turned on */ 01177 if (rtp->nat) { 01178 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01179 (rtp->them.sin_port != sin.sin_port)) { 01180 rtp->them = sin; 01181 if (rtp->rtcp) { 01182 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01183 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01184 } 01185 rtp->rxseqno = 0; 01186 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01187 if (option_debug || rtpdebug) 01188 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)); 01189 } 01190 } 01191 01192 /* If we are bridged to another RTP stream, send direct */ 01193 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01194 return &ast_null_frame; 01195 01196 if (version != 2) 01197 return &ast_null_frame; 01198 01199 payloadtype = (seqno & 0x7f0000) >> 16; 01200 padding = seqno & (1 << 29); 01201 mark = seqno & (1 << 23); 01202 ext = seqno & (1 << 28); 01203 cc = (seqno & 0xF000000) >> 24; 01204 seqno &= 0xffff; 01205 timestamp = ntohl(rtpheader[1]); 01206 ssrc = ntohl(rtpheader[2]); 01207 01208 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01209 if (option_debug || rtpdebug) 01210 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01211 mark = 1; 01212 } 01213 01214 rtp->rxssrc = ssrc; 01215 01216 if (padding) { 01217 /* Remove padding bytes */ 01218 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01219 } 01220 01221 if (cc) { 01222 /* CSRC fields present */ 01223 hdrlen += cc*4; 01224 } 01225 01226 if (ext) { 01227 /* RTP Extension present */ 01228 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01229 hdrlen += 4; 01230 if (option_debug) { 01231 int profile; 01232 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01233 if (profile == 0x505a) 01234 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01235 else 01236 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile); 01237 } 01238 } 01239 01240 if (res < hdrlen) { 01241 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01242 return &ast_null_frame; 01243 } 01244 01245 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01246 01247 if (rtp->rxcount==1) { 01248 /* This is the first RTP packet successfully received from source */ 01249 rtp->seedrxseqno = seqno; 01250 } 01251 01252 /* Do not schedule RR if RTCP isn't run */ 01253 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01254 /* Schedule transmission of Receiver Report */ 01255 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01256 } 01257 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01258 rtp->cycles += RTP_SEQ_MOD; 01259 01260 rtp->lastrxseqno = seqno; 01261 01262 if (rtp->themssrc==0) 01263 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01264 01265 if (rtp_debug_test_addr(&sin)) 01266 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01267 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01268 01269 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01270 if (!rtpPT.isAstFormat) { 01271 struct ast_frame *f = NULL; 01272 01273 /* This is special in-band data that's not one of our codecs */ 01274 if (rtpPT.code == AST_RTP_DTMF) { 01275 /* It's special -- rfc2833 process it */ 01276 if (rtp_debug_test_addr(&sin)) { 01277 unsigned char *data; 01278 unsigned int event; 01279 unsigned int event_end; 01280 unsigned int duration; 01281 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01282 event = ntohl(*((unsigned int *)(data))); 01283 event >>= 24; 01284 event_end = ntohl(*((unsigned int *)(data))); 01285 event_end <<= 8; 01286 event_end >>= 24; 01287 duration = ntohl(*((unsigned int *)(data))); 01288 duration &= 0xFFFF; 01289 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); 01290 } 01291 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01292 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01293 /* It's really special -- process it the Cisco way */ 01294 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01295 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01296 rtp->lastevent = seqno; 01297 } 01298 } else if (rtpPT.code == AST_RTP_CN) { 01299 /* Comfort Noise */ 01300 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01301 } else { 01302 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01303 } 01304 return f ? f : &ast_null_frame; 01305 } 01306 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01307 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01308 01309 if (!rtp->lastrxts) 01310 rtp->lastrxts = timestamp; 01311 01312 rtp->rxseqno = seqno; 01313 01314 /* Record received timestamp as last received now */ 01315 rtp->lastrxts = timestamp; 01316 01317 rtp->f.mallocd = 0; 01318 rtp->f.datalen = res - hdrlen; 01319 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01320 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01321 rtp->f.seqno = seqno; 01322 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01323 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01324 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01325 ast_frame_byteswap_be(&rtp->f); 01326 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01327 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01328 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01329 rtp->f.ts = timestamp / 8; 01330 rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 ); 01331 } else { 01332 /* Video -- samples is # of samples vs. 90000 */ 01333 if (!rtp->lastividtimestamp) 01334 rtp->lastividtimestamp = timestamp; 01335 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01336 rtp->lastividtimestamp = timestamp; 01337 rtp->f.delivery.tv_sec = 0; 01338 rtp->f.delivery.tv_usec = 0; 01339 if (mark) 01340 rtp->f.subclass |= 0x1; 01341 01342 } 01343 rtp->f.src = "RTP"; 01344 return &rtp->f; 01345 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3760 of file rtp.c.
References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and VERBOSE_PREFIX_2.
Referenced by ast_rtp_init().
03761 { 03762 struct ast_config *cfg; 03763 const char *s; 03764 03765 rtpstart = 5000; 03766 rtpend = 31000; 03767 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03768 cfg = ast_config_load("rtp.conf"); 03769 if (cfg) { 03770 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03771 rtpstart = atoi(s); 03772 if (rtpstart < 1024) 03773 rtpstart = 1024; 03774 if (rtpstart > 65535) 03775 rtpstart = 65535; 03776 } 03777 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03778 rtpend = atoi(s); 03779 if (rtpend < 1024) 03780 rtpend = 1024; 03781 if (rtpend > 65535) 03782 rtpend = 65535; 03783 } 03784 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03785 rtcpinterval = atoi(s); 03786 if (rtcpinterval == 0) 03787 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03788 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03789 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03790 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03791 rtcpinterval = RTCP_MAX_INTERVALMS; 03792 } 03793 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03794 #ifdef SO_NO_CHECK 03795 if (ast_false(s)) 03796 nochecksums = 1; 03797 else 03798 nochecksums = 0; 03799 #else 03800 if (ast_false(s)) 03801 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03802 #endif 03803 } 03804 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03805 dtmftimeout = atoi(s); 03806 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03807 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03808 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03809 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03810 }; 03811 } 03812 ast_config_destroy(cfg); 03813 } 03814 if (rtpstart >= rtpend) { 03815 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03816 rtpstart = 5000; 03817 rtpend = 31000; 03818 } 03819 if (option_verbose > 1) 03820 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03821 return 0; 03822 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2079 of file rtp.c.
References ast_rtp::dtmfcount, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.
02080 { 02081 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02082 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02083 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02084 rtp->lastts = 0; 02085 rtp->lastdigitts = 0; 02086 rtp->lastrxts = 0; 02087 rtp->lastividtimestamp = 0; 02088 rtp->lastovidtimestamp = 0; 02089 rtp->lasteventseqn = 0; 02090 rtp->lastevent = 0; 02091 rtp->lasttxformat = 0; 02092 rtp->lastrxformat = 0; 02093 rtp->dtmfcount = 0; 02094 rtp->dtmfsamples = 0; 02095 rtp->seqno = 0; 02096 rtp->rxseqno = 0; 02097 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2594 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::data, ast_rtp::dtmfmute, errno, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by do_monitor().
02595 { 02596 unsigned int *rtpheader; 02597 int hdrlen = 12; 02598 int res; 02599 int payload; 02600 char data[256]; 02601 level = 127 - (level & 0x7f); 02602 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02603 02604 /* If we have no peer, return immediately */ 02605 if (!rtp->them.sin_addr.s_addr) 02606 return 0; 02607 02608 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02609 02610 /* Get a pointer to the header */ 02611 rtpheader = (unsigned int *)data; 02612 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02613 rtpheader[1] = htonl(rtp->lastts); 02614 rtpheader[2] = htonl(rtp->ssrc); 02615 data[12] = level; 02616 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02617 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02618 if (res <0) 02619 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)); 02620 if (rtp_debug_test_addr(&rtp->them)) 02621 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02622 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02623 02624 } 02625 return 0; 02626 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2202 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by mgcp_senddigit_begin(), oh323_digit_begin(), and sip_senddigit_begin().
02203 { 02204 unsigned int *rtpheader; 02205 int hdrlen = 12, res = 0, i = 0, payload = 0; 02206 char data[256]; 02207 02208 if ((digit <= '9') && (digit >= '0')) 02209 digit -= '0'; 02210 else if (digit == '*') 02211 digit = 10; 02212 else if (digit == '#') 02213 digit = 11; 02214 else if ((digit >= 'A') && (digit <= 'D')) 02215 digit = digit - 'A' + 12; 02216 else if ((digit >= 'a') && (digit <= 'd')) 02217 digit = digit - 'a' + 12; 02218 else { 02219 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02220 return 0; 02221 } 02222 02223 /* If we have no peer, return immediately */ 02224 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02225 return 0; 02226 02227 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02228 02229 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02230 rtp->send_duration = 160; 02231 02232 /* Get a pointer to the header */ 02233 rtpheader = (unsigned int *)data; 02234 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02235 rtpheader[1] = htonl(rtp->lastdigitts); 02236 rtpheader[2] = htonl(rtp->ssrc); 02237 02238 for (i = 0; i < 2; i++) { 02239 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02240 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02241 if (res < 0) 02242 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02243 ast_inet_ntoa(rtp->them.sin_addr), 02244 ntohs(rtp->them.sin_port), strerror(errno)); 02245 if (rtp_debug_test_addr(&rtp->them)) 02246 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02247 ast_inet_ntoa(rtp->them.sin_addr), 02248 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02249 /* Increment sequence number */ 02250 rtp->seqno++; 02251 /* Increment duration */ 02252 rtp->send_duration += 160; 02253 /* Clear marker bit and set seqno */ 02254 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02255 } 02256 02257 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02258 rtp->sending_digit = 1; 02259 rtp->send_digit = digit; 02260 rtp->send_payload = payload; 02261 02262 return 0; 02263 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2266 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_verbose(), errno, ast_rtp::lastdigitts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by ast_rtp_read().
02267 { 02268 unsigned int *rtpheader; 02269 int hdrlen = 12, res = 0; 02270 char data[256]; 02271 02272 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02273 return 0; 02274 02275 /* Setup packet to send */ 02276 rtpheader = (unsigned int *)data; 02277 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02278 rtpheader[1] = htonl(rtp->lastdigitts); 02279 rtpheader[2] = htonl(rtp->ssrc); 02280 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02281 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02282 02283 /* Transmit */ 02284 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02285 if (res < 0) 02286 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02287 ast_inet_ntoa(rtp->them.sin_addr), 02288 ntohs(rtp->them.sin_port), strerror(errno)); 02289 if (rtp_debug_test_addr(&rtp->them)) 02290 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02291 ast_inet_ntoa(rtp->them.sin_addr), 02292 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02293 02294 /* Increment sequence number */ 02295 rtp->seqno++; 02296 /* Increment duration */ 02297 rtp->send_duration += 160; 02298 02299 return 0; 02300 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2303 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by mgcp_senddigit_end(), oh323_digit_end(), and sip_senddigit_end().
02304 { 02305 unsigned int *rtpheader; 02306 int hdrlen = 12, res = 0, i = 0; 02307 char data[256]; 02308 02309 /* If no address, then bail out */ 02310 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02311 return 0; 02312 02313 if ((digit <= '9') && (digit >= '0')) 02314 digit -= '0'; 02315 else if (digit == '*') 02316 digit = 10; 02317 else if (digit == '#') 02318 digit = 11; 02319 else if ((digit >= 'A') && (digit <= 'D')) 02320 digit = digit - 'A' + 12; 02321 else if ((digit >= 'a') && (digit <= 'd')) 02322 digit = digit - 'a' + 12; 02323 else { 02324 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02325 return 0; 02326 } 02327 02328 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02329 02330 rtpheader = (unsigned int *)data; 02331 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02332 rtpheader[1] = htonl(rtp->lastdigitts); 02333 rtpheader[2] = htonl(rtp->ssrc); 02334 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02335 /* Set end bit */ 02336 rtpheader[3] |= htonl((1 << 23)); 02337 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02338 /* Send 3 termination packets */ 02339 for (i = 0; i < 3; i++) { 02340 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02341 if (res < 0) 02342 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02343 ast_inet_ntoa(rtp->them.sin_addr), 02344 ntohs(rtp->them.sin_port), strerror(errno)); 02345 if (rtp_debug_test_addr(&rtp->them)) 02346 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02347 ast_inet_ntoa(rtp->them.sin_addr), 02348 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02349 } 02350 rtp->sending_digit = 0; 02351 rtp->send_digit = 0; 02352 /* Increment lastdigitts */ 02353 rtp->lastdigitts += 960; 02354 rtp->seqno++; 02355 02356 return res; 02357 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 586 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00587 { 00588 rtp->callback = callback; 00589 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 581 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00582 { 00583 rtp->data = data; 00584 }
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Activate payload type.
Definition at line 1657 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, ast_rtp::current_RTP_PT, MAX_RTP_PT, and static_RTP_PT.
Referenced by gtalk_newcall(), and process_sdp().
01658 { 01659 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01660 return; /* bogus payload type */ 01661 01662 ast_mutex_lock(&rtp->bridge_lock); 01663 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01664 ast_mutex_unlock(&rtp->bridge_lock); 01665 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2025 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().
02026 { 02027 rtp->them.sin_port = them->sin_port; 02028 rtp->them.sin_addr = them->sin_addr; 02029 if (rtp->rtcp) { 02030 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02031 rtp->rtcp->them.sin_addr = them->sin_addr; 02032 } 02033 rtp->rxseqno = 0; 02034 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 548 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00549 { 00550 rtp->rtpholdtimeout = timeout; 00551 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 554 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00555 { 00556 rtp->rtpkeepalive = period; 00557 }
int ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
int | pt, | |||
char * | mimeType, | |||
char * | mimeSubtype, | |||
enum ast_rtp_options | options | |||
) |
Initiate payload type to a known MIME media type for a codec.
Definition at line 1684 of file rtp.c.
References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, subtype, and type.
Referenced by __oh323_rtp_create(), gtalk_newcall(), process_sdp(), and set_dtmf_payload().
01687 { 01688 unsigned int i; 01689 int found = 0; 01690 01691 if (pt < 0 || pt > MAX_RTP_PT) 01692 return -1; /* bogus payload type */ 01693 01694 ast_mutex_lock(&rtp->bridge_lock); 01695 01696 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01697 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01698 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01699 found = 1; 01700 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01701 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01702 mimeTypes[i].payloadType.isAstFormat && 01703 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01704 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01705 break; 01706 } 01707 } 01708 01709 ast_mutex_unlock(&rtp->bridge_lock); 01710 01711 return (found ? 0 : -1); 01712 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 542 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00543 { 00544 rtp->rtptimeout = timeout; 00545 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 535 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00536 { 00537 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00538 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00539 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 601 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_DTMF.
Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), sip_alloc(), and sip_dtmfmode().
00602 { 00603 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00604 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 606 of file rtp.c.
References ast_set2_flag, and FLAG_DTMF_COMPENSATE.
Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), and sip_alloc().
00607 { 00608 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00609 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 591 of file rtp.c.
References ast_rtp::nat.
Referenced by __oh323_rtp_create(), do_setnat(), oh323_rtp_read(), and start_rtp().
void ast_rtp_setstun | ( | struct ast_rtp * | rtp, | |
int | stun_enable | |||
) |
Enable STUN capability.
Definition at line 611 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00612 { 00613 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00614 }
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 2009 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
02010 { 02011 int res; 02012 02013 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 02014 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 02015 return res; 02016 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2065 of file rtp.c.
References ast_clear_flag, AST_SCHED_DEL, FLAG_P2P_SENT_MARK, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::them, and ast_rtcp::them.
Referenced by process_sdp(), setup_rtp_connection(), and stop_media_flows().
02066 { 02067 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02068 02069 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02070 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02071 if (rtp->rtcp) { 02072 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02073 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02074 } 02075 02076 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02077 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Definition at line 403 of file rtp.c.
References append_attr_string(), stun_attr::attr, ast_rtp::s, STUN_BINDREQ, stun_req_id(), stun_send(), and STUN_USERNAME.
Referenced by gtalk_update_stun().
00404 { 00405 struct stun_header *req; 00406 unsigned char reqdata[1024]; 00407 int reqlen, reqleft; 00408 struct stun_attr *attr; 00409 00410 req = (struct stun_header *)reqdata; 00411 stun_req_id(req); 00412 reqlen = 0; 00413 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00414 req->msgtype = 0; 00415 req->msglen = 0; 00416 attr = (struct stun_attr *)req->ies; 00417 if (username) 00418 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00419 req->msglen = htons(reqlen); 00420 req->msgtype = htons(STUN_BINDREQ); 00421 stun_send(rtp->s, suggestion, req); 00422 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
clear payload type
Definition at line 1669 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by process_sdp().
01670 { 01671 if (pt < 0 || pt > MAX_RTP_PT) 01672 return; /* bogus payload type */ 01673 01674 ast_mutex_lock(&rtp->bridge_lock); 01675 rtp->current_RTP_PT[pt].isAstFormat = 0; 01676 rtp->current_RTP_PT[pt].code = 0; 01677 ast_mutex_unlock(&rtp->bridge_lock); 01678 }
Definition at line 2753 of file rtp.c.
References ast_codec_pref_getsize(), AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_frame::datalen, f, fmt, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
Referenced by gtalk_write(), mgcp_write(), oh323_write(), sip_write(), and skinny_write().
02754 { 02755 struct ast_frame *f; 02756 int codec; 02757 int hdrlen = 12; 02758 int subclass; 02759 02760 02761 /* If we have no peer, return immediately */ 02762 if (!rtp->them.sin_addr.s_addr) 02763 return 0; 02764 02765 /* If there is no data length, return immediately */ 02766 if (!_f->datalen) 02767 return 0; 02768 02769 /* Make sure we have enough space for RTP header */ 02770 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02771 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02772 return -1; 02773 } 02774 02775 subclass = _f->subclass; 02776 if (_f->frametype == AST_FRAME_VIDEO) 02777 subclass &= ~0x1; 02778 02779 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02780 if (codec < 0) { 02781 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02782 return -1; 02783 } 02784 02785 if (rtp->lasttxformat != subclass) { 02786 /* New format, reset the smoother */ 02787 if (option_debug) 02788 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02789 rtp->lasttxformat = subclass; 02790 if (rtp->smoother) 02791 ast_smoother_free(rtp->smoother); 02792 rtp->smoother = NULL; 02793 } 02794 02795 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 02796 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02797 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02798 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02799 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); 02800 return -1; 02801 } 02802 if (fmt.flags) 02803 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02804 if (option_debug) 02805 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); 02806 } 02807 } 02808 if (rtp->smoother) { 02809 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02810 ast_smoother_feed_be(rtp->smoother, _f); 02811 } else { 02812 ast_smoother_feed(rtp->smoother, _f); 02813 } 02814 02815 while((f = ast_smoother_read(rtp->smoother)) && (f->data)) 02816 ast_rtp_raw_write(rtp, f, codec); 02817 } else { 02818 /* Don't buffer outgoing frames; send them one-per-packet: */ 02819 if (_f->offset < hdrlen) { 02820 f = ast_frdup(_f); 02821 } else { 02822 f = _f; 02823 } 02824 if (f->data) 02825 ast_rtp_raw_write(rtp, f, codec); 02826 if (f != _f) 02827 ast_frfree(f); 02828 } 02829 02830 return 0; 02831 }
static enum ast_bridge_result bridge_native_loop | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
struct ast_rtp * | p0, | |||
struct ast_rtp * | p1, | |||
struct ast_rtp * | vp0, | |||
struct ast_rtp * | vp1, | |||
struct ast_rtp_protocol * | pr0, | |||
struct ast_rtp_protocol * | pr1, | |||
int | codec0, | |||
int | codec1, | |||
int | timeoutms, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
void * | pvt0, | |||
void * | pvt1 | |||
) | [static] |
Bridge loop for true native bridge (reinvite).
Definition at line 2861 of file rtp.c.
References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate_data(), ast_inet_ntoa(), ast_log(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), ast_channel::audiohooks, ast_frame::data, ast_frame::datalen, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, inaddrcmp(), LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
02862 { 02863 struct ast_frame *fr = NULL; 02864 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02865 int oldcodec0 = codec0, oldcodec1 = codec1; 02866 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02867 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02868 02869 /* Set it up so audio goes directly between the two endpoints */ 02870 02871 /* Test the first channel */ 02872 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02873 ast_rtp_get_peer(p1, &ac1); 02874 if (vp1) 02875 ast_rtp_get_peer(vp1, &vac1); 02876 } else 02877 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 02878 02879 /* Test the second channel */ 02880 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 02881 ast_rtp_get_peer(p0, &ac0); 02882 if (vp0) 02883 ast_rtp_get_peer(vp0, &vac0); 02884 } else 02885 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 02886 02887 /* Now we can unlock and move into our loop */ 02888 ast_channel_unlock(c0); 02889 ast_channel_unlock(c1); 02890 02891 /* Throw our channels into the structure and enter the loop */ 02892 cs[0] = c0; 02893 cs[1] = c1; 02894 cs[2] = NULL; 02895 for (;;) { 02896 /* Check if anything changed */ 02897 if ((c0->tech_pvt != pvt0) || 02898 (c1->tech_pvt != pvt1) || 02899 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 02900 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 02901 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 02902 if (c0->tech_pvt == pvt0) 02903 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02904 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02905 if (c1->tech_pvt == pvt1) 02906 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02907 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02908 return AST_BRIDGE_RETRY; 02909 } 02910 02911 /* Check if they have changed their address */ 02912 ast_rtp_get_peer(p1, &t1); 02913 if (vp1) 02914 ast_rtp_get_peer(vp1, &vt1); 02915 if (pr1->get_codec) 02916 codec1 = pr1->get_codec(c1); 02917 ast_rtp_get_peer(p0, &t0); 02918 if (vp0) 02919 ast_rtp_get_peer(vp0, &vt0); 02920 if (pr0->get_codec) 02921 codec0 = pr0->get_codec(c0); 02922 if ((inaddrcmp(&t1, &ac1)) || 02923 (vp1 && inaddrcmp(&vt1, &vac1)) || 02924 (codec1 != oldcodec1)) { 02925 if (option_debug > 1) { 02926 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02927 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 02928 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 02929 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 02930 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02931 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 02932 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02933 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 02934 } 02935 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 02936 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 02937 memcpy(&ac1, &t1, sizeof(ac1)); 02938 memcpy(&vac1, &vt1, sizeof(vac1)); 02939 oldcodec1 = codec1; 02940 } 02941 if ((inaddrcmp(&t0, &ac0)) || 02942 (vp0 && inaddrcmp(&vt0, &vac0))) { 02943 if (option_debug > 1) { 02944 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02945 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 02946 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02947 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 02948 } 02949 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 02950 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 02951 memcpy(&ac0, &t0, sizeof(ac0)); 02952 memcpy(&vac0, &vt0, sizeof(vac0)); 02953 oldcodec0 = codec0; 02954 } 02955 02956 /* Wait for frame to come in on the channels */ 02957 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 02958 if (!timeoutms) { 02959 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02960 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02961 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02962 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02963 return AST_BRIDGE_RETRY; 02964 } 02965 if (option_debug) 02966 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 02967 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 02968 break; 02969 continue; 02970 } 02971 fr = ast_read(who); 02972 other = (who == c0) ? c1 : c0; 02973 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 02974 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 02975 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 02976 /* Break out of bridge */ 02977 *fo = fr; 02978 *rc = who; 02979 if (option_debug) 02980 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 02981 if (c0->tech_pvt == pvt0) 02982 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02983 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02984 if (c1->tech_pvt == pvt1) 02985 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02986 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02987 return AST_BRIDGE_COMPLETE; 02988 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02989 if ((fr->subclass == AST_CONTROL_HOLD) || 02990 (fr->subclass == AST_CONTROL_UNHOLD) || 02991 (fr->subclass == AST_CONTROL_VIDUPDATE) || 02992 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 02993 if (fr->subclass == AST_CONTROL_HOLD) { 02994 /* If we someone went on hold we want the other side to reinvite back to us */ 02995 if (who == c0) 02996 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 02997 else 02998 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 02999 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03000 /* If they went off hold they should go back to being direct */ 03001 if (who == c0) 03002 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 03003 else 03004 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 03005 } 03006 /* Update local address information */ 03007 ast_rtp_get_peer(p0, &t0); 03008 memcpy(&ac0, &t0, sizeof(ac0)); 03009 ast_rtp_get_peer(p1, &t1); 03010 memcpy(&ac1, &t1, sizeof(ac1)); 03011 /* Update codec information */ 03012 if (pr0->get_codec && c0->tech_pvt) 03013 oldcodec0 = codec0 = pr0->get_codec(c0); 03014 if (pr1->get_codec && c1->tech_pvt) 03015 oldcodec1 = codec1 = pr1->get_codec(c1); 03016 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03017 ast_frfree(fr); 03018 } else { 03019 *fo = fr; 03020 *rc = who; 03021 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03022 return AST_BRIDGE_COMPLETE; 03023 } 03024 } else { 03025 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03026 (fr->frametype == AST_FRAME_DTMF_END) || 03027 (fr->frametype == AST_FRAME_VOICE) || 03028 (fr->frametype == AST_FRAME_VIDEO) || 03029 (fr->frametype == AST_FRAME_IMAGE) || 03030 (fr->frametype == AST_FRAME_HTML) || 03031 (fr->frametype == AST_FRAME_MODEM) || 03032 (fr->frametype == AST_FRAME_TEXT)) { 03033 ast_write(other, fr); 03034 } 03035 ast_frfree(fr); 03036 } 03037 /* Swap priority */ 03038 cs[2] = cs[0]; 03039 cs[0] = cs[1]; 03040 cs[1] = cs[2]; 03041 } 03042 03043 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03044 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03045 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03046 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03047 03048 return AST_BRIDGE_FAILED; 03049 }
static enum ast_bridge_result bridge_p2p_loop | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
struct ast_rtp * | p0, | |||
struct ast_rtp * | p1, | |||
int | timeoutms, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
void * | pvt0, | |||
void * | pvt1 | |||
) | [static] |
Bridge loop for partial native bridge (packet2packet).
Definition at line 3147 of file rtp.c.
References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_unlock, ast_clear_flag, ast_frfree, ast_log(), ast_read(), ast_channel::audiohooks, FLAG_P2P_SENT_MARK, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, p2p_callback_enable(), p2p_set_bridge(), ast_channel::rawreadformat, ast_channel::rawwriteformat, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
03148 { 03149 struct ast_frame *fr = NULL; 03150 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03151 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03152 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03153 int p0_callback = 0, p1_callback = 0; 03154 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03155 03156 /* Okay, setup each RTP structure to do P2P forwarding */ 03157 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03158 p2p_set_bridge(p0, p1); 03159 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03160 p2p_set_bridge(p1, p0); 03161 03162 /* Activate callback modes if possible */ 03163 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03164 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03165 03166 /* Now let go of the channel locks and be on our way */ 03167 ast_channel_unlock(c0); 03168 ast_channel_unlock(c1); 03169 03170 /* Go into a loop forwarding frames until we don't need to anymore */ 03171 cs[0] = c0; 03172 cs[1] = c1; 03173 cs[2] = NULL; 03174 for (;;) { 03175 /* If the underlying formats have changed force this bridge to break */ 03176 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 03177 ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n"); 03178 res = AST_BRIDGE_FAILED_NOWARN; 03179 break; 03180 } 03181 /* Check if anything changed */ 03182 if ((c0->tech_pvt != pvt0) || 03183 (c1->tech_pvt != pvt1) || 03184 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03185 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03186 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03187 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03188 ast_frfree(fr); 03189 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03190 ast_frfree(fr); 03191 res = AST_BRIDGE_RETRY; 03192 break; 03193 } 03194 /* Wait on a channel to feed us a frame */ 03195 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03196 if (!timeoutms) { 03197 res = AST_BRIDGE_RETRY; 03198 break; 03199 } 03200 if (option_debug) 03201 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03202 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03203 break; 03204 continue; 03205 } 03206 /* Read in frame from channel */ 03207 fr = ast_read(who); 03208 other = (who == c0) ? c1 : c0; 03209 /* Dependong on the frame we may need to break out of our bridge */ 03210 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03211 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03212 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03213 /* Record received frame and who */ 03214 *fo = fr; 03215 *rc = who; 03216 if (option_debug) 03217 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03218 res = AST_BRIDGE_COMPLETE; 03219 break; 03220 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03221 if ((fr->subclass == AST_CONTROL_HOLD) || 03222 (fr->subclass == AST_CONTROL_UNHOLD) || 03223 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03224 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03225 /* If we are going on hold, then break callback mode and P2P bridging */ 03226 if (fr->subclass == AST_CONTROL_HOLD) { 03227 if (p0_callback) 03228 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03229 if (p1_callback) 03230 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03231 p2p_set_bridge(p0, NULL); 03232 p2p_set_bridge(p1, NULL); 03233 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03234 /* If we are off hold, then go back to callback mode and P2P bridging */ 03235 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03236 p2p_set_bridge(p0, p1); 03237 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03238 p2p_set_bridge(p1, p0); 03239 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03240 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03241 } 03242 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03243 ast_frfree(fr); 03244 } else { 03245 *fo = fr; 03246 *rc = who; 03247 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03248 res = AST_BRIDGE_COMPLETE; 03249 break; 03250 } 03251 } else { 03252 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03253 (fr->frametype == AST_FRAME_DTMF_END) || 03254 (fr->frametype == AST_FRAME_VOICE) || 03255 (fr->frametype == AST_FRAME_VIDEO) || 03256 (fr->frametype == AST_FRAME_IMAGE) || 03257 (fr->frametype == AST_FRAME_HTML) || 03258 (fr->frametype == AST_FRAME_MODEM) || 03259 (fr->frametype == AST_FRAME_TEXT)) { 03260 ast_write(other, fr); 03261 } 03262 03263 ast_frfree(fr); 03264 } 03265 /* Swap priority */ 03266 cs[2] = cs[0]; 03267 cs[0] = cs[1]; 03268 cs[1] = cs[2]; 03269 } 03270 03271 /* If we are totally avoiding the core, then restore our link to it */ 03272 if (p0_callback) 03273 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03274 if (p1_callback) 03275 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03276 03277 /* Break out of the direct bridge */ 03278 p2p_set_bridge(p0, NULL); 03279 p2p_set_bridge(p1, NULL); 03280 03281 return res; 03282 }
static int bridge_p2p_rtp_write | ( | struct ast_rtp * | rtp, | |
struct ast_rtp * | bridged, | |||
unsigned int * | rtpheader, | |||
int | len, | |||
int | hdrlen | |||
) | [static] |
Perform a Packet2Packet RTP write.
Definition at line 1053 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_set_flag, ast_test_flag, ast_verbose(), rtpPayloadType::code, ast_rtp::current_RTP_PT, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_P2P_NEED_DTMF, FLAG_P2P_SENT_MARK, rtpPayloadType::isAstFormat, LOG_DEBUG, ast_rtp::nat, option_debug, reconstruct(), rtp_debug_test_addr(), ast_rtp::s, and ast_rtp::them.
Referenced by ast_rtp_read().
01054 { 01055 int res = 0, payload = 0, bridged_payload = 0, mark; 01056 struct rtpPayloadType rtpPT; 01057 int reconstruct = ntohl(rtpheader[0]); 01058 01059 /* Get fields from packet */ 01060 payload = (reconstruct & 0x7f0000) >> 16; 01061 mark = (((reconstruct & 0x800000) >> 23) != 0); 01062 01063 /* Check what the payload value should be */ 01064 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01065 01066 /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */ 01067 if (!bridged->current_RTP_PT[payload].code) 01068 return -1; 01069 01070 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01071 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01072 return -1; 01073 01074 /* Otherwise adjust bridged payload to match */ 01075 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01076 01077 /* If the mark bit has not been sent yet... do it now */ 01078 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01079 mark = 1; 01080 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01081 } 01082 01083 /* Reconstruct part of the packet */ 01084 reconstruct &= 0xFF80FFFF; 01085 reconstruct |= (bridged_payload << 16); 01086 reconstruct |= (mark << 23); 01087 rtpheader[0] = htonl(reconstruct); 01088 01089 /* Send the packet back out */ 01090 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01091 if (res < 0) { 01092 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01093 ast_log(LOG_DEBUG, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno)); 01094 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01095 if (option_debug || rtpdebug) 01096 ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port)); 01097 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01098 } 01099 return 0; 01100 } else if (rtp_debug_test_addr(&bridged->them)) 01101 ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), bridged_payload, len - hdrlen); 01102 01103 return 0; 01104 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1004 of file rtp.c.
References ast_rtp::drxcore, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtp::rtcp, ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtp::rxtransit, and ast_rtp::seedrxts.
Referenced by ast_rtp_read(), and schedule_delivery().
01005 { 01006 struct timeval now; 01007 double transit; 01008 double current_time; 01009 double d; 01010 double dtv; 01011 double prog; 01012 01013 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01014 gettimeofday(&rtp->rxcore, NULL); 01015 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01016 /* map timestamp to a real time */ 01017 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01018 rtp->rxcore.tv_sec -= timestamp / 8000; 01019 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01020 /* Round to 0.1ms for nice, pretty timestamps */ 01021 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01022 if (rtp->rxcore.tv_usec < 0) { 01023 /* Adjust appropriately if necessary */ 01024 rtp->rxcore.tv_usec += 1000000; 01025 rtp->rxcore.tv_sec -= 1; 01026 } 01027 } 01028 01029 gettimeofday(&now,NULL); 01030 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01031 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01032 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01033 if (tv->tv_usec >= 1000000) { 01034 tv->tv_usec -= 1000000; 01035 tv->tv_sec += 1; 01036 } 01037 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01038 dtv = (double)rtp->drxcore + (double)(prog); 01039 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01040 transit = current_time - dtv; 01041 d = transit - rtp->rxtransit; 01042 rtp->rxtransit = transit; 01043 if (d<0) 01044 d=-d; 01045 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01046 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01047 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01048 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01049 rtp->rtcp->minrxjitter = rtp->rxjitter; 01050 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2182 of file rtp.c.
References t, and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02183 { 02184 struct timeval t; 02185 long ms; 02186 if (ast_tvzero(rtp->txcore)) { 02187 rtp->txcore = ast_tvnow(); 02188 /* Round to 20ms for nice, pretty timestamps */ 02189 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02190 } 02191 /* Use previous txcore if available */ 02192 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02193 ms = ast_tvdiff_ms(t, rtp->txcore); 02194 if (ms < 0) 02195 ms = 0; 02196 /* Use what we just got for next time */ 02197 rtp->txcore = t; 02198 return (unsigned int) ms; 02199 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 1480 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, protos, ast_channel::tech, ast_channel_tech::type, and ast_rtp_protocol::type.
Referenced by ast_rtp_bridge(), ast_rtp_early_bridge(), ast_rtp_make_compatible(), and ast_udptl_bridge().
01481 { 01482 struct ast_rtp_protocol *cur = NULL; 01483 01484 AST_LIST_LOCK(&protos); 01485 AST_LIST_TRAVERSE(&protos, cur, list) { 01486 if (cur->type == chan->tech->type) 01487 break; 01488 } 01489 AST_LIST_UNLOCK(&protos); 01490 01491 return cur; 01492 }
static int p2p_callback_disable | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
int * | fds, | |||
int ** | iod | |||
) | [static] |
Helper function to switch a channel and RTP stream out of callback mode.
Definition at line 3118 of file rtp.c.
References ast_channel_lock, ast_channel_unlock, ast_io_add(), AST_IO_IN, ast_io_remove(), ast_test_flag, ast_channel::fds, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, rtpread(), and ast_rtp::s.
03119 { 03120 ast_channel_lock(chan); 03121 03122 /* Remove the callback from the IO context */ 03123 ast_io_remove(rtp->io, iod[0]); 03124 03125 /* Restore file descriptors */ 03126 chan->fds[0] = fds[0]; 03127 ast_channel_unlock(chan); 03128 03129 /* Restore callback mode if previously used */ 03130 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03131 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03132 03133 return 0; 03134 }
static int p2p_callback_enable | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
int * | fds, | |||
int ** | iod | |||
) | [static] |
Helper function that sets what an RTP structure is bridged to.
Definition at line 3137 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03138 { 03139 ast_mutex_lock(&rtp0->bridge_lock); 03140 rtp0->bridged = rtp1; 03141 ast_mutex_unlock(&rtp0->bridge_lock); 03142 03143 return; 03144 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 670 of file rtp.c.
References AST_FRAME_DTMF_END, ast_log(), ast_rtp::dtmfcount, event, f, LOG_DEBUG, option_debug, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00671 { 00672 unsigned int event; 00673 char resp = 0; 00674 struct ast_frame *f = NULL; 00675 event = ntohl(*((unsigned int *)(data))); 00676 event &= 0x001F; 00677 if (option_debug > 2 || rtpdebug) 00678 ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len); 00679 if (event < 10) { 00680 resp = '0' + event; 00681 } else if (event < 11) { 00682 resp = '*'; 00683 } else if (event < 12) { 00684 resp = '#'; 00685 } else if (event < 16) { 00686 resp = 'A' + (event - 12); 00687 } else if (event < 17) { 00688 resp = 'X'; 00689 } 00690 if (rtp->resp && (rtp->resp != resp)) { 00691 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00692 } 00693 rtp->resp = resp; 00694 rtp->dtmfcount = dtmftimeout; 00695 return f; 00696 }
static struct ast_frame* process_rfc2833 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp | |||
) | [static] |
Process RTP DTMF and events according to RFC 2833.
RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
rtp | ||
data | ||
len | ||
seqno |
Definition at line 709 of file rtp.c.
References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_null_frame, ast_test_flag, ast_rtp::dtmfcount, ast_rtp::dtmfsamples, event, f, FLAG_DTMF_COMPENSATE, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, ast_frame::samples, and send_dtmf().
Referenced by ast_rtp_read().
00710 { 00711 unsigned int event; 00712 unsigned int event_end; 00713 unsigned int samples; 00714 char resp = 0; 00715 struct ast_frame *f = NULL; 00716 00717 /* Figure out event, event end, and samples */ 00718 event = ntohl(*((unsigned int *)(data))); 00719 event >>= 24; 00720 event_end = ntohl(*((unsigned int *)(data))); 00721 event_end <<= 8; 00722 event_end >>= 24; 00723 samples = ntohl(*((unsigned int *)(data))); 00724 samples &= 0xFFFF; 00725 00726 /* Print out debug if turned on */ 00727 if (rtpdebug || option_debug > 2) 00728 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00729 00730 /* Figure out what digit was pressed */ 00731 if (event < 10) { 00732 resp = '0' + event; 00733 } else if (event < 11) { 00734 resp = '*'; 00735 } else if (event < 12) { 00736 resp = '#'; 00737 } else if (event < 16) { 00738 resp = 'A' + (event - 12); 00739 } else if (event < 17) { /* Event 16: Hook flash */ 00740 resp = 'X'; 00741 } else { 00742 /* Not a supported event */ 00743 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 00744 return &ast_null_frame; 00745 } 00746 00747 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00748 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 00749 rtp->resp = resp; 00750 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00751 f->len = 0; 00752 rtp->lastevent = timestamp; 00753 } 00754 } else { 00755 if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) { 00756 rtp->resp = resp; 00757 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00758 } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) { 00759 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00760 f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */ 00761 rtp->resp = 0; 00762 rtp->lastevent = seqno; 00763 } 00764 } 00765 00766 rtp->dtmfcount = dtmftimeout; 00767 rtp->dtmfsamples = samples; 00768 00769 return f; 00770 }
static struct ast_frame* process_rfc3389 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Process Comfort Noise RTP.
This is incomplete at the moment.
Definition at line 778 of file rtp.c.
References AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, f, FLAG_3389_WARNING, ast_frame::frametype, ast_rtp::lastrxformat, LOG_DEBUG, LOG_NOTICE, ast_frame::offset, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read().
00779 { 00780 struct ast_frame *f = NULL; 00781 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00782 totally help us out becuase we don't have an engine to keep it going and we are not 00783 guaranteed to have it every 20ms or anything */ 00784 if (rtpdebug) 00785 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00786 00787 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00788 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00789 ast_inet_ntoa(rtp->them.sin_addr)); 00790 ast_set_flag(rtp, FLAG_3389_WARNING); 00791 } 00792 00793 /* Must have at least one byte */ 00794 if (!len) 00795 return NULL; 00796 if (len < 24) { 00797 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00798 rtp->f.datalen = len - 1; 00799 rtp->f.offset = AST_FRIENDLY_OFFSET; 00800 memcpy(rtp->f.data, data + 1, len - 1); 00801 } else { 00802 rtp->f.data = NULL; 00803 rtp->f.offset = 0; 00804 rtp->f.datalen = 0; 00805 } 00806 rtp->f.frametype = AST_FRAME_CNG; 00807 rtp->f.subclass = data[0] & 0x7f; 00808 rtp->f.datalen = len - 1; 00809 rtp->f.samples = 0; 00810 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00811 f = &rtp->f; 00812 return f; 00813 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 656 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00657 { 00658 if (rtcpdebug == 0) 00659 return 0; 00660 if (rtcpdebugaddr.sin_addr.s_addr) { 00661 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00662 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00663 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00664 return 0; 00665 } 00666 return 1; 00667 }
static int rtcp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3557 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip().
03557 { 03558 if (argc != 2) { 03559 if (argc != 4) 03560 return RESULT_SHOWUSAGE; 03561 return rtcp_do_debug_ip(fd, argc, argv); 03562 } 03563 rtcpdebug = 1; 03564 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03565 ast_cli(fd, "RTCP Debugging Enabled\n"); 03566 return RESULT_SUCCESS; 03567 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3545 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip_deprecated().
03545 { 03546 if (argc != 3) { 03547 if (argc != 5) 03548 return RESULT_SHOWUSAGE; 03549 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03550 } 03551 rtcpdebug = 1; 03552 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03553 ast_cli(fd, "RTCP Debugging Enabled\n"); 03554 return RESULT_SUCCESS; 03555 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3502 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtcp_do_debug().
03503 { 03504 struct hostent *hp; 03505 struct ast_hostent ahp; 03506 int port = 0; 03507 char *p, *arg; 03508 if (argc != 4) 03509 return RESULT_SHOWUSAGE; 03510 03511 arg = argv[3]; 03512 p = strstr(arg, ":"); 03513 if (p) { 03514 *p = '\0'; 03515 p++; 03516 port = atoi(p); 03517 } 03518 hp = ast_gethostbyname(arg, &ahp); 03519 if (hp == NULL) 03520 return RESULT_SHOWUSAGE; 03521 rtcpdebugaddr.sin_family = AF_INET; 03522 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03523 rtcpdebugaddr.sin_port = htons(port); 03524 if (port == 0) 03525 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03526 else 03527 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03528 rtcpdebug = 1; 03529 return RESULT_SUCCESS; 03530 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3472 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtcp_do_debug_deprecated().
03473 { 03474 struct hostent *hp; 03475 struct ast_hostent ahp; 03476 int port = 0; 03477 char *p, *arg; 03478 if (argc != 5) 03479 return RESULT_SHOWUSAGE; 03480 03481 arg = argv[4]; 03482 p = strstr(arg, ":"); 03483 if (p) { 03484 *p = '\0'; 03485 p++; 03486 port = atoi(p); 03487 } 03488 hp = ast_gethostbyname(arg, &ahp); 03489 if (hp == NULL) 03490 return RESULT_SHOWUSAGE; 03491 rtcpdebugaddr.sin_family = AF_INET; 03492 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03493 rtcpdebugaddr.sin_port = htons(port); 03494 if (port == 0) 03495 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03496 else 03497 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03498 rtcpdebug = 1; 03499 return RESULT_SUCCESS; 03500 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3578 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03578 { 03579 if (argc != 2) { 03580 return RESULT_SHOWUSAGE; 03581 } 03582 rtcpstats = 1; 03583 ast_cli(fd, "RTCP Stats Enabled\n"); 03584 return RESULT_SUCCESS; 03585 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3569 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03569 { 03570 if (argc != 3) { 03571 return RESULT_SHOWUSAGE; 03572 } 03573 rtcpstats = 1; 03574 ast_cli(fd, "RTCP Stats Enabled\n"); 03575 return RESULT_SUCCESS; 03576 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3605 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03606 { 03607 if (argc != 3) 03608 return RESULT_SHOWUSAGE; 03609 rtcpdebug = 0; 03610 ast_cli(fd,"RTCP Debugging Disabled\n"); 03611 return RESULT_SUCCESS; 03612 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3596 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03597 { 03598 if (argc != 4) 03599 return RESULT_SHOWUSAGE; 03600 rtcpdebug = 0; 03601 ast_cli(fd,"RTCP Debugging Disabled\n"); 03602 return RESULT_SUCCESS; 03603 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3623 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03624 { 03625 if (argc != 3) 03626 return RESULT_SHOWUSAGE; 03627 rtcpstats = 0; 03628 ast_cli(fd,"RTCP Stats Disabled\n"); 03629 return RESULT_SUCCESS; 03630 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3614 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03615 { 03616 if (argc != 4) 03617 return RESULT_SHOWUSAGE; 03618 rtcpstats = 0; 03619 ast_cli(fd,"RTCP Stats Disabled\n"); 03620 return RESULT_SUCCESS; 03621 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 643 of file rtp.c.
Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_senddigit_continuation(), ast_rtp_senddigit_end(), and bridge_p2p_rtp_write().
00644 { 00645 if (rtpdebug == 0) 00646 return 0; 00647 if (rtpdebugaddr.sin_addr.s_addr) { 00648 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00649 && (rtpdebugaddr.sin_port != addr->sin_port)) 00650 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00651 return 0; 00652 } 00653 return 1; 00654 }
static int rtp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3532 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtp_do_debug_ip().
03533 { 03534 if (argc != 2) { 03535 if (argc != 4) 03536 return RESULT_SHOWUSAGE; 03537 return rtp_do_debug_ip(fd, argc, argv); 03538 } 03539 rtpdebug = 1; 03540 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03541 ast_cli(fd, "RTP Debugging Enabled\n"); 03542 return RESULT_SUCCESS; 03543 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3442 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtp_do_debug().
03443 { 03444 struct hostent *hp; 03445 struct ast_hostent ahp; 03446 int port = 0; 03447 char *p, *arg; 03448 03449 if (argc != 4) 03450 return RESULT_SHOWUSAGE; 03451 arg = argv[3]; 03452 p = strstr(arg, ":"); 03453 if (p) { 03454 *p = '\0'; 03455 p++; 03456 port = atoi(p); 03457 } 03458 hp = ast_gethostbyname(arg, &ahp); 03459 if (hp == NULL) 03460 return RESULT_SHOWUSAGE; 03461 rtpdebugaddr.sin_family = AF_INET; 03462 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03463 rtpdebugaddr.sin_port = htons(port); 03464 if (port == 0) 03465 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03466 else 03467 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03468 rtpdebug = 1; 03469 return RESULT_SUCCESS; 03470 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3587 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03588 { 03589 if (argc != 3) 03590 return RESULT_SHOWUSAGE; 03591 rtpdebug = 0; 03592 ast_cli(fd,"RTP Debugging Disabled\n"); 03593 return RESULT_SUCCESS; 03594 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1856 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01857 { 01858 int s; 01859 long flags; 01860 s = socket(AF_INET, SOCK_DGRAM, 0); 01861 if (s > -1) { 01862 flags = fcntl(s, F_GETFL); 01863 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01864 #ifdef SO_NO_CHECK 01865 if (nochecksums) 01866 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01867 #endif 01868 } 01869 return s; 01870 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 815 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and f.
Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().
00816 { 00817 struct ast_rtp *rtp = cbdata; 00818 struct ast_frame *f; 00819 f = ast_rtp_read(rtp); 00820 if (f) { 00821 if (rtp->callback) 00822 rtp->callback(rtp, f, rtp->data); 00823 } 00824 return 1; 00825 }
static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static] |
Definition at line 616 of file rtp.c.
References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_test_flag, ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::f, FLAG_DTMF_COMPENSATE, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, option_debug, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.
Referenced by process_cisco_dtmf(), and process_rfc2833().
00617 { 00618 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00619 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00620 if (option_debug) 00621 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00622 rtp->resp = 0; 00623 rtp->dtmfsamples = 0; 00624 return &ast_null_frame; 00625 } 00626 if (option_debug) 00627 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00628 if (rtp->resp == 'X') { 00629 rtp->f.frametype = AST_FRAME_CONTROL; 00630 rtp->f.subclass = AST_CONTROL_FLASH; 00631 } else { 00632 rtp->f.frametype = type; 00633 rtp->f.subclass = rtp->resp; 00634 } 00635 rtp->f.datalen = 0; 00636 rtp->f.samples = 0; 00637 rtp->f.mallocd = 0; 00638 rtp->f.src = "RTP"; 00639 return &rtp->f; 00640 00641 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
Definition at line 300 of file rtp.c.
References STUN_CHANGE_REQUEST, STUN_CHANGED_ADDRESS, STUN_ERROR_CODE, STUN_MAPPED_ADDRESS, STUN_MESSAGE_INTEGRITY, STUN_PASSWORD, STUN_REFLECTED_FROM, STUN_RESPONSE_ADDRESS, STUN_SOURCE_ADDRESS, STUN_UNKNOWN_ATTRIBUTES, and STUN_USERNAME.
Referenced by stun_handle_packet(), and stun_process_attr().
00301 { 00302 switch(msg) { 00303 case STUN_MAPPED_ADDRESS: 00304 return "Mapped Address"; 00305 case STUN_RESPONSE_ADDRESS: 00306 return "Response Address"; 00307 case STUN_CHANGE_REQUEST: 00308 return "Change Request"; 00309 case STUN_SOURCE_ADDRESS: 00310 return "Source Address"; 00311 case STUN_CHANGED_ADDRESS: 00312 return "Changed Address"; 00313 case STUN_USERNAME: 00314 return "Username"; 00315 case STUN_PASSWORD: 00316 return "Password"; 00317 case STUN_MESSAGE_INTEGRITY: 00318 return "Message Integrity"; 00319 case STUN_ERROR_CODE: 00320 return "Error Code"; 00321 case STUN_UNKNOWN_ATTRIBUTES: 00322 return "Unknown Attributes"; 00323 case STUN_REFLECTED_FROM: 00324 return "Reflected From"; 00325 } 00326 return "Non-RFC3489 Attribute"; 00327 }
static int stun_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3632 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03633 { 03634 if (argc != 2) { 03635 return RESULT_SHOWUSAGE; 03636 } 03637 stundebug = 1; 03638 ast_cli(fd, "STUN Debugging Enabled\n"); 03639 return RESULT_SUCCESS; 03640 }
static int stun_handle_packet | ( | int | s, | |
struct sockaddr_in * | src, | |||
unsigned char * | data, | |||
size_t | len | |||
) | [static] |
Definition at line 424 of file rtp.c.
References append_attr_address(), append_attr_string(), ast_log(), ast_verbose(), stun_attr::attr, stun_header::id, stun_header::ies, LOG_DEBUG, stun_header::msglen, stun_header::msgtype, option_debug, STUN_ACCEPT, stun_attr2str(), STUN_BINDREQ, STUN_BINDRESP, STUN_IGNORE, STUN_MAPPED_ADDRESS, stun_msg2str(), stun_process_attr(), stun_send(), and STUN_USERNAME.
Referenced by ast_rtp_read().
00425 { 00426 struct stun_header *resp, *hdr = (struct stun_header *)data; 00427 struct stun_attr *attr; 00428 struct stun_state st; 00429 int ret = STUN_IGNORE; 00430 unsigned char respdata[1024]; 00431 int resplen, respleft; 00432 00433 if (len < sizeof(struct stun_header)) { 00434 if (option_debug) 00435 ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header)); 00436 return -1; 00437 } 00438 if (stundebug) 00439 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen)); 00440 if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) { 00441 if (option_debug) 00442 ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header)); 00443 } else 00444 len = ntohs(hdr->msglen); 00445 data += sizeof(struct stun_header); 00446 memset(&st, 0, sizeof(st)); 00447 while(len) { 00448 if (len < sizeof(struct stun_attr)) { 00449 if (option_debug) 00450 ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr)); 00451 break; 00452 } 00453 attr = (struct stun_attr *)data; 00454 if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) { 00455 if (option_debug) 00456 ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len); 00457 break; 00458 } 00459 if (stun_process_attr(&st, attr)) { 00460 if (option_debug) 00461 ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00462 break; 00463 } 00464 /* Clear attribute in case previous entry was a string */ 00465 attr->attr = 0; 00466 data += ntohs(attr->len) + sizeof(struct stun_attr); 00467 len -= ntohs(attr->len) + sizeof(struct stun_attr); 00468 } 00469 /* Null terminate any string */ 00470 *data = '\0'; 00471 resp = (struct stun_header *)respdata; 00472 resplen = 0; 00473 respleft = sizeof(respdata) - sizeof(struct stun_header); 00474 resp->id = hdr->id; 00475 resp->msgtype = 0; 00476 resp->msglen = 0; 00477 attr = (struct stun_attr *)resp->ies; 00478 if (!len) { 00479 switch(ntohs(hdr->msgtype)) { 00480 case STUN_BINDREQ: 00481 if (stundebug) 00482 ast_verbose("STUN Bind Request, username: %s\n", 00483 st.username ? st.username : "<none>"); 00484 if (st.username) 00485 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00486 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00487 resp->msglen = htons(resplen); 00488 resp->msgtype = htons(STUN_BINDRESP); 00489 stun_send(s, src, resp); 00490 ret = STUN_ACCEPT; 00491 break; 00492 default: 00493 if (stundebug) 00494 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00495 } 00496 } 00497 return ret; 00498 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
Definition at line 281 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00282 { 00283 switch(msg) { 00284 case STUN_BINDREQ: 00285 return "Binding Request"; 00286 case STUN_BINDRESP: 00287 return "Binding Response"; 00288 case STUN_BINDERR: 00289 return "Binding Error Response"; 00290 case STUN_SECREQ: 00291 return "Shared Secret Request"; 00292 case STUN_SECRESP: 00293 return "Shared Secret Response"; 00294 case STUN_SECERR: 00295 return "Shared Secret Error Response"; 00296 } 00297 return "Non-RFC3489 Message"; 00298 }
static int stun_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3642 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03643 { 03644 if (argc != 3) 03645 return RESULT_SHOWUSAGE; 03646 stundebug = 0; 03647 ast_cli(fd, "STUN Debugging Disabled\n"); 03648 return RESULT_SUCCESS; 03649 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 334 of file rtp.c.
References ast_verbose(), stun_attr::attr, stun_attr::len, stun_state::password, stun_attr2str(), STUN_PASSWORD, STUN_USERNAME, stun_state::username, and stun_attr::value.
Referenced by stun_handle_packet().
00335 { 00336 if (stundebug) 00337 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00338 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00339 switch(ntohs(attr->attr)) { 00340 case STUN_USERNAME: 00341 state->username = (const char *) (attr->value); 00342 break; 00343 case STUN_PASSWORD: 00344 state->password = (const char *) (attr->value); 00345 break; 00346 default: 00347 if (stundebug) 00348 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00349 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00350 } 00351 return 0; 00352 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
Definition at line 391 of file rtp.c.
References ast_random(), and stun_header::id.
Referenced by ast_rtp_stun_request().
00392 { 00393 int x; 00394 for (x=0;x<4;x++) 00395 req->id.id[x] = ast_random(); 00396 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
Definition at line 385 of file rtp.c.
References stun_header::msglen.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00386 { 00387 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00388 (struct sockaddr *)dst, sizeof(*dst)); 00389 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 503 of file rtp.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00504 { 00505 unsigned int sec, usec, frac; 00506 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00507 usec = tv.tv_usec; 00508 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00509 *msw = sec; 00510 *lsw = frac; 00511 }
struct ast_cli_entry cli_rtp[] [static] |
struct ast_cli_entry cli_rtp_no_debug_deprecated [static] |
Initial value:
{ { "rtp", "no", "debug", NULL }, rtp_no_debug, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_debug_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "debug", NULL }, rtcp_do_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "debug", "ip", NULL }, rtcp_do_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "no", "debug", NULL }, rtcp_no_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "no", "stats", NULL }, rtcp_no_stats_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_stats_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "stats", NULL }, rtcp_do_stats_deprecated, NULL, NULL }
struct ast_cli_entry cli_stun_no_debug_deprecated [static] |
Initial value:
{ { "stun", "no", "debug", NULL }, stun_no_debug, NULL, NULL }
char debug_usage[] [static] |
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
struct { ... } mimeTypes[] [static] |
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
char no_debug_usage[] [static] |
struct stun_header packed |
Referenced by get_unaligned_uint16(), get_unaligned_uint32(), put_unaligned_uint16(), and put_unaligned_uint32().
struct rtpPayloadType payloadType |
Definition at line 1350 of file rtp.c.
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
char rtcp_debug_usage[] [static] |
char rtcp_no_debug_usage[] [static] |
char rtcp_no_stats_usage[] [static] |
char rtcp_stats_usage[] [static] |
struct sockaddr_in rtcpdebugaddr [static] |
int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static] |
struct sockaddr_in rtpdebugaddr [static] |
int rtpend [static] |
int rtpstart [static] |
struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static] |
Definition at line 1385 of file rtp.c.
Referenced by ast_rtp_codec_getformat(), ast_rtp_lookup_pt(), ast_rtp_pt_default(), and ast_rtp_set_m_type().
char stun_debug_usage[] [static] |
char stun_no_debug_usage[] [static] |
char* subtype |
char* type |
Definition at line 1351 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), find_subscription_type(), g723_len(), load_module(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), parse_information(), parse_setup(), sla_load_config(), subscription_type2str(), and yyparse().