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