#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"
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_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 1859 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().
01860 { 01861 struct ast_rtcp *rtcp; 01862 01863 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01864 return NULL; 01865 rtcp->s = rtp_socket(); 01866 rtcp->us.sin_family = AF_INET; 01867 rtcp->them.sin_family = AF_INET; 01868 rtcp->schedid = -1; 01869 01870 if (rtcp->s < 0) { 01871 free(rtcp); 01872 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01873 return NULL; 01874 } 01875 01876 return rtcp; 01877 }
Definition at line 827 of file rtp.c.
References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, 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 ast_assert(errno != EBADF); 00859 if (errno != EAGAIN) { 00860 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00861 return NULL; 00862 } 00863 return &ast_null_frame; 00864 } 00865 00866 packetwords = res / 4; 00867 00868 if (rtp->nat) { 00869 /* Send to whoever sent to us */ 00870 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00871 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00872 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00873 if (option_debug || rtpdebug) 00874 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)); 00875 } 00876 } 00877 00878 if (option_debug) 00879 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00880 00881 /* Process a compound packet */ 00882 position = 0; 00883 while (position < packetwords) { 00884 i = position; 00885 length = ntohl(rtcpheader[i]); 00886 pt = (length & 0xff0000) >> 16; 00887 rc = (length & 0x1f000000) >> 24; 00888 length &= 0xffff; 00889 00890 if ((i + length) > packetwords) { 00891 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00892 return &ast_null_frame; 00893 } 00894 00895 if (rtcp_debug_test_addr(&sin)) { 00896 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00897 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00898 ast_verbose("Reception reports: %d\n", rc); 00899 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00900 } 00901 00902 i += 2; /* Advance past header and ssrc */ 00903 00904 switch (pt) { 00905 case RTCP_PT_SR: 00906 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00907 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00908 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00909 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00910 00911 if (rtcp_debug_test_addr(&sin)) { 00912 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00913 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00914 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00915 } 00916 i += 5; 00917 if (rc < 1) 00918 break; 00919 /* Intentional fall through */ 00920 case RTCP_PT_RR: 00921 /* Don't handle multiple reception reports (rc > 1) yet */ 00922 /* Calculate RTT per RFC */ 00923 gettimeofday(&now, NULL); 00924 timeval2ntp(now, &msw, &lsw); 00925 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00926 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00927 lsr = ntohl(rtcpheader[i + 4]); 00928 dlsr = ntohl(rtcpheader[i + 5]); 00929 rtt = comp - lsr - dlsr; 00930 00931 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00932 sess->ee_delay = (eedelay * 1000) / 65536; */ 00933 if (rtt < 4294) { 00934 rtt = (rtt * 1000000) >> 16; 00935 } else { 00936 rtt = (rtt * 1000) >> 16; 00937 rtt *= 1000; 00938 } 00939 rtt = rtt / 1000.; 00940 rttsec = rtt / 1000.; 00941 00942 if (comp - dlsr >= lsr) { 00943 rtp->rtcp->accumulated_transit += rttsec; 00944 rtp->rtcp->rtt = rttsec; 00945 if (rtp->rtcp->maxrtt<rttsec) 00946 rtp->rtcp->maxrtt = rttsec; 00947 if (rtp->rtcp->minrtt>rttsec) 00948 rtp->rtcp->minrtt = rttsec; 00949 } else if (rtcp_debug_test_addr(&sin)) { 00950 ast_verbose("Internal RTCP NTP clock skew detected: " 00951 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 00952 "diff=%d\n", 00953 lsr, comp, dlsr, dlsr / 65536, 00954 (dlsr % 65536) * 1000 / 65536, 00955 dlsr - (comp - lsr)); 00956 } 00957 } 00958 00959 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00960 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00961 if (rtcp_debug_test_addr(&sin)) { 00962 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00963 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00964 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00965 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00966 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00967 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00968 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00969 if (rtt) 00970 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 00971 } 00972 break; 00973 case RTCP_PT_FUR: 00974 if (rtcp_debug_test_addr(&sin)) 00975 ast_verbose("Received an RTCP Fast Update Request\n"); 00976 rtp->f.frametype = AST_FRAME_CONTROL; 00977 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00978 rtp->f.datalen = 0; 00979 rtp->f.samples = 0; 00980 rtp->f.mallocd = 0; 00981 rtp->f.src = "RTP"; 00982 f = &rtp->f; 00983 break; 00984 case RTCP_PT_SDES: 00985 if (rtcp_debug_test_addr(&sin)) 00986 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00987 break; 00988 case RTCP_PT_BYE: 00989 if (rtcp_debug_test_addr(&sin)) 00990 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00991 break; 00992 default: 00993 if (option_debug) 00994 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)); 00995 break; 00996 } 00997 position += (length + 1); 00998 } 00999 01000 return f; 01001 }
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 2341 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02342 { 02343 struct ast_rtp *rtp = data; 02344 int res; 02345 02346 rtp->rtcp->sendfur = 1; 02347 res = ast_rtcp_write(data); 02348 02349 return res; 02350 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2558 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().
02559 { 02560 struct ast_rtp *rtp = (struct ast_rtp *)data; 02561 int res; 02562 02563 if (!rtp || !rtp->rtcp) 02564 return 0; 02565 02566 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02567 res = ast_rtcp_write_sr(data); 02568 else 02569 res = ast_rtcp_write_rr(data); 02570 02571 return res; 02572 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recepient's report.
Definition at line 2463 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().
02464 { 02465 struct ast_rtp *rtp = (struct ast_rtp *)data; 02466 int res; 02467 int len = 32; 02468 unsigned int lost; 02469 unsigned int extended; 02470 unsigned int expected; 02471 unsigned int expected_interval; 02472 unsigned int received_interval; 02473 int lost_interval; 02474 struct timeval now; 02475 unsigned int *rtcpheader; 02476 char bdata[1024]; 02477 struct timeval dlsr; 02478 int fraction; 02479 02480 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02481 return 0; 02482 02483 if (!rtp->rtcp->them.sin_addr.s_addr) { 02484 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02485 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02486 return 0; 02487 } 02488 02489 extended = rtp->cycles + rtp->lastrxseqno; 02490 expected = extended - rtp->seedrxseqno + 1; 02491 lost = expected - rtp->rxcount; 02492 expected_interval = expected - rtp->rtcp->expected_prior; 02493 rtp->rtcp->expected_prior = expected; 02494 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02495 rtp->rtcp->received_prior = rtp->rxcount; 02496 lost_interval = expected_interval - received_interval; 02497 if (expected_interval == 0 || lost_interval <= 0) 02498 fraction = 0; 02499 else 02500 fraction = (lost_interval << 8) / expected_interval; 02501 gettimeofday(&now, NULL); 02502 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02503 rtcpheader = (unsigned int *)bdata; 02504 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02505 rtcpheader[1] = htonl(rtp->ssrc); 02506 rtcpheader[2] = htonl(rtp->themssrc); 02507 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02508 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02509 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02510 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02511 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02512 02513 if (rtp->rtcp->sendfur) { 02514 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02515 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02516 len += 8; 02517 rtp->rtcp->sendfur = 0; 02518 } 02519 02520 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02521 it can change mid call, and SDES can't) */ 02522 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02523 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02524 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02525 len += 12; 02526 02527 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02528 02529 if (res < 0) { 02530 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02531 /* Remove the scheduler */ 02532 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02533 return 0; 02534 } 02535 02536 rtp->rtcp->rr_count++; 02537 02538 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02539 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02540 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02541 " IA jitter: %.4f\n" 02542 " Their last SR: %u\n" 02543 " DLSR: %4.4f (sec)\n\n", 02544 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02545 ntohs(rtp->rtcp->them.sin_port), 02546 rtp->ssrc, rtp->themssrc, fraction, lost, 02547 rtp->rxjitter, 02548 rtp->rtcp->themrxlsr, 02549 (double)(ntohl(rtcpheader[7])/65536.0)); 02550 } 02551 02552 return res; 02553 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2353 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().
02354 { 02355 struct ast_rtp *rtp = (struct ast_rtp *)data; 02356 int res; 02357 int len = 0; 02358 struct timeval now; 02359 unsigned int now_lsw; 02360 unsigned int now_msw; 02361 unsigned int *rtcpheader; 02362 unsigned int lost; 02363 unsigned int extended; 02364 unsigned int expected; 02365 unsigned int expected_interval; 02366 unsigned int received_interval; 02367 int lost_interval; 02368 int fraction; 02369 struct timeval dlsr; 02370 char bdata[512]; 02371 02372 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02373 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02374 return 0; 02375 02376 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02377 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02378 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02379 return 0; 02380 } 02381 02382 gettimeofday(&now, NULL); 02383 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02384 rtcpheader = (unsigned int *)bdata; 02385 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02386 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02387 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02388 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02389 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02390 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02391 len += 28; 02392 02393 extended = rtp->cycles + rtp->lastrxseqno; 02394 expected = extended - rtp->seedrxseqno + 1; 02395 if (rtp->rxcount > expected) 02396 expected += rtp->rxcount - expected; 02397 lost = expected - rtp->rxcount; 02398 expected_interval = expected - rtp->rtcp->expected_prior; 02399 rtp->rtcp->expected_prior = expected; 02400 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02401 rtp->rtcp->received_prior = rtp->rxcount; 02402 lost_interval = expected_interval - received_interval; 02403 if (expected_interval == 0 || lost_interval <= 0) 02404 fraction = 0; 02405 else 02406 fraction = (lost_interval << 8) / expected_interval; 02407 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02408 rtcpheader[7] = htonl(rtp->themssrc); 02409 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02410 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02411 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02412 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02413 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02414 len += 24; 02415 02416 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02417 02418 if (rtp->rtcp->sendfur) { 02419 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02420 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02421 len += 8; 02422 rtp->rtcp->sendfur = 0; 02423 } 02424 02425 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02426 /* it can change mid call, and SDES can't) */ 02427 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02428 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02429 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02430 len += 12; 02431 02432 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02433 if (res < 0) { 02434 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)); 02435 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02436 return 0; 02437 } 02438 02439 /* FIXME Don't need to get a new one */ 02440 gettimeofday(&rtp->rtcp->txlsr, NULL); 02441 rtp->rtcp->sr_count++; 02442 02443 rtp->rtcp->lastsrtxcount = rtp->txcount; 02444 02445 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02446 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02447 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02448 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02449 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02450 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02451 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02452 ast_verbose(" Report block:\n"); 02453 ast_verbose(" Fraction lost: %u\n", fraction); 02454 ast_verbose(" Cumulative loss: %u\n", lost); 02455 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02456 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02457 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02458 } 02459 return res; 02460 }
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 3279 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_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.
03280 { 03281 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03282 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03283 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03284 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03285 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03286 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03287 int codec0 = 0, codec1 = 0; 03288 void *pvt0 = NULL, *pvt1 = NULL; 03289 03290 /* Lock channels */ 03291 ast_channel_lock(c0); 03292 while(ast_channel_trylock(c1)) { 03293 ast_channel_unlock(c0); 03294 usleep(1); 03295 ast_channel_lock(c0); 03296 } 03297 03298 /* Ensure neither channel got hungup during lock avoidance */ 03299 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03300 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03301 ast_channel_unlock(c0); 03302 ast_channel_unlock(c1); 03303 return AST_BRIDGE_FAILED; 03304 } 03305 03306 /* Find channel driver interfaces */ 03307 if (!(pr0 = get_proto(c0))) { 03308 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03309 ast_channel_unlock(c0); 03310 ast_channel_unlock(c1); 03311 return AST_BRIDGE_FAILED; 03312 } 03313 if (!(pr1 = get_proto(c1))) { 03314 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03315 ast_channel_unlock(c0); 03316 ast_channel_unlock(c1); 03317 return AST_BRIDGE_FAILED; 03318 } 03319 03320 /* Get channel specific interface structures */ 03321 pvt0 = c0->tech_pvt; 03322 pvt1 = c1->tech_pvt; 03323 03324 /* Get audio and video interface (if native bridge is possible) */ 03325 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03326 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03327 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03328 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03329 03330 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03331 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03332 audio_p0_res = AST_RTP_GET_FAILED; 03333 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03334 audio_p1_res = AST_RTP_GET_FAILED; 03335 03336 /* Check if a bridge is possible (partial/native) */ 03337 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03338 /* Somebody doesn't want to play... */ 03339 ast_channel_unlock(c0); 03340 ast_channel_unlock(c1); 03341 return AST_BRIDGE_FAILED_NOWARN; 03342 } 03343 03344 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03345 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03346 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03347 audio_p0_res = AST_RTP_TRY_PARTIAL; 03348 } 03349 03350 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03351 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03352 audio_p1_res = AST_RTP_TRY_PARTIAL; 03353 } 03354 03355 /* If both sides are not using the same method of DTMF transmission 03356 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03357 * -------------------------------------------------- 03358 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03359 * |-----------|------------|-----------------------| 03360 * | Inband | False | True | 03361 * | RFC2833 | True | True | 03362 * | SIP INFO | False | False | 03363 * -------------------------------------------------- 03364 * However, if DTMF from both channels is being monitored by the core, then 03365 * we can still do packet-to-packet bridging, because passing through the 03366 * core will handle DTMF mode translation. 03367 */ 03368 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03369 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03370 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03371 ast_channel_unlock(c0); 03372 ast_channel_unlock(c1); 03373 return AST_BRIDGE_FAILED_NOWARN; 03374 } 03375 audio_p0_res = AST_RTP_TRY_PARTIAL; 03376 audio_p1_res = AST_RTP_TRY_PARTIAL; 03377 } 03378 03379 /* If we need to feed frames into the core don't do a P2P bridge */ 03380 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 03381 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 03382 ast_channel_unlock(c0); 03383 ast_channel_unlock(c1); 03384 return AST_BRIDGE_FAILED_NOWARN; 03385 } 03386 03387 /* Get codecs from both sides */ 03388 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03389 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03390 if (codec0 && codec1 && !(codec0 & codec1)) { 03391 /* Hey, we can't do native bridging if both parties speak different codecs */ 03392 if (option_debug) 03393 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03394 ast_channel_unlock(c0); 03395 ast_channel_unlock(c1); 03396 return AST_BRIDGE_FAILED_NOWARN; 03397 } 03398 03399 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03400 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03401 struct ast_format_list fmt0, fmt1; 03402 03403 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03404 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03405 if (option_debug) 03406 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03407 ast_channel_unlock(c0); 03408 ast_channel_unlock(c1); 03409 return AST_BRIDGE_FAILED_NOWARN; 03410 } 03411 /* They must also be using the same packetization */ 03412 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03413 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03414 if (fmt0.cur_ms != fmt1.cur_ms) { 03415 if (option_debug) 03416 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03417 ast_channel_unlock(c0); 03418 ast_channel_unlock(c1); 03419 return AST_BRIDGE_FAILED_NOWARN; 03420 } 03421 03422 if (option_verbose > 2) 03423 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03424 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03425 } else { 03426 if (option_verbose > 2) 03427 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03428 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03429 } 03430 03431 return res; 03432 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2723 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp().
02724 { 02725 if (pt < 0 || pt > MAX_RTP_PT) 02726 return 0; /* bogus payload type */ 02727 02728 if (static_RTP_PT[pt].isAstFormat) 02729 return static_RTP_PT[pt].code; 02730 else 02731 return 0; 02732 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Definition at line 2718 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
02719 { 02720 return &rtp->pref; 02721 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2705 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(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().
02706 { 02707 int x; 02708 for (x = 0; x < 32; x++) { /* Ugly way */ 02709 rtp->pref.order[x] = prefs->order[x]; 02710 rtp->pref.framing[x] = prefs->framing[x]; 02711 } 02712 if (rtp->smoother) 02713 ast_smoother_free(rtp->smoother); 02714 rtp->smoother = NULL; 02715 return 0; 02716 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2124 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().
02125 { 02126 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02127 /*Print some info on the call here */ 02128 ast_verbose(" RTP-stats\n"); 02129 ast_verbose("* Our Receiver:\n"); 02130 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02131 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02132 ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02133 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02134 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02135 ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count); 02136 ast_verbose("* Our Sender:\n"); 02137 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02138 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02139 ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost); 02140 ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0); 02141 ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count); 02142 ast_verbose(" RTT: %f\n", rtp->rtcp->rtt); 02143 } 02144 02145 if (rtp->smoother) 02146 ast_smoother_free(rtp->smoother); 02147 if (rtp->ioid) 02148 ast_io_remove(rtp->io, rtp->ioid); 02149 if (rtp->s > -1) 02150 close(rtp->s); 02151 if (rtp->rtcp) { 02152 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02153 close(rtp->rtcp->s); 02154 free(rtp->rtcp); 02155 rtp->rtcp=NULL; 02156 } 02157 02158 ast_mutex_destroy(&rtp->bridge_lock); 02159 02160 free(rtp); 02161 }
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 1476 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().
01477 { 01478 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01479 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01480 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01481 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01482 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01483 int srccodec, destcodec, nat_active = 0; 01484 01485 /* Lock channels */ 01486 ast_channel_lock(dest); 01487 if (src) { 01488 while(ast_channel_trylock(src)) { 01489 ast_channel_unlock(dest); 01490 usleep(1); 01491 ast_channel_lock(dest); 01492 } 01493 } 01494 01495 /* Find channel driver interfaces */ 01496 destpr = get_proto(dest); 01497 if (src) 01498 srcpr = get_proto(src); 01499 if (!destpr) { 01500 if (option_debug) 01501 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01502 ast_channel_unlock(dest); 01503 if (src) 01504 ast_channel_unlock(src); 01505 return 0; 01506 } 01507 if (!srcpr) { 01508 if (option_debug) 01509 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01510 ast_channel_unlock(dest); 01511 if (src) 01512 ast_channel_unlock(src); 01513 return 0; 01514 } 01515 01516 /* Get audio and video interface (if native bridge is possible) */ 01517 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01518 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01519 if (srcpr) { 01520 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01521 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01522 } 01523 01524 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01525 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01526 /* Somebody doesn't want to play... */ 01527 ast_channel_unlock(dest); 01528 if (src) 01529 ast_channel_unlock(src); 01530 return 0; 01531 } 01532 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01533 srccodec = srcpr->get_codec(src); 01534 else 01535 srccodec = 0; 01536 if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec) 01537 destcodec = destpr->get_codec(dest); 01538 else 01539 destcodec = 0; 01540 /* Ensure we have at least one matching codec */ 01541 if (!(srccodec & destcodec)) { 01542 ast_channel_unlock(dest); 01543 if (src) 01544 ast_channel_unlock(src); 01545 return 0; 01546 } 01547 /* Consider empty media as non-existant */ 01548 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01549 srcp = NULL; 01550 /* If the client has NAT stuff turned on then just safe NAT is active */ 01551 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01552 nat_active = 1; 01553 /* Bridge media early */ 01554 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01555 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01556 ast_channel_unlock(dest); 01557 if (src) 01558 ast_channel_unlock(src); 01559 if (option_debug) 01560 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01561 return 1; 01562 }
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 2035 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().
02036 { 02037 struct ast_rtp *bridged = NULL; 02038 02039 ast_mutex_lock(&rtp->bridge_lock); 02040 bridged = rtp->bridged; 02041 ast_mutex_unlock(&rtp->bridge_lock); 02042 02043 return bridged; 02044 }
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 1698 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 gtalk_is_answered(), gtalk_newcall(), and process_sdp().
01700 { 01701 int pt; 01702 01703 ast_mutex_lock(&rtp->bridge_lock); 01704 01705 *astFormats = *nonAstFormats = 0; 01706 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01707 if (rtp->current_RTP_PT[pt].isAstFormat) { 01708 *astFormats |= rtp->current_RTP_PT[pt].code; 01709 } else { 01710 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01711 } 01712 } 01713 01714 ast_mutex_unlock(&rtp->bridge_lock); 01715 01716 return; 01717 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2017 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), bridge_native_loop(), do_monitor(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
02018 { 02019 if ((them->sin_family != AF_INET) || 02020 (them->sin_port != rtp->them.sin_port) || 02021 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02022 them->sin_family = AF_INET; 02023 them->sin_port = rtp->them.sin_port; 02024 them->sin_addr = rtp->them.sin_addr; 02025 return 1; 02026 } 02027 return 0; 02028 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2080 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().
02081 { 02082 /* 02083 *ssrc our ssrc 02084 *themssrc their ssrc 02085 *lp lost packets 02086 *rxjitter our calculated jitter(rx) 02087 *rxcount no. received packets 02088 *txjitter reported jitter of the other end 02089 *txcount transmitted packets 02090 *rlp remote lost packets 02091 *rtt round trip time 02092 */ 02093 02094 if (qual && rtp) { 02095 qual->local_ssrc = rtp->ssrc; 02096 qual->local_jitter = rtp->rxjitter; 02097 qual->local_count = rtp->rxcount; 02098 qual->remote_ssrc = rtp->themssrc; 02099 qual->remote_count = rtp->txcount; 02100 if (rtp->rtcp) { 02101 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02102 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02103 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02104 qual->rtt = rtp->rtcp->rtt; 02105 } 02106 } 02107 if (rtp->rtcp) { 02108 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02109 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02110 rtp->ssrc, 02111 rtp->themssrc, 02112 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02113 rtp->rxjitter, 02114 rtp->rxcount, 02115 (double)rtp->rtcp->reported_jitter / 65536.0, 02116 rtp->txcount, 02117 rtp->rtcp->reported_lost, 02118 rtp->rtcp->rtt); 02119 return rtp->rtcp->quality; 02120 } else 02121 return "<Unknown> - RTP/RTCP has already been destroyed"; 02122 }
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 2030 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 3817 of file rtp.c.
References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp.
Referenced by main().
03818 { 03819 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03820 ast_rtp_reload(); 03821 }
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 1741 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().
01742 { 01743 int pt = 0; 01744 01745 ast_mutex_lock(&rtp->bridge_lock); 01746 01747 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01748 code == rtp->rtp_lookup_code_cache_code) { 01749 /* Use our cached mapping, to avoid the overhead of the loop below */ 01750 pt = rtp->rtp_lookup_code_cache_result; 01751 ast_mutex_unlock(&rtp->bridge_lock); 01752 return pt; 01753 } 01754 01755 /* Check the dynamic list first */ 01756 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01757 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01758 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01759 rtp->rtp_lookup_code_cache_code = code; 01760 rtp->rtp_lookup_code_cache_result = pt; 01761 ast_mutex_unlock(&rtp->bridge_lock); 01762 return pt; 01763 } 01764 } 01765 01766 /* Then the static list */ 01767 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01768 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01769 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01770 rtp->rtp_lookup_code_cache_code = code; 01771 rtp->rtp_lookup_code_cache_result = pt; 01772 ast_mutex_unlock(&rtp->bridge_lock); 01773 return pt; 01774 } 01775 } 01776 01777 ast_mutex_unlock(&rtp->bridge_lock); 01778 01779 return -1; 01780 }
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 1801 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len, and name.
Referenced by process_sdp().
01803 { 01804 int format; 01805 unsigned len; 01806 char *end = buf; 01807 char *start = buf; 01808 01809 if (!buf || !size) 01810 return NULL; 01811 01812 snprintf(end, size, "0x%x (", capability); 01813 01814 len = strlen(end); 01815 end += len; 01816 size -= len; 01817 start = end; 01818 01819 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01820 if (capability & format) { 01821 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01822 01823 snprintf(end, size, "%s|", name); 01824 len = strlen(end); 01825 end += len; 01826 size -= len; 01827 } 01828 } 01829 01830 if (start == end) 01831 snprintf(start, size, "nothing)"); 01832 else if (size > 1) 01833 *(end -1) = ')'; 01834 01835 return buf; 01836 }
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 1782 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().
01784 { 01785 unsigned int i; 01786 01787 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01788 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01789 if (isAstFormat && 01790 (code == AST_FORMAT_G726_AAL2) && 01791 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01792 return "G726-32"; 01793 else 01794 return mimeTypes[i].subtype; 01795 } 01796 } 01797 01798 return ""; 01799 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1719 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), rtpPayloadType::isAstFormat, MAX_RTP_PT, and static_RTP_PT.
Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().
01720 { 01721 struct rtpPayloadType result; 01722 01723 result.isAstFormat = result.code = 0; 01724 01725 if (pt < 0 || pt > MAX_RTP_PT) 01726 return result; /* bogus payload type */ 01727 01728 /* Start with negotiated codecs */ 01729 ast_mutex_lock(&rtp->bridge_lock); 01730 result = rtp->current_RTP_PT[pt]; 01731 ast_mutex_unlock(&rtp->bridge_lock); 01732 01733 /* If it doesn't exist, check our static RTP type list, just in case */ 01734 if (!result.code) 01735 result = static_RTP_PT[pt]; 01736 01737 return result; 01738 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1564 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().
01565 { 01566 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01567 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01568 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01569 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01570 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01571 int srccodec, destcodec; 01572 01573 /* Lock channels */ 01574 ast_channel_lock(dest); 01575 while(ast_channel_trylock(src)) { 01576 ast_channel_unlock(dest); 01577 usleep(1); 01578 ast_channel_lock(dest); 01579 } 01580 01581 /* Find channel driver interfaces */ 01582 if (!(destpr = get_proto(dest))) { 01583 if (option_debug) 01584 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01585 ast_channel_unlock(dest); 01586 ast_channel_unlock(src); 01587 return 0; 01588 } 01589 if (!(srcpr = get_proto(src))) { 01590 if (option_debug) 01591 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01592 ast_channel_unlock(dest); 01593 ast_channel_unlock(src); 01594 return 0; 01595 } 01596 01597 /* Get audio and video interface (if native bridge is possible) */ 01598 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01599 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01600 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01601 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01602 01603 /* Ensure we have at least one matching codec */ 01604 if (srcpr->get_codec) 01605 srccodec = srcpr->get_codec(src); 01606 else 01607 srccodec = 0; 01608 if (destpr->get_codec) 01609 destcodec = destpr->get_codec(dest); 01610 else 01611 destcodec = 0; 01612 01613 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01614 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) { 01615 /* Somebody doesn't want to play... */ 01616 ast_channel_unlock(dest); 01617 ast_channel_unlock(src); 01618 return 0; 01619 } 01620 ast_rtp_pt_copy(destp, srcp); 01621 if (vdestp && vsrcp) 01622 ast_rtp_pt_copy(vdestp, vsrcp); 01623 if (media) { 01624 /* Bridge early */ 01625 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01626 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01627 } 01628 ast_channel_unlock(dest); 01629 ast_channel_unlock(src); 01630 if (option_debug) 01631 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01632 return 1; 01633 }
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 1983 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
01984 { 01985 struct in_addr ia; 01986 01987 memset(&ia, 0, sizeof(ia)); 01988 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 01989 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1883 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().
01884 { 01885 ast_mutex_init(&rtp->bridge_lock); 01886 01887 rtp->them.sin_family = AF_INET; 01888 rtp->us.sin_family = AF_INET; 01889 rtp->ssrc = ast_random(); 01890 rtp->seqno = ast_random() & 0xffff; 01891 ast_set_flag(rtp, FLAG_HAS_DTMF); 01892 01893 return; 01894 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2000 of file rtp.c.
References ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), sip_write(), and skinny_indicate().
02001 { 02002 rtp->set_marker_bit = 1; 02003 return; 02004 }
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 1896 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().
01897 { 01898 struct ast_rtp *rtp; 01899 int x; 01900 int first; 01901 int startplace; 01902 01903 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01904 return NULL; 01905 01906 ast_rtp_new_init(rtp); 01907 01908 rtp->s = rtp_socket(); 01909 if (rtp->s < 0) { 01910 free(rtp); 01911 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01912 return NULL; 01913 } 01914 if (sched && rtcpenable) { 01915 rtp->sched = sched; 01916 rtp->rtcp = ast_rtcp_new(); 01917 } 01918 01919 /* Select a random port number in the range of possible RTP */ 01920 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01921 x = x & ~1; 01922 /* Save it for future references. */ 01923 startplace = x; 01924 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01925 for (;;) { 01926 /* Must be an even port number by RTP spec */ 01927 rtp->us.sin_port = htons(x); 01928 rtp->us.sin_addr = addr; 01929 /* If there's rtcp, initialize it as well. */ 01930 if (rtp->rtcp) { 01931 rtp->rtcp->us.sin_port = htons(x + 1); 01932 rtp->rtcp->us.sin_addr = addr; 01933 } 01934 /* Try to bind it/them. */ 01935 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01936 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01937 break; 01938 if (!first) { 01939 /* Primary bind succeeded! Gotta recreate it */ 01940 close(rtp->s); 01941 rtp->s = rtp_socket(); 01942 } 01943 if (errno != EADDRINUSE) { 01944 /* We got an error that wasn't expected, abort! */ 01945 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01946 close(rtp->s); 01947 if (rtp->rtcp) { 01948 close(rtp->rtcp->s); 01949 free(rtp->rtcp); 01950 } 01951 free(rtp); 01952 return NULL; 01953 } 01954 /* The port was used, increment it (by two). */ 01955 x += 2; 01956 /* Did we go over the limit ? */ 01957 if (x > rtpend) 01958 /* then, start from the begingig. */ 01959 x = (rtpstart + 1) & ~1; 01960 /* Check if we reached the place were we started. */ 01961 if (x == startplace) { 01962 /* If so, there's no ports available. */ 01963 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 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 } 01973 rtp->sched = sched; 01974 rtp->io = io; 01975 if (callbackmode) { 01976 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01977 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01978 } 01979 ast_rtp_pt_default(rtp); 01980 return rtp; 01981 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2834 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().
02835 { 02836 struct ast_rtp_protocol *cur; 02837 02838 AST_LIST_LOCK(&protos); 02839 AST_LIST_TRAVERSE(&protos, cur, list) { 02840 if (!strcmp(cur->type, proto->type)) { 02841 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02842 AST_LIST_UNLOCK(&protos); 02843 return -1; 02844 } 02845 } 02846 AST_LIST_INSERT_HEAD(&protos, proto, list); 02847 AST_LIST_UNLOCK(&protos); 02848 02849 return 0; 02850 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2826 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.
Referenced by load_module(), and unload_module().
02827 { 02828 AST_LIST_LOCK(&protos); 02829 AST_LIST_REMOVE(&protos, proto, list); 02830 AST_LIST_UNLOCK(&protos); 02831 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1400 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by gtalk_alloc(), and process_sdp().
01401 { 01402 int i; 01403 01404 if (!rtp) 01405 return; 01406 01407 ast_mutex_lock(&rtp->bridge_lock); 01408 01409 for (i = 0; i < MAX_RTP_PT; ++i) { 01410 rtp->current_RTP_PT[i].isAstFormat = 0; 01411 rtp->current_RTP_PT[i].code = 0; 01412 } 01413 01414 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01415 rtp->rtp_lookup_code_cache_code = 0; 01416 rtp->rtp_lookup_code_cache_result = 0; 01417 01418 ast_mutex_unlock(&rtp->bridge_lock); 01419 }
Copy payload types between RTP structures.
Definition at line 1440 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().
01441 { 01442 unsigned int i; 01443 01444 ast_mutex_lock(&dest->bridge_lock); 01445 ast_mutex_lock(&src->bridge_lock); 01446 01447 for (i=0; i < MAX_RTP_PT; ++i) { 01448 dest->current_RTP_PT[i].isAstFormat = 01449 src->current_RTP_PT[i].isAstFormat; 01450 dest->current_RTP_PT[i].code = 01451 src->current_RTP_PT[i].code; 01452 } 01453 dest->rtp_lookup_code_cache_isAstFormat = 0; 01454 dest->rtp_lookup_code_cache_code = 0; 01455 dest->rtp_lookup_code_cache_result = 0; 01456 01457 ast_mutex_unlock(&src->bridge_lock); 01458 ast_mutex_unlock(&dest->bridge_lock); 01459 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1421 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().
01422 { 01423 int i; 01424 01425 ast_mutex_lock(&rtp->bridge_lock); 01426 01427 /* Initialize to default payload types */ 01428 for (i = 0; i < MAX_RTP_PT; ++i) { 01429 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01430 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01431 } 01432 01433 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01434 rtp->rtp_lookup_code_cache_code = 0; 01435 rtp->rtp_lookup_code_cache_result = 0; 01436 01437 ast_mutex_unlock(&rtp->bridge_lock); 01438 }
Definition at line 2609 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().
02610 { 02611 unsigned char *rtpheader; 02612 int hdrlen = 12; 02613 int res; 02614 unsigned int ms; 02615 int pred; 02616 int mark = 0; 02617 02618 ms = calc_txstamp(rtp, &f->delivery); 02619 /* Default prediction */ 02620 if (f->frametype == AST_FRAME_VOICE) { 02621 pred = rtp->lastts + f->samples; 02622 02623 /* Re-calculate last TS */ 02624 rtp->lastts = rtp->lastts + ms * 8; 02625 if (ast_tvzero(f->delivery)) { 02626 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02627 and if so, go with our prediction */ 02628 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02629 rtp->lastts = pred; 02630 else { 02631 if (option_debug > 2) 02632 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02633 mark = 1; 02634 } 02635 } 02636 } else if (f->frametype == AST_FRAME_VIDEO) { 02637 mark = f->subclass & 0x1; 02638 pred = rtp->lastovidtimestamp + f->samples; 02639 /* Re-calculate last TS */ 02640 rtp->lastts = rtp->lastts + ms * 90; 02641 /* If it's close to our prediction, go for it */ 02642 if (ast_tvzero(f->delivery)) { 02643 if (abs(rtp->lastts - pred) < 7200) { 02644 rtp->lastts = pred; 02645 rtp->lastovidtimestamp += f->samples; 02646 } else { 02647 if (option_debug > 2) 02648 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); 02649 rtp->lastovidtimestamp = rtp->lastts; 02650 } 02651 } 02652 } 02653 02654 /* If we have been explicitly told to set the marker bit do so */ 02655 if (rtp->set_marker_bit) { 02656 mark = 1; 02657 rtp->set_marker_bit = 0; 02658 } 02659 02660 /* If the timestamp for non-digit packets has moved beyond the timestamp 02661 for digits, update the digit timestamp. 02662 */ 02663 if (rtp->lastts > rtp->lastdigitts) 02664 rtp->lastdigitts = rtp->lastts; 02665 02666 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 02667 rtp->lastts = f->ts * 8; 02668 02669 /* Get a pointer to the header */ 02670 rtpheader = (unsigned char *)(f->data - hdrlen); 02671 02672 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02673 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02674 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02675 02676 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02677 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02678 if (res <0) { 02679 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02680 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)); 02681 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02682 /* Only give this error message once if we are not RTP debugging */ 02683 if (option_debug || rtpdebug) 02684 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)); 02685 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02686 } 02687 } else { 02688 rtp->txcount++; 02689 rtp->txoctetcount +=(res - hdrlen); 02690 02691 if (rtp->rtcp && rtp->rtcp->schedid < 1) 02692 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02693 } 02694 02695 if (rtp_debug_test_addr(&rtp->them)) 02696 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02697 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02698 } 02699 02700 rtp->seqno++; 02701 02702 return 0; 02703 }
Definition at line 1105 of file rtp.c.
References ast_assert, ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, event, ext, 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_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().
01106 { 01107 int res; 01108 struct sockaddr_in sin; 01109 socklen_t len; 01110 unsigned int seqno; 01111 int version; 01112 int payloadtype; 01113 int hdrlen = 12; 01114 int padding; 01115 int mark; 01116 int ext; 01117 int cc; 01118 unsigned int ssrc; 01119 unsigned int timestamp; 01120 unsigned int *rtpheader; 01121 struct rtpPayloadType rtpPT; 01122 struct ast_rtp *bridged = NULL; 01123 01124 /* If time is up, kill it */ 01125 if (rtp->sending_digit) 01126 ast_rtp_senddigit_continuation(rtp); 01127 01128 len = sizeof(sin); 01129 01130 /* Cache where the header will go */ 01131 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01132 0, (struct sockaddr *)&sin, &len); 01133 01134 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01135 if (res < 0) { 01136 ast_assert(errno != EBADF); 01137 if (errno != EAGAIN) { 01138 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01139 return NULL; 01140 } 01141 return &ast_null_frame; 01142 } 01143 01144 if (res < hdrlen) { 01145 ast_log(LOG_WARNING, "RTP Read too short\n"); 01146 return &ast_null_frame; 01147 } 01148 01149 /* Get fields */ 01150 seqno = ntohl(rtpheader[0]); 01151 01152 /* Check RTP version */ 01153 version = (seqno & 0xC0000000) >> 30; 01154 if (!version) { 01155 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01156 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01157 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01158 } 01159 return &ast_null_frame; 01160 } 01161 01162 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01163 /* If we don't have the other side's address, then ignore this */ 01164 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01165 return &ast_null_frame; 01166 #endif 01167 01168 /* Send to whoever send to us if NAT is turned on */ 01169 if (rtp->nat) { 01170 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01171 (rtp->them.sin_port != sin.sin_port)) { 01172 rtp->them = sin; 01173 if (rtp->rtcp) { 01174 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01175 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01176 } 01177 rtp->rxseqno = 0; 01178 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01179 if (option_debug || rtpdebug) 01180 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)); 01181 } 01182 } 01183 01184 /* If we are bridged to another RTP stream, send direct */ 01185 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01186 return &ast_null_frame; 01187 01188 if (version != 2) 01189 return &ast_null_frame; 01190 01191 payloadtype = (seqno & 0x7f0000) >> 16; 01192 padding = seqno & (1 << 29); 01193 mark = seqno & (1 << 23); 01194 ext = seqno & (1 << 28); 01195 cc = (seqno & 0xF000000) >> 24; 01196 seqno &= 0xffff; 01197 timestamp = ntohl(rtpheader[1]); 01198 ssrc = ntohl(rtpheader[2]); 01199 01200 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01201 if (option_debug || rtpdebug) 01202 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01203 mark = 1; 01204 } 01205 01206 rtp->rxssrc = ssrc; 01207 01208 if (padding) { 01209 /* Remove padding bytes */ 01210 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01211 } 01212 01213 if (cc) { 01214 /* CSRC fields present */ 01215 hdrlen += cc*4; 01216 } 01217 01218 if (ext) { 01219 /* RTP Extension present */ 01220 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01221 hdrlen += 4; 01222 } 01223 01224 if (res < hdrlen) { 01225 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01226 return &ast_null_frame; 01227 } 01228 01229 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01230 01231 if (rtp->rxcount==1) { 01232 /* This is the first RTP packet successfully received from source */ 01233 rtp->seedrxseqno = seqno; 01234 } 01235 01236 /* Do not schedule RR if RTCP isn't run */ 01237 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01238 /* Schedule transmission of Receiver Report */ 01239 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01240 } 01241 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01242 rtp->cycles += RTP_SEQ_MOD; 01243 01244 rtp->lastrxseqno = seqno; 01245 01246 if (rtp->themssrc==0) 01247 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01248 01249 if (rtp_debug_test_addr(&sin)) 01250 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01251 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01252 01253 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01254 if (!rtpPT.isAstFormat) { 01255 struct ast_frame *f = NULL; 01256 01257 /* This is special in-band data that's not one of our codecs */ 01258 if (rtpPT.code == AST_RTP_DTMF) { 01259 /* It's special -- rfc2833 process it */ 01260 if (rtp_debug_test_addr(&sin)) { 01261 unsigned char *data; 01262 unsigned int event; 01263 unsigned int event_end; 01264 unsigned int duration; 01265 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01266 event = ntohl(*((unsigned int *)(data))); 01267 event >>= 24; 01268 event_end = ntohl(*((unsigned int *)(data))); 01269 event_end <<= 8; 01270 event_end >>= 24; 01271 duration = ntohl(*((unsigned int *)(data))); 01272 duration &= 0xFFFF; 01273 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); 01274 } 01275 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01276 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01277 /* It's really special -- process it the Cisco way */ 01278 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01279 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01280 rtp->lastevent = seqno; 01281 } 01282 } else if (rtpPT.code == AST_RTP_CN) { 01283 /* Comfort Noise */ 01284 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01285 } else { 01286 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01287 } 01288 return f ? f : &ast_null_frame; 01289 } 01290 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01291 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01292 01293 if (!rtp->lastrxts) 01294 rtp->lastrxts = timestamp; 01295 01296 rtp->rxseqno = seqno; 01297 01298 /* Record received timestamp as last received now */ 01299 rtp->lastrxts = timestamp; 01300 01301 rtp->f.mallocd = 0; 01302 rtp->f.datalen = res - hdrlen; 01303 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01304 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01305 rtp->f.seqno = seqno; 01306 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01307 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01308 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01309 ast_frame_byteswap_be(&rtp->f); 01310 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01311 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01312 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01313 rtp->f.ts = timestamp / 8; 01314 rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000); 01315 } else { 01316 /* Video -- samples is # of samples vs. 90000 */ 01317 if (!rtp->lastividtimestamp) 01318 rtp->lastividtimestamp = timestamp; 01319 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01320 rtp->lastividtimestamp = timestamp; 01321 rtp->f.delivery.tv_sec = 0; 01322 rtp->f.delivery.tv_usec = 0; 01323 if (mark) 01324 rtp->f.subclass |= 0x1; 01325 01326 } 01327 rtp->f.src = "RTP"; 01328 return &rtp->f; 01329 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3752 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().
03753 { 03754 struct ast_config *cfg; 03755 const char *s; 03756 03757 rtpstart = 5000; 03758 rtpend = 31000; 03759 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03760 cfg = ast_config_load("rtp.conf"); 03761 if (cfg) { 03762 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03763 rtpstart = atoi(s); 03764 if (rtpstart < 1024) 03765 rtpstart = 1024; 03766 if (rtpstart > 65535) 03767 rtpstart = 65535; 03768 } 03769 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03770 rtpend = atoi(s); 03771 if (rtpend < 1024) 03772 rtpend = 1024; 03773 if (rtpend > 65535) 03774 rtpend = 65535; 03775 } 03776 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03777 rtcpinterval = atoi(s); 03778 if (rtcpinterval == 0) 03779 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03780 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03781 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03782 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03783 rtcpinterval = RTCP_MAX_INTERVALMS; 03784 } 03785 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03786 #ifdef SO_NO_CHECK 03787 if (ast_false(s)) 03788 nochecksums = 1; 03789 else 03790 nochecksums = 0; 03791 #else 03792 if (ast_false(s)) 03793 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03794 #endif 03795 } 03796 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03797 dtmftimeout = atoi(s); 03798 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03799 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03800 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03801 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03802 }; 03803 } 03804 ast_config_destroy(cfg); 03805 } 03806 if (rtpstart >= rtpend) { 03807 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03808 rtpstart = 5000; 03809 rtpend = 31000; 03810 } 03811 if (option_verbose > 1) 03812 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03813 return 0; 03814 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2060 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.
02061 { 02062 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02063 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02064 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02065 rtp->lastts = 0; 02066 rtp->lastdigitts = 0; 02067 rtp->lastrxts = 0; 02068 rtp->lastividtimestamp = 0; 02069 rtp->lastovidtimestamp = 0; 02070 rtp->lasteventseqn = 0; 02071 rtp->lastevent = 0; 02072 rtp->lasttxformat = 0; 02073 rtp->lastrxformat = 0; 02074 rtp->dtmfcount = 0; 02075 rtp->dtmfsamples = 0; 02076 rtp->seqno = 0; 02077 rtp->rxseqno = 0; 02078 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2575 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().
02576 { 02577 unsigned int *rtpheader; 02578 int hdrlen = 12; 02579 int res; 02580 int payload; 02581 char data[256]; 02582 level = 127 - (level & 0x7f); 02583 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02584 02585 /* If we have no peer, return immediately */ 02586 if (!rtp->them.sin_addr.s_addr) 02587 return 0; 02588 02589 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02590 02591 /* Get a pointer to the header */ 02592 rtpheader = (unsigned int *)data; 02593 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02594 rtpheader[1] = htonl(rtp->lastts); 02595 rtpheader[2] = htonl(rtp->ssrc); 02596 data[12] = level; 02597 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02598 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02599 if (res <0) 02600 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)); 02601 if (rtp_debug_test_addr(&rtp->them)) 02602 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02603 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02604 02605 } 02606 return 0; 02607 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2183 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().
02184 { 02185 unsigned int *rtpheader; 02186 int hdrlen = 12, res = 0, i = 0, payload = 0; 02187 char data[256]; 02188 02189 if ((digit <= '9') && (digit >= '0')) 02190 digit -= '0'; 02191 else if (digit == '*') 02192 digit = 10; 02193 else if (digit == '#') 02194 digit = 11; 02195 else if ((digit >= 'A') && (digit <= 'D')) 02196 digit = digit - 'A' + 12; 02197 else if ((digit >= 'a') && (digit <= 'd')) 02198 digit = digit - 'a' + 12; 02199 else { 02200 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02201 return 0; 02202 } 02203 02204 /* If we have no peer, return immediately */ 02205 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02206 return 0; 02207 02208 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02209 02210 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02211 rtp->send_duration = 160; 02212 02213 /* Get a pointer to the header */ 02214 rtpheader = (unsigned int *)data; 02215 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02216 rtpheader[1] = htonl(rtp->lastdigitts); 02217 rtpheader[2] = htonl(rtp->ssrc); 02218 02219 for (i = 0; i < 2; i++) { 02220 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02221 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02222 if (res < 0) 02223 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02224 ast_inet_ntoa(rtp->them.sin_addr), 02225 ntohs(rtp->them.sin_port), strerror(errno)); 02226 if (rtp_debug_test_addr(&rtp->them)) 02227 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02228 ast_inet_ntoa(rtp->them.sin_addr), 02229 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02230 /* Increment sequence number */ 02231 rtp->seqno++; 02232 /* Increment duration */ 02233 rtp->send_duration += 160; 02234 /* Clear marker bit and set seqno */ 02235 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02236 } 02237 02238 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02239 rtp->sending_digit = 1; 02240 rtp->send_digit = digit; 02241 rtp->send_payload = payload; 02242 02243 return 0; 02244 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2247 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().
02248 { 02249 unsigned int *rtpheader; 02250 int hdrlen = 12, res = 0; 02251 char data[256]; 02252 02253 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02254 return 0; 02255 02256 /* Setup packet to send */ 02257 rtpheader = (unsigned int *)data; 02258 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02259 rtpheader[1] = htonl(rtp->lastdigitts); 02260 rtpheader[2] = htonl(rtp->ssrc); 02261 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02262 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02263 02264 /* Transmit */ 02265 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02266 if (res < 0) 02267 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02268 ast_inet_ntoa(rtp->them.sin_addr), 02269 ntohs(rtp->them.sin_port), strerror(errno)); 02270 if (rtp_debug_test_addr(&rtp->them)) 02271 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02272 ast_inet_ntoa(rtp->them.sin_addr), 02273 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02274 02275 /* Increment sequence number */ 02276 rtp->seqno++; 02277 /* Increment duration */ 02278 rtp->send_duration += 160; 02279 02280 return 0; 02281 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2284 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().
02285 { 02286 unsigned int *rtpheader; 02287 int hdrlen = 12, res = 0, i = 0; 02288 char data[256]; 02289 02290 /* If no address, then bail out */ 02291 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02292 return 0; 02293 02294 if ((digit <= '9') && (digit >= '0')) 02295 digit -= '0'; 02296 else if (digit == '*') 02297 digit = 10; 02298 else if (digit == '#') 02299 digit = 11; 02300 else if ((digit >= 'A') && (digit <= 'D')) 02301 digit = digit - 'A' + 12; 02302 else if ((digit >= 'a') && (digit <= 'd')) 02303 digit = digit - 'a' + 12; 02304 else { 02305 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02306 return 0; 02307 } 02308 02309 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02310 02311 rtpheader = (unsigned int *)data; 02312 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02313 rtpheader[1] = htonl(rtp->lastdigitts); 02314 rtpheader[2] = htonl(rtp->ssrc); 02315 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02316 /* Set end bit */ 02317 rtpheader[3] |= htonl((1 << 23)); 02318 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02319 /* Send 3 termination packets */ 02320 for (i = 0; i < 3; i++) { 02321 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02322 if (res < 0) 02323 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02324 ast_inet_ntoa(rtp->them.sin_addr), 02325 ntohs(rtp->them.sin_port), strerror(errno)); 02326 if (rtp_debug_test_addr(&rtp->them)) 02327 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02328 ast_inet_ntoa(rtp->them.sin_addr), 02329 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02330 } 02331 rtp->sending_digit = 0; 02332 rtp->send_digit = 0; 02333 /* Increment lastdigitts */ 02334 rtp->lastdigitts += 960; 02335 rtp->seqno++; 02336 02337 return res; 02338 }
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 1639 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_is_answered(), gtalk_newcall(), and process_sdp().
01640 { 01641 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01642 return; /* bogus payload type */ 01643 01644 ast_mutex_lock(&rtp->bridge_lock); 01645 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01646 ast_mutex_unlock(&rtp->bridge_lock); 01647 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2006 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().
02007 { 02008 rtp->them.sin_port = them->sin_port; 02009 rtp->them.sin_addr = them->sin_addr; 02010 if (rtp->rtcp) { 02011 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02012 rtp->rtcp->them.sin_addr = them->sin_addr; 02013 } 02014 rtp->rxseqno = 0; 02015 }
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 1666 of file rtp.c.
References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, subtype, and type.
Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), process_sdp(), and set_dtmf_payload().
01669 { 01670 unsigned int i; 01671 int found = 0; 01672 01673 if (pt < 0 || pt > MAX_RTP_PT) 01674 return -1; /* bogus payload type */ 01675 01676 ast_mutex_lock(&rtp->bridge_lock); 01677 01678 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01679 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01680 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01681 found = 1; 01682 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01683 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01684 mimeTypes[i].payloadType.isAstFormat && 01685 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01686 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01687 break; 01688 } 01689 } 01690 01691 ast_mutex_unlock(&rtp->bridge_lock); 01692 01693 return (found ? 0 : -1); 01694 }
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 1991 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
01992 { 01993 int res; 01994 01995 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 01996 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 01997 return res; 01998 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2046 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().
02047 { 02048 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02049 02050 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02051 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02052 if (rtp->rtcp) { 02053 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02054 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02055 } 02056 02057 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02058 }
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 1651 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().
01652 { 01653 if (pt < 0 || pt > MAX_RTP_PT) 01654 return; /* bogus payload type */ 01655 01656 ast_mutex_lock(&rtp->bridge_lock); 01657 rtp->current_RTP_PT[pt].isAstFormat = 0; 01658 rtp->current_RTP_PT[pt].code = 0; 01659 ast_mutex_unlock(&rtp->bridge_lock); 01660 }
Definition at line 2734 of file rtp.c.
References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_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().
02735 { 02736 struct ast_frame *f; 02737 int codec; 02738 int hdrlen = 12; 02739 int subclass; 02740 02741 02742 /* If we have no peer, return immediately */ 02743 if (!rtp->them.sin_addr.s_addr) 02744 return 0; 02745 02746 /* If there is no data length, return immediately */ 02747 if (!_f->datalen) 02748 return 0; 02749 02750 /* Make sure we have enough space for RTP header */ 02751 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02752 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02753 return -1; 02754 } 02755 02756 subclass = _f->subclass; 02757 if (_f->frametype == AST_FRAME_VIDEO) 02758 subclass &= ~0x1; 02759 02760 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02761 if (codec < 0) { 02762 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02763 return -1; 02764 } 02765 02766 if (rtp->lasttxformat != subclass) { 02767 /* New format, reset the smoother */ 02768 if (option_debug) 02769 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02770 rtp->lasttxformat = subclass; 02771 if (rtp->smoother) 02772 ast_smoother_free(rtp->smoother); 02773 rtp->smoother = NULL; 02774 } 02775 02776 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 02777 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02778 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02779 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02780 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)); 02781 return -1; 02782 } 02783 if (fmt.flags) 02784 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02785 if (option_debug) 02786 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)); 02787 } 02788 } 02789 if (rtp->smoother) { 02790 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02791 ast_smoother_feed_be(rtp->smoother, _f); 02792 } else { 02793 ast_smoother_feed(rtp->smoother, _f); 02794 } 02795 02796 while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { 02797 if (f->subclass == AST_FORMAT_G722) { 02798 /* G.722 is silllllllllllllly */ 02799 f->samples /= 2; 02800 } 02801 02802 ast_rtp_raw_write(rtp, f, codec); 02803 } 02804 } else { 02805 /* Don't buffer outgoing frames; send them one-per-packet: */ 02806 if (_f->offset < hdrlen) { 02807 f = ast_frdup(_f); 02808 } else { 02809 f = _f; 02810 } 02811 if (f->data) { 02812 if (f->subclass == AST_FORMAT_G722) { 02813 /* G.722 is silllllllllllllly */ 02814 f->samples /= 2; 02815 } 02816 ast_rtp_raw_write(rtp, f, codec); 02817 } 02818 if (f != _f) 02819 ast_frfree(f); 02820 } 02821 02822 return 0; 02823 }
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 2853 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().
02854 { 02855 struct ast_frame *fr = NULL; 02856 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02857 int oldcodec0 = codec0, oldcodec1 = codec1; 02858 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02859 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02860 02861 /* Set it up so audio goes directly between the two endpoints */ 02862 02863 /* Test the first channel */ 02864 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02865 ast_rtp_get_peer(p1, &ac1); 02866 if (vp1) 02867 ast_rtp_get_peer(vp1, &vac1); 02868 } else 02869 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 02870 02871 /* Test the second channel */ 02872 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 02873 ast_rtp_get_peer(p0, &ac0); 02874 if (vp0) 02875 ast_rtp_get_peer(vp0, &vac0); 02876 } else 02877 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 02878 02879 /* Now we can unlock and move into our loop */ 02880 ast_channel_unlock(c0); 02881 ast_channel_unlock(c1); 02882 02883 /* Throw our channels into the structure and enter the loop */ 02884 cs[0] = c0; 02885 cs[1] = c1; 02886 cs[2] = NULL; 02887 for (;;) { 02888 /* Check if anything changed */ 02889 if ((c0->tech_pvt != pvt0) || 02890 (c1->tech_pvt != pvt1) || 02891 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 02892 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 02893 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 02894 if (c0->tech_pvt == pvt0) 02895 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02896 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02897 if (c1->tech_pvt == pvt1) 02898 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02899 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02900 return AST_BRIDGE_RETRY; 02901 } 02902 02903 /* Check if they have changed their address */ 02904 ast_rtp_get_peer(p1, &t1); 02905 if (vp1) 02906 ast_rtp_get_peer(vp1, &vt1); 02907 if (pr1->get_codec) 02908 codec1 = pr1->get_codec(c1); 02909 ast_rtp_get_peer(p0, &t0); 02910 if (vp0) 02911 ast_rtp_get_peer(vp0, &vt0); 02912 if (pr0->get_codec) 02913 codec0 = pr0->get_codec(c0); 02914 if ((inaddrcmp(&t1, &ac1)) || 02915 (vp1 && inaddrcmp(&vt1, &vac1)) || 02916 (codec1 != oldcodec1)) { 02917 if (option_debug > 1) { 02918 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02919 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 02920 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 02921 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 02922 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02923 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 02924 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02925 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 02926 } 02927 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))) 02928 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 02929 memcpy(&ac1, &t1, sizeof(ac1)); 02930 memcpy(&vac1, &vt1, sizeof(vac1)); 02931 oldcodec1 = codec1; 02932 } 02933 if ((inaddrcmp(&t0, &ac0)) || 02934 (vp0 && inaddrcmp(&vt0, &vac0))) { 02935 if (option_debug > 1) { 02936 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02937 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 02938 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02939 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 02940 } 02941 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))) 02942 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 02943 memcpy(&ac0, &t0, sizeof(ac0)); 02944 memcpy(&vac0, &vt0, sizeof(vac0)); 02945 oldcodec0 = codec0; 02946 } 02947 02948 /* Wait for frame to come in on the channels */ 02949 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 02950 if (!timeoutms) { 02951 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02952 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02953 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02954 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02955 return AST_BRIDGE_RETRY; 02956 } 02957 if (option_debug) 02958 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 02959 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 02960 break; 02961 continue; 02962 } 02963 fr = ast_read(who); 02964 other = (who == c0) ? c1 : c0; 02965 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 02966 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 02967 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 02968 /* Break out of bridge */ 02969 *fo = fr; 02970 *rc = who; 02971 if (option_debug) 02972 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 02973 if (c0->tech_pvt == pvt0) 02974 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02975 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02976 if (c1->tech_pvt == pvt1) 02977 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02978 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02979 return AST_BRIDGE_COMPLETE; 02980 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02981 if ((fr->subclass == AST_CONTROL_HOLD) || 02982 (fr->subclass == AST_CONTROL_UNHOLD) || 02983 (fr->subclass == AST_CONTROL_VIDUPDATE) || 02984 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 02985 if (fr->subclass == AST_CONTROL_HOLD) { 02986 /* If we someone went on hold we want the other side to reinvite back to us */ 02987 if (who == c0) 02988 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 02989 else 02990 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 02991 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 02992 /* If they went off hold they should go back to being direct */ 02993 if (who == c0) 02994 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 02995 else 02996 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 02997 } 02998 /* Update local address information */ 02999 ast_rtp_get_peer(p0, &t0); 03000 memcpy(&ac0, &t0, sizeof(ac0)); 03001 ast_rtp_get_peer(p1, &t1); 03002 memcpy(&ac1, &t1, sizeof(ac1)); 03003 /* Update codec information */ 03004 if (pr0->get_codec && c0->tech_pvt) 03005 oldcodec0 = codec0 = pr0->get_codec(c0); 03006 if (pr1->get_codec && c1->tech_pvt) 03007 oldcodec1 = codec1 = pr1->get_codec(c1); 03008 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03009 ast_frfree(fr); 03010 } else { 03011 *fo = fr; 03012 *rc = who; 03013 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03014 return AST_BRIDGE_COMPLETE; 03015 } 03016 } else { 03017 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03018 (fr->frametype == AST_FRAME_DTMF_END) || 03019 (fr->frametype == AST_FRAME_VOICE) || 03020 (fr->frametype == AST_FRAME_VIDEO) || 03021 (fr->frametype == AST_FRAME_IMAGE) || 03022 (fr->frametype == AST_FRAME_HTML) || 03023 (fr->frametype == AST_FRAME_MODEM) || 03024 (fr->frametype == AST_FRAME_TEXT)) { 03025 ast_write(other, fr); 03026 } 03027 ast_frfree(fr); 03028 } 03029 /* Swap priority */ 03030 cs[2] = cs[0]; 03031 cs[0] = cs[1]; 03032 cs[1] = cs[2]; 03033 } 03034 03035 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03036 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03037 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03038 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03039 03040 return AST_BRIDGE_FAILED; 03041 }
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 3139 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().
03140 { 03141 struct ast_frame *fr = NULL; 03142 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03143 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03144 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03145 int p0_callback = 0, p1_callback = 0; 03146 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03147 03148 /* Okay, setup each RTP structure to do P2P forwarding */ 03149 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03150 p2p_set_bridge(p0, p1); 03151 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03152 p2p_set_bridge(p1, p0); 03153 03154 /* Activate callback modes if possible */ 03155 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03156 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03157 03158 /* Now let go of the channel locks and be on our way */ 03159 ast_channel_unlock(c0); 03160 ast_channel_unlock(c1); 03161 03162 /* Go into a loop forwarding frames until we don't need to anymore */ 03163 cs[0] = c0; 03164 cs[1] = c1; 03165 cs[2] = NULL; 03166 for (;;) { 03167 /* If the underlying formats have changed force this bridge to break */ 03168 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 03169 ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n"); 03170 res = AST_BRIDGE_FAILED_NOWARN; 03171 break; 03172 } 03173 /* Check if anything changed */ 03174 if ((c0->tech_pvt != pvt0) || 03175 (c1->tech_pvt != pvt1) || 03176 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03177 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03178 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03179 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03180 ast_frfree(fr); 03181 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03182 ast_frfree(fr); 03183 res = AST_BRIDGE_RETRY; 03184 break; 03185 } 03186 /* Wait on a channel to feed us a frame */ 03187 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03188 if (!timeoutms) { 03189 res = AST_BRIDGE_RETRY; 03190 break; 03191 } 03192 if (option_debug) 03193 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03194 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03195 break; 03196 continue; 03197 } 03198 /* Read in frame from channel */ 03199 fr = ast_read(who); 03200 other = (who == c0) ? c1 : c0; 03201 /* Dependong on the frame we may need to break out of our bridge */ 03202 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03203 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03204 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03205 /* Record received frame and who */ 03206 *fo = fr; 03207 *rc = who; 03208 if (option_debug) 03209 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03210 res = AST_BRIDGE_COMPLETE; 03211 break; 03212 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03213 if ((fr->subclass == AST_CONTROL_HOLD) || 03214 (fr->subclass == AST_CONTROL_UNHOLD) || 03215 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03216 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03217 /* If we are going on hold, then break callback mode and P2P bridging */ 03218 if (fr->subclass == AST_CONTROL_HOLD) { 03219 if (p0_callback) 03220 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03221 if (p1_callback) 03222 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03223 p2p_set_bridge(p0, NULL); 03224 p2p_set_bridge(p1, NULL); 03225 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03226 /* If we are off hold, then go back to callback mode and P2P bridging */ 03227 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03228 p2p_set_bridge(p0, p1); 03229 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03230 p2p_set_bridge(p1, p0); 03231 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03232 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03233 } 03234 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03235 ast_frfree(fr); 03236 } else { 03237 *fo = fr; 03238 *rc = who; 03239 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03240 res = AST_BRIDGE_COMPLETE; 03241 break; 03242 } 03243 } else { 03244 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03245 (fr->frametype == AST_FRAME_DTMF_END) || 03246 (fr->frametype == AST_FRAME_VOICE) || 03247 (fr->frametype == AST_FRAME_VIDEO) || 03248 (fr->frametype == AST_FRAME_IMAGE) || 03249 (fr->frametype == AST_FRAME_HTML) || 03250 (fr->frametype == AST_FRAME_MODEM) || 03251 (fr->frametype == AST_FRAME_TEXT)) { 03252 ast_write(other, fr); 03253 } 03254 03255 ast_frfree(fr); 03256 } 03257 /* Swap priority */ 03258 cs[2] = cs[0]; 03259 cs[0] = cs[1]; 03260 cs[1] = cs[2]; 03261 } 03262 03263 /* If we are totally avoiding the core, then restore our link to it */ 03264 if (p0_callback) 03265 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03266 if (p1_callback) 03267 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03268 03269 /* Break out of the direct bridge */ 03270 p2p_set_bridge(p0, NULL); 03271 p2p_set_bridge(p1, NULL); 03272 03273 return res; 03274 }
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 1052 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().
01053 { 01054 int res = 0, payload = 0, bridged_payload = 0, mark; 01055 struct rtpPayloadType rtpPT; 01056 int reconstruct = ntohl(rtpheader[0]); 01057 01058 /* Get fields from packet */ 01059 payload = (reconstruct & 0x7f0000) >> 16; 01060 mark = (((reconstruct & 0x800000) >> 23) != 0); 01061 01062 /* Check what the payload value should be */ 01063 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01064 01065 /* 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 */ 01066 if (!bridged->current_RTP_PT[payload].code) 01067 return -1; 01068 01069 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01070 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01071 return -1; 01072 01073 /* Otherwise adjust bridged payload to match */ 01074 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01075 01076 /* If the mark bit has not been sent yet... do it now */ 01077 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01078 mark = 1; 01079 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01080 } 01081 01082 /* Reconstruct part of the packet */ 01083 reconstruct &= 0xFF80FFFF; 01084 reconstruct |= (bridged_payload << 16); 01085 reconstruct |= (mark << 23); 01086 rtpheader[0] = htonl(reconstruct); 01087 01088 /* Send the packet back out */ 01089 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01090 if (res < 0) { 01091 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01092 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)); 01093 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01094 if (option_debug || rtpdebug) 01095 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)); 01096 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01097 } 01098 return 0; 01099 } else if (rtp_debug_test_addr(&bridged->them)) 01100 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); 01101 01102 return 0; 01103 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1003 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().
01004 { 01005 struct timeval now; 01006 double transit; 01007 double current_time; 01008 double d; 01009 double dtv; 01010 double prog; 01011 01012 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01013 gettimeofday(&rtp->rxcore, NULL); 01014 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01015 /* map timestamp to a real time */ 01016 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01017 rtp->rxcore.tv_sec -= timestamp / 8000; 01018 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01019 /* Round to 0.1ms for nice, pretty timestamps */ 01020 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01021 if (rtp->rxcore.tv_usec < 0) { 01022 /* Adjust appropriately if necessary */ 01023 rtp->rxcore.tv_usec += 1000000; 01024 rtp->rxcore.tv_sec -= 1; 01025 } 01026 } 01027 01028 gettimeofday(&now,NULL); 01029 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01030 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01031 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01032 if (tv->tv_usec >= 1000000) { 01033 tv->tv_usec -= 1000000; 01034 tv->tv_sec += 1; 01035 } 01036 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01037 dtv = (double)rtp->drxcore + (double)(prog); 01038 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01039 transit = current_time - dtv; 01040 d = transit - rtp->rxtransit; 01041 rtp->rxtransit = transit; 01042 if (d<0) 01043 d=-d; 01044 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01045 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01046 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01047 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01048 rtp->rtcp->minrxjitter = rtp->rxjitter; 01049 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2163 of file rtp.c.
References t, and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02164 { 02165 struct timeval t; 02166 long ms; 02167 if (ast_tvzero(rtp->txcore)) { 02168 rtp->txcore = ast_tvnow(); 02169 /* Round to 20ms for nice, pretty timestamps */ 02170 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02171 } 02172 /* Use previous txcore if available */ 02173 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02174 ms = ast_tvdiff_ms(t, rtp->txcore); 02175 if (ms < 0) 02176 ms = 0; 02177 /* Use what we just got for next time */ 02178 rtp->txcore = t; 02179 return (unsigned int) ms; 02180 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 1462 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().
01463 { 01464 struct ast_rtp_protocol *cur = NULL; 01465 01466 AST_LIST_LOCK(&protos); 01467 AST_LIST_TRAVERSE(&protos, cur, list) { 01468 if (cur->type == chan->tech->type) 01469 break; 01470 } 01471 AST_LIST_UNLOCK(&protos); 01472 01473 return cur; 01474 }
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 3110 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.
03111 { 03112 ast_channel_lock(chan); 03113 03114 /* Remove the callback from the IO context */ 03115 ast_io_remove(rtp->io, iod[0]); 03116 03117 /* Restore file descriptors */ 03118 chan->fds[0] = fds[0]; 03119 ast_channel_unlock(chan); 03120 03121 /* Restore callback mode if previously used */ 03122 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03123 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03124 03125 return 0; 03126 }
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 3129 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03130 { 03131 ast_mutex_lock(&rtp0->bridge_lock); 03132 rtp0->bridged = rtp1; 03133 ast_mutex_unlock(&rtp0->bridge_lock); 03134 03135 return; 03136 }
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 3549 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip().
03549 { 03550 if (argc != 2) { 03551 if (argc != 4) 03552 return RESULT_SHOWUSAGE; 03553 return rtcp_do_debug_ip(fd, argc, argv); 03554 } 03555 rtcpdebug = 1; 03556 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03557 ast_cli(fd, "RTCP Debugging Enabled\n"); 03558 return RESULT_SUCCESS; 03559 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3537 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip_deprecated().
03537 { 03538 if (argc != 3) { 03539 if (argc != 5) 03540 return RESULT_SHOWUSAGE; 03541 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03542 } 03543 rtcpdebug = 1; 03544 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03545 ast_cli(fd, "RTCP Debugging Enabled\n"); 03546 return RESULT_SUCCESS; 03547 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3494 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtcp_do_debug().
03495 { 03496 struct hostent *hp; 03497 struct ast_hostent ahp; 03498 int port = 0; 03499 char *p, *arg; 03500 if (argc != 4) 03501 return RESULT_SHOWUSAGE; 03502 03503 arg = argv[3]; 03504 p = strstr(arg, ":"); 03505 if (p) { 03506 *p = '\0'; 03507 p++; 03508 port = atoi(p); 03509 } 03510 hp = ast_gethostbyname(arg, &ahp); 03511 if (hp == NULL) 03512 return RESULT_SHOWUSAGE; 03513 rtcpdebugaddr.sin_family = AF_INET; 03514 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03515 rtcpdebugaddr.sin_port = htons(port); 03516 if (port == 0) 03517 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03518 else 03519 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03520 rtcpdebug = 1; 03521 return RESULT_SUCCESS; 03522 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3464 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().
03465 { 03466 struct hostent *hp; 03467 struct ast_hostent ahp; 03468 int port = 0; 03469 char *p, *arg; 03470 if (argc != 5) 03471 return RESULT_SHOWUSAGE; 03472 03473 arg = argv[4]; 03474 p = strstr(arg, ":"); 03475 if (p) { 03476 *p = '\0'; 03477 p++; 03478 port = atoi(p); 03479 } 03480 hp = ast_gethostbyname(arg, &ahp); 03481 if (hp == NULL) 03482 return RESULT_SHOWUSAGE; 03483 rtcpdebugaddr.sin_family = AF_INET; 03484 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03485 rtcpdebugaddr.sin_port = htons(port); 03486 if (port == 0) 03487 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03488 else 03489 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03490 rtcpdebug = 1; 03491 return RESULT_SUCCESS; 03492 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3570 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03570 { 03571 if (argc != 2) { 03572 return RESULT_SHOWUSAGE; 03573 } 03574 rtcpstats = 1; 03575 ast_cli(fd, "RTCP Stats Enabled\n"); 03576 return RESULT_SUCCESS; 03577 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3561 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03561 { 03562 if (argc != 3) { 03563 return RESULT_SHOWUSAGE; 03564 } 03565 rtcpstats = 1; 03566 ast_cli(fd, "RTCP Stats Enabled\n"); 03567 return RESULT_SUCCESS; 03568 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3597 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03598 { 03599 if (argc != 3) 03600 return RESULT_SHOWUSAGE; 03601 rtcpdebug = 0; 03602 ast_cli(fd,"RTCP Debugging Disabled\n"); 03603 return RESULT_SUCCESS; 03604 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3588 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03589 { 03590 if (argc != 4) 03591 return RESULT_SHOWUSAGE; 03592 rtcpdebug = 0; 03593 ast_cli(fd,"RTCP Debugging Disabled\n"); 03594 return RESULT_SUCCESS; 03595 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3615 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03616 { 03617 if (argc != 3) 03618 return RESULT_SHOWUSAGE; 03619 rtcpstats = 0; 03620 ast_cli(fd,"RTCP Stats Disabled\n"); 03621 return RESULT_SUCCESS; 03622 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3606 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03607 { 03608 if (argc != 4) 03609 return RESULT_SHOWUSAGE; 03610 rtcpstats = 0; 03611 ast_cli(fd,"RTCP Stats Disabled\n"); 03612 return RESULT_SUCCESS; 03613 }
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 3524 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtp_do_debug_ip().
03525 { 03526 if (argc != 2) { 03527 if (argc != 4) 03528 return RESULT_SHOWUSAGE; 03529 return rtp_do_debug_ip(fd, argc, argv); 03530 } 03531 rtpdebug = 1; 03532 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03533 ast_cli(fd, "RTP Debugging Enabled\n"); 03534 return RESULT_SUCCESS; 03535 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3434 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtp_do_debug().
03435 { 03436 struct hostent *hp; 03437 struct ast_hostent ahp; 03438 int port = 0; 03439 char *p, *arg; 03440 03441 if (argc != 4) 03442 return RESULT_SHOWUSAGE; 03443 arg = argv[3]; 03444 p = strstr(arg, ":"); 03445 if (p) { 03446 *p = '\0'; 03447 p++; 03448 port = atoi(p); 03449 } 03450 hp = ast_gethostbyname(arg, &ahp); 03451 if (hp == NULL) 03452 return RESULT_SHOWUSAGE; 03453 rtpdebugaddr.sin_family = AF_INET; 03454 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03455 rtpdebugaddr.sin_port = htons(port); 03456 if (port == 0) 03457 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03458 else 03459 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03460 rtpdebug = 1; 03461 return RESULT_SUCCESS; 03462 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3579 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03580 { 03581 if (argc != 3) 03582 return RESULT_SHOWUSAGE; 03583 rtpdebug = 0; 03584 ast_cli(fd,"RTP Debugging Disabled\n"); 03585 return RESULT_SUCCESS; 03586 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1838 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01839 { 01840 int s; 01841 long flags; 01842 s = socket(AF_INET, SOCK_DGRAM, 0); 01843 if (s > -1) { 01844 flags = fcntl(s, F_GETFL); 01845 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01846 #ifdef SO_NO_CHECK 01847 if (nochecksums) 01848 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01849 #endif 01850 } 01851 return s; 01852 }
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 3624 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03625 { 03626 if (argc != 2) { 03627 return RESULT_SHOWUSAGE; 03628 } 03629 stundebug = 1; 03630 ast_cli(fd, "STUN Debugging Enabled\n"); 03631 return RESULT_SUCCESS; 03632 }
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 3634 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03635 { 03636 if (argc != 3) 03637 return RESULT_SHOWUSAGE; 03638 stundebug = 0; 03639 ast_cli(fd, "STUN Debugging Disabled\n"); 03640 return RESULT_SUCCESS; 03641 }
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 1334 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 1368 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 1335 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(), iax2_show_threads(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), parse_information(), parse_setup(), schedule_delivery(), sla_load_config(), subscription_type2str(), and yyparse().