#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 | ast_rtcp |
Structure defining an RTCP session. More... | |
struct | ast_rtp |
RTP session description. More... | |
struct | protos |
List of current sessions. 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 |
struct | stun_trans_id |
Defines | |
#define | DEFAULT_DTMF_TIMEOUT (150 * (8000 / 1000)) |
#define | FLAG_3389_WARNING (1 << 0) |
#define | FLAG_CALLBACK_MODE (1 << 6) |
#define | FLAG_DTMF_COMPENSATE (1 << 7) |
#define | FLAG_HAS_DTMF (1 << 3) |
#define | FLAG_HAS_STUN (1 << 8) |
#define | FLAG_NAT_ACTIVE (3 << 1) |
#define | FLAG_NAT_INACTIVE (0 << 1) |
#define | FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
#define | FLAG_P2P_NEED_DTMF (1 << 5) |
#define | FLAG_P2P_SENT_MARK (1 << 4) |
#define | MAX_TIMESTAMP_SKEW 640 |
#define | RTCP_DEFAULT_INTERVALMS 5000 |
#define | RTCP_MAX_INTERVALMS 60000 |
#define | RTCP_MIN_INTERVALMS 500 |
#define | RTCP_PT_APP 204 |
#define | RTCP_PT_BYE 203 |
#define | RTCP_PT_FUR 192 |
#define | RTCP_PT_RR 201 |
#define | RTCP_PT_SDES 202 |
#define | RTCP_PT_SR 200 |
#define | RTP_MTU 1200 |
#define | RTP_SEQ_MOD (1<<16) |
#define | STUN_ACCEPT (1) |
#define | STUN_BINDERR 0x0111 |
#define | STUN_BINDREQ 0x0001 |
#define | STUN_BINDRESP 0x0101 |
#define | STUN_CHANGE_REQUEST 0x0003 |
#define | STUN_CHANGED_ADDRESS 0x0005 |
#define | STUN_ERROR_CODE 0x0009 |
#define | STUN_IGNORE (0) |
#define | STUN_MAPPED_ADDRESS 0x0001 |
#define | STUN_MESSAGE_INTEGRITY 0x0008 |
#define | STUN_PASSWORD 0x0007 |
#define | STUN_REFLECTED_FROM 0x000b |
#define | STUN_RESPONSE_ADDRESS 0x0002 |
#define | STUN_SECERR 0x0112 |
#define | STUN_SECREQ 0x0002 |
#define | STUN_SECRESP 0x0102 |
#define | STUN_SOURCE_ADDRESS 0x0004 |
#define | STUN_UNKNOWN_ATTRIBUTES 0x000a |
#define | STUN_USERNAME 0x0006 |
Functions | |
static void | append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left) |
static void | append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left) |
static unsigned int | ast_rtcp_calc_interval (struct ast_rtp *rtp) |
int | ast_rtcp_fd (struct ast_rtp *rtp) |
static struct ast_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_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt) |
set potential alternate source for RTP media | |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_set_constantssrc (struct ast_rtp *rtp) |
When changing sources, don't generate a new SSRC. | |
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_get_rate (int subclass) |
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 void | sanitize_tv (struct timeval *tv) |
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 [] |
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 (150 * (8000 / 1000)) |
#define FLAG_3389_WARNING (1 << 0) |
#define FLAG_CALLBACK_MODE (1 << 6) |
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 197 of file rtp.c.
Referenced by ast_rtp_setdtmfcompensate(), process_rfc2833(), and send_dtmf().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 193 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 190 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 191 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 192 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 194 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 265 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 277 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 370 of file rtp.c.
References stun_addr::addr.
Referenced by stun_handle_packet().
00371 { 00372 int size = sizeof(**attr) + 8; 00373 struct stun_addr *addr; 00374 if (*left > size) { 00375 (*attr)->attr = htons(attrval); 00376 (*attr)->len = htons(8); 00377 addr = (struct stun_addr *)((*attr)->value); 00378 addr->unused = 0; 00379 addr->family = 0x01; 00380 addr->port = sin->sin_port; 00381 addr->addr = sin->sin_addr.s_addr; 00382 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00383 *len += size; 00384 *left -= size; 00385 } 00386 }
static void append_attr_string | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
const char * | s, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 357 of file rtp.c.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00358 { 00359 int size = sizeof(**attr) + strlen(s); 00360 if (*left > size) { 00361 (*attr)->attr = htons(attrval); 00362 (*attr)->len = htons(strlen(s)); 00363 memcpy((*attr)->value, s, strlen(s)); 00364 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00365 *len += size; 00366 *left -= size; 00367 } 00368 }
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 533 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00534 { 00535 unsigned int interval; 00536 /*! \todo XXX Do a more reasonable calculation on this one 00537 * Look in RFC 3550 Section A.7 for an example*/ 00538 interval = rtcpinterval; 00539 return interval; 00540 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 521 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 1928 of file rtp.c.
References ast_calloc, ast_log(), errno, free, LOG_DEBUG, LOG_WARNING, option_debug, rtp_socket(), and ast_rtcp::s.
Referenced by ast_rtp_new_with_bindaddr().
01929 { 01930 struct ast_rtcp *rtcp; 01931 01932 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01933 return NULL; 01934 rtcp->s = rtp_socket(); 01935 if (option_debug > 3) 01936 ast_log(LOG_DEBUG, "socket RTPaux (RTCP) fd: %i\n", rtcp->s); 01937 rtcp->us.sin_family = AF_INET; 01938 rtcp->them.sin_family = AF_INET; 01939 rtcp->schedid = -1; 01940 01941 if (rtcp->s < 0) { 01942 free(rtcp); 01943 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01944 return NULL; 01945 } 01946 01947 return rtcp; 01948 }
Definition at line 869 of file rtp.c.
References ast_rtcp::accumulated_transit, ast_rtcp::altthem, 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().
00870 { 00871 socklen_t len; 00872 int position, i, packetwords; 00873 int res; 00874 struct sockaddr_in sin; 00875 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00876 unsigned int *rtcpheader; 00877 int pt; 00878 struct timeval now; 00879 unsigned int length; 00880 int rc; 00881 double rttsec; 00882 uint64_t rtt = 0; 00883 unsigned int dlsr; 00884 unsigned int lsr; 00885 unsigned int msw; 00886 unsigned int lsw; 00887 unsigned int comp; 00888 struct ast_frame *f = &ast_null_frame; 00889 00890 if (!rtp || !rtp->rtcp) 00891 return &ast_null_frame; 00892 00893 len = sizeof(sin); 00894 00895 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00896 0, (struct sockaddr *)&sin, &len); 00897 if (option_debug > 2) 00898 ast_log(LOG_DEBUG, "socket RTCP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 00899 00900 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00901 00902 if (res < 0) { 00903 ast_assert(errno != EBADF); 00904 if (errno != EAGAIN) { 00905 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00906 ast_log(LOG_WARNING, "socket RTCP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 00907 return NULL; 00908 } 00909 return &ast_null_frame; 00910 } 00911 00912 packetwords = res / 4; 00913 00914 if (rtp->nat) { 00915 /* Send to whoever sent to us */ 00916 if (((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00917 (rtp->rtcp->them.sin_port != sin.sin_port)) && 00918 ((rtp->rtcp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) || 00919 (rtp->rtcp->altthem.sin_port != sin.sin_port))) { 00920 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00921 if (option_debug || rtpdebug) 00922 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)); 00923 } 00924 } 00925 00926 if (option_debug) 00927 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00928 00929 /* Process a compound packet */ 00930 position = 0; 00931 while (position < packetwords) { 00932 i = position; 00933 length = ntohl(rtcpheader[i]); 00934 pt = (length & 0xff0000) >> 16; 00935 rc = (length & 0x1f000000) >> 24; 00936 length &= 0xffff; 00937 00938 if ((i + length) > packetwords) { 00939 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00940 return &ast_null_frame; 00941 } 00942 00943 if (rtcp_debug_test_addr(&sin)) { 00944 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00945 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00946 ast_verbose("Reception reports: %d\n", rc); 00947 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00948 } 00949 00950 i += 2; /* Advance past header and ssrc */ 00951 00952 switch (pt) { 00953 case RTCP_PT_SR: 00954 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00955 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00956 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00957 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00958 00959 if (rtcp_debug_test_addr(&sin)) { 00960 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00961 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00962 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00963 } 00964 i += 5; 00965 if (rc < 1) 00966 break; 00967 /* Intentional fall through */ 00968 case RTCP_PT_RR: 00969 /* Don't handle multiple reception reports (rc > 1) yet */ 00970 /* Calculate RTT per RFC */ 00971 gettimeofday(&now, NULL); 00972 timeval2ntp(now, &msw, &lsw); 00973 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00974 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00975 lsr = ntohl(rtcpheader[i + 4]); 00976 dlsr = ntohl(rtcpheader[i + 5]); 00977 rtt = comp - lsr - dlsr; 00978 00979 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00980 sess->ee_delay = (eedelay * 1000) / 65536; */ 00981 if (rtt < 4294) { 00982 rtt = (rtt * 1000000) >> 16; 00983 } else { 00984 rtt = (rtt * 1000) >> 16; 00985 rtt *= 1000; 00986 } 00987 rtt = rtt / 1000.; 00988 rttsec = rtt / 1000.; 00989 00990 if (comp - dlsr >= lsr) { 00991 rtp->rtcp->accumulated_transit += rttsec; 00992 rtp->rtcp->rtt = rttsec; 00993 if (rtp->rtcp->maxrtt<rttsec) 00994 rtp->rtcp->maxrtt = rttsec; 00995 if (rtp->rtcp->minrtt>rttsec) 00996 rtp->rtcp->minrtt = rttsec; 00997 } else if (rtcp_debug_test_addr(&sin)) { 00998 ast_verbose("Internal RTCP NTP clock skew detected: " 00999 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 01000 "diff=%d\n", 01001 lsr, comp, dlsr, dlsr / 65536, 01002 (dlsr % 65536) * 1000 / 65536, 01003 dlsr - (comp - lsr)); 01004 } 01005 } 01006 01007 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 01008 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 01009 if (rtcp_debug_test_addr(&sin)) { 01010 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 01011 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 01012 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 01013 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 01014 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 01015 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 01016 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 01017 if (rtt) 01018 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 01019 } 01020 break; 01021 case RTCP_PT_FUR: 01022 if (rtcp_debug_test_addr(&sin)) 01023 ast_verbose("Received an RTCP Fast Update Request\n"); 01024 rtp->f.frametype = AST_FRAME_CONTROL; 01025 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 01026 rtp->f.datalen = 0; 01027 rtp->f.samples = 0; 01028 rtp->f.mallocd = 0; 01029 rtp->f.src = "RTP"; 01030 f = &rtp->f; 01031 break; 01032 case RTCP_PT_SDES: 01033 if (rtcp_debug_test_addr(&sin)) 01034 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01035 break; 01036 case RTCP_PT_BYE: 01037 if (rtcp_debug_test_addr(&sin)) 01038 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01039 break; 01040 default: 01041 if (option_debug) 01042 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)); 01043 break; 01044 } 01045 position += (length + 1); 01046 } 01047 01048 return f; 01049 }
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 2438 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02439 { 02440 struct ast_rtp *rtp = data; 02441 int res; 02442 02443 rtp->rtcp->sendfur = 1; 02444 res = ast_rtcp_write(data); 02445 02446 return res; 02447 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2655 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().
02656 { 02657 struct ast_rtp *rtp = (struct ast_rtp *)data; 02658 int res; 02659 02660 if (!rtp || !rtp->rtcp) 02661 return 0; 02662 02663 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02664 res = ast_rtcp_write_sr(data); 02665 else 02666 res = ast_rtcp_write_rr(data); 02667 02668 return res; 02669 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recepient's report.
Definition at line 2560 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().
02561 { 02562 struct ast_rtp *rtp = (struct ast_rtp *)data; 02563 int res; 02564 int len = 32; 02565 unsigned int lost; 02566 unsigned int extended; 02567 unsigned int expected; 02568 unsigned int expected_interval; 02569 unsigned int received_interval; 02570 int lost_interval; 02571 struct timeval now; 02572 unsigned int *rtcpheader; 02573 char bdata[1024]; 02574 struct timeval dlsr; 02575 int fraction; 02576 02577 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02578 return 0; 02579 02580 if (!rtp->rtcp->them.sin_addr.s_addr) { 02581 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02582 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02583 return 0; 02584 } 02585 02586 extended = rtp->cycles + rtp->lastrxseqno; 02587 expected = extended - rtp->seedrxseqno + 1; 02588 lost = expected - rtp->rxcount; 02589 expected_interval = expected - rtp->rtcp->expected_prior; 02590 rtp->rtcp->expected_prior = expected; 02591 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02592 rtp->rtcp->received_prior = rtp->rxcount; 02593 lost_interval = expected_interval - received_interval; 02594 if (expected_interval == 0 || lost_interval <= 0) 02595 fraction = 0; 02596 else 02597 fraction = (lost_interval << 8) / expected_interval; 02598 gettimeofday(&now, NULL); 02599 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02600 rtcpheader = (unsigned int *)bdata; 02601 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02602 rtcpheader[1] = htonl(rtp->ssrc); 02603 rtcpheader[2] = htonl(rtp->themssrc); 02604 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02605 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02606 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02607 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02608 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02609 02610 if (rtp->rtcp->sendfur) { 02611 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02612 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02613 len += 8; 02614 rtp->rtcp->sendfur = 0; 02615 } 02616 02617 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02618 it can change mid call, and SDES can't) */ 02619 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02620 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02621 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02622 len += 12; 02623 02624 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02625 02626 if (res < 0) { 02627 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02628 /* Remove the scheduler */ 02629 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02630 return 0; 02631 } 02632 02633 rtp->rtcp->rr_count++; 02634 02635 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02636 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02637 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02638 " IA jitter: %.4f\n" 02639 " Their last SR: %u\n" 02640 " DLSR: %4.4f (sec)\n\n", 02641 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02642 ntohs(rtp->rtcp->them.sin_port), 02643 rtp->ssrc, rtp->themssrc, fraction, lost, 02644 rtp->rxjitter, 02645 rtp->rtcp->themrxlsr, 02646 (double)(ntohl(rtcpheader[7])/65536.0)); 02647 } 02648 02649 return res; 02650 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2450 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().
02451 { 02452 struct ast_rtp *rtp = (struct ast_rtp *)data; 02453 int res; 02454 int len = 0; 02455 struct timeval now; 02456 unsigned int now_lsw; 02457 unsigned int now_msw; 02458 unsigned int *rtcpheader; 02459 unsigned int lost; 02460 unsigned int extended; 02461 unsigned int expected; 02462 unsigned int expected_interval; 02463 unsigned int received_interval; 02464 int lost_interval; 02465 int fraction; 02466 struct timeval dlsr; 02467 char bdata[512]; 02468 02469 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02470 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02471 return 0; 02472 02473 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02474 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02475 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02476 return 0; 02477 } 02478 02479 gettimeofday(&now, NULL); 02480 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02481 rtcpheader = (unsigned int *)bdata; 02482 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02483 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02484 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02485 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02486 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02487 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02488 len += 28; 02489 02490 extended = rtp->cycles + rtp->lastrxseqno; 02491 expected = extended - rtp->seedrxseqno + 1; 02492 if (rtp->rxcount > expected) 02493 expected += rtp->rxcount - expected; 02494 lost = expected - rtp->rxcount; 02495 expected_interval = expected - rtp->rtcp->expected_prior; 02496 rtp->rtcp->expected_prior = expected; 02497 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02498 rtp->rtcp->received_prior = rtp->rxcount; 02499 lost_interval = expected_interval - received_interval; 02500 if (expected_interval == 0 || lost_interval <= 0) 02501 fraction = 0; 02502 else 02503 fraction = (lost_interval << 8) / expected_interval; 02504 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02505 rtcpheader[7] = htonl(rtp->themssrc); 02506 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02507 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02508 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02509 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02510 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02511 len += 24; 02512 02513 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02514 02515 if (rtp->rtcp->sendfur) { 02516 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02517 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02518 len += 8; 02519 rtp->rtcp->sendfur = 0; 02520 } 02521 02522 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02523 /* it can change mid call, and SDES can't) */ 02524 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02525 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02526 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02527 len += 12; 02528 02529 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02530 if (res < 0) { 02531 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)); 02532 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02533 return 0; 02534 } 02535 02536 /* FIXME Don't need to get a new one */ 02537 gettimeofday(&rtp->rtcp->txlsr, NULL); 02538 rtp->rtcp->sr_count++; 02539 02540 rtp->rtcp->lastsrtxcount = rtp->txcount; 02541 02542 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02543 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02544 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02545 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02546 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02547 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02548 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02549 ast_verbose(" Report block:\n"); 02550 ast_verbose(" Fraction lost: %u\n", fraction); 02551 ast_verbose(" Cumulative loss: %u\n", lost); 02552 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02553 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02554 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02555 } 02556 return res; 02557 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 401 of file rtp.c.
Referenced by process_sdp().
00402 { 00403 return sizeof(struct ast_rtp); 00404 }
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 3414 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, ast_channel::name, 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.
03415 { 03416 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03417 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03418 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03419 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03420 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03421 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03422 int codec0 = 0, codec1 = 0; 03423 void *pvt0 = NULL, *pvt1 = NULL; 03424 03425 /* Lock channels */ 03426 ast_channel_lock(c0); 03427 while(ast_channel_trylock(c1)) { 03428 ast_channel_unlock(c0); 03429 usleep(1); 03430 ast_channel_lock(c0); 03431 } 03432 03433 /* Ensure neither channel got hungup during lock avoidance */ 03434 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03435 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03436 ast_channel_unlock(c0); 03437 ast_channel_unlock(c1); 03438 return AST_BRIDGE_FAILED; 03439 } 03440 03441 /* Find channel driver interfaces */ 03442 if (!(pr0 = get_proto(c0))) { 03443 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03444 ast_channel_unlock(c0); 03445 ast_channel_unlock(c1); 03446 return AST_BRIDGE_FAILED; 03447 } 03448 if (!(pr1 = get_proto(c1))) { 03449 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03450 ast_channel_unlock(c0); 03451 ast_channel_unlock(c1); 03452 return AST_BRIDGE_FAILED; 03453 } 03454 03455 /* Get channel specific interface structures */ 03456 pvt0 = c0->tech_pvt; 03457 pvt1 = c1->tech_pvt; 03458 03459 /* Get audio and video interface (if native bridge is possible) */ 03460 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03461 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03462 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03463 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03464 03465 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03466 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03467 audio_p0_res = AST_RTP_GET_FAILED; 03468 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03469 audio_p1_res = AST_RTP_GET_FAILED; 03470 03471 /* Check if a bridge is possible (partial/native) */ 03472 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03473 /* Somebody doesn't want to play... */ 03474 ast_channel_unlock(c0); 03475 ast_channel_unlock(c1); 03476 return AST_BRIDGE_FAILED_NOWARN; 03477 } 03478 03479 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03480 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03481 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03482 audio_p0_res = AST_RTP_TRY_PARTIAL; 03483 } 03484 03485 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03486 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03487 audio_p1_res = AST_RTP_TRY_PARTIAL; 03488 } 03489 03490 /* If both sides are not using the same method of DTMF transmission 03491 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03492 * -------------------------------------------------- 03493 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03494 * |-----------|------------|-----------------------| 03495 * | Inband | False | True | 03496 * | RFC2833 | True | True | 03497 * | SIP INFO | False | False | 03498 * -------------------------------------------------- 03499 * However, if DTMF from both channels is being monitored by the core, then 03500 * we can still do packet-to-packet bridging, because passing through the 03501 * core will handle DTMF mode translation. 03502 */ 03503 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03504 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03505 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03506 ast_channel_unlock(c0); 03507 ast_channel_unlock(c1); 03508 return AST_BRIDGE_FAILED_NOWARN; 03509 } 03510 audio_p0_res = AST_RTP_TRY_PARTIAL; 03511 audio_p1_res = AST_RTP_TRY_PARTIAL; 03512 } 03513 03514 /* If we need to feed frames into the core don't do a P2P bridge */ 03515 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 03516 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 03517 ast_channel_unlock(c0); 03518 ast_channel_unlock(c1); 03519 return AST_BRIDGE_FAILED_NOWARN; 03520 } 03521 03522 /* Get codecs from both sides */ 03523 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03524 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03525 if (codec0 && codec1 && !(codec0 & codec1)) { 03526 /* Hey, we can't do native bridging if both parties speak different codecs */ 03527 if (option_debug) 03528 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03529 ast_channel_unlock(c0); 03530 ast_channel_unlock(c1); 03531 return AST_BRIDGE_FAILED_NOWARN; 03532 } 03533 03534 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03535 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03536 struct ast_format_list fmt0, fmt1; 03537 03538 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03539 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03540 if (option_debug) 03541 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03542 ast_channel_unlock(c0); 03543 ast_channel_unlock(c1); 03544 return AST_BRIDGE_FAILED_NOWARN; 03545 } 03546 /* They must also be using the same packetization */ 03547 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03548 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03549 if (fmt0.cur_ms != fmt1.cur_ms) { 03550 if (option_debug) 03551 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03552 ast_channel_unlock(c0); 03553 ast_channel_unlock(c1); 03554 return AST_BRIDGE_FAILED_NOWARN; 03555 } 03556 03557 if (option_verbose > 2) 03558 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03559 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03560 } else { 03561 if (option_verbose > 2) 03562 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03563 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03564 } 03565 03566 return res; 03567 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2866 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp_a_audio().
02867 { 02868 if (pt < 0 || pt >= MAX_RTP_PT) 02869 return 0; /* bogus payload type */ 02870 02871 if (static_RTP_PT[pt].isAstFormat) 02872 return static_RTP_PT[pt].code; 02873 else 02874 return 0; 02875 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Definition at line 2861 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp_a_audio().
02862 { 02863 return &rtp->pref; 02864 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2814 of file rtp.c.
References ast_codec_pref_getsize(), ast_log(), ast_smoother_new(), ast_smoother_reconfigure(), ast_smoother_set_flags(), ast_format_list::cur_ms, ast_format_list::flags, ast_format_list::fr_len, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, option_debug, ast_rtp::pref, prefs, and ast_rtp::smoother.
Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp_a_audio(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().
02815 { 02816 struct ast_format_list current_format_old, current_format_new; 02817 02818 /* if no packets have been sent through this session yet, then 02819 * changing preferences does not require any extra work 02820 */ 02821 if (rtp->lasttxformat == 0) { 02822 rtp->pref = *prefs; 02823 return 0; 02824 } 02825 02826 current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 02827 02828 rtp->pref = *prefs; 02829 02830 current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 02831 02832 /* if the framing desired for the current format has changed, we may have to create 02833 * or adjust the smoother for this session 02834 */ 02835 if ((current_format_new.inc_ms != 0) && 02836 (current_format_new.cur_ms != current_format_old.cur_ms)) { 02837 int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms; 02838 02839 if (rtp->smoother) { 02840 ast_smoother_reconfigure(rtp->smoother, new_size); 02841 if (option_debug) { 02842 ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size); 02843 } 02844 } else { 02845 if (!(rtp->smoother = ast_smoother_new(new_size))) { 02846 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 02847 return -1; 02848 } 02849 if (current_format_new.flags) { 02850 ast_smoother_set_flags(rtp->smoother, current_format_new.flags); 02851 } 02852 if (option_debug) { 02853 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 02854 } 02855 } 02856 } 02857 02858 return 0; 02859 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2221 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(), sip_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().
02222 { 02223 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02224 /*Print some info on the call here */ 02225 ast_verbose(" RTP-stats\n"); 02226 ast_verbose("* Our Receiver:\n"); 02227 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02228 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02229 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0); 02230 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02231 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02232 ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0); 02233 ast_verbose("* Our Sender:\n"); 02234 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02235 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02236 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0); 02237 ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0); 02238 ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0); 02239 ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0); 02240 } 02241 02242 if (rtp->smoother) 02243 ast_smoother_free(rtp->smoother); 02244 if (rtp->ioid) 02245 ast_io_remove(rtp->io, rtp->ioid); 02246 if (rtp->s > -1) 02247 close(rtp->s); 02248 if (rtp->rtcp) { 02249 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02250 close(rtp->rtcp->s); 02251 free(rtp->rtcp); 02252 rtp->rtcp=NULL; 02253 } 02254 02255 ast_mutex_destroy(&rtp->bridge_lock); 02256 02257 free(rtp); 02258 }
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 1546 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, ast_channel::name, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01547 { 01548 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01549 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01550 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01551 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01552 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01553 int srccodec, destcodec, nat_active = 0; 01554 01555 /* Lock channels */ 01556 ast_channel_lock(dest); 01557 if (src) { 01558 while(ast_channel_trylock(src)) { 01559 ast_channel_unlock(dest); 01560 usleep(1); 01561 ast_channel_lock(dest); 01562 } 01563 } 01564 01565 /* Find channel driver interfaces */ 01566 destpr = get_proto(dest); 01567 if (src) 01568 srcpr = get_proto(src); 01569 if (!destpr) { 01570 if (option_debug) 01571 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01572 ast_channel_unlock(dest); 01573 if (src) 01574 ast_channel_unlock(src); 01575 return 0; 01576 } 01577 if (!srcpr) { 01578 if (option_debug) 01579 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01580 ast_channel_unlock(dest); 01581 if (src) 01582 ast_channel_unlock(src); 01583 return 0; 01584 } 01585 01586 /* Get audio and video interface (if native bridge is possible) */ 01587 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01588 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01589 if (srcpr) { 01590 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01591 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01592 } 01593 01594 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01595 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) { 01596 /* Somebody doesn't want to play... */ 01597 ast_channel_unlock(dest); 01598 if (src) 01599 ast_channel_unlock(src); 01600 return 0; 01601 } 01602 if (audio_src_res == AST_RTP_TRY_NATIVE && (video_src_res == AST_RTP_GET_FAILED || video_src_res == AST_RTP_TRY_NATIVE) && srcpr->get_codec) 01603 srccodec = srcpr->get_codec(src); 01604 else 01605 srccodec = 0; 01606 if (audio_dest_res == AST_RTP_TRY_NATIVE && (video_dest_res == AST_RTP_GET_FAILED || video_dest_res == AST_RTP_TRY_NATIVE) && destpr->get_codec) 01607 destcodec = destpr->get_codec(dest); 01608 else 01609 destcodec = 0; 01610 /* Ensure we have at least one matching codec */ 01611 if (srcp && !(srccodec & destcodec)) { 01612 ast_channel_unlock(dest); 01613 ast_channel_unlock(src); 01614 return 0; 01615 } 01616 /* Consider empty media as non-existant */ 01617 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01618 srcp = NULL; 01619 /* If the client has NAT stuff turned on then just safe NAT is active */ 01620 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01621 nat_active = 1; 01622 /* Bridge media early */ 01623 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01624 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01625 ast_channel_unlock(dest); 01626 if (src) 01627 ast_channel_unlock(src); 01628 if (option_debug) 01629 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01630 return 1; 01631 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 516 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().
00517 { 00518 return rtp->s; 00519 }
Definition at line 2131 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().
02132 { 02133 struct ast_rtp *bridged = NULL; 02134 02135 ast_mutex_lock(&rtp->bridge_lock); 02136 bridged = rtp->bridged; 02137 ast_mutex_unlock(&rtp->bridge_lock); 02138 02139 return bridged; 02140 }
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 1767 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().
01769 { 01770 int pt; 01771 01772 ast_mutex_lock(&rtp->bridge_lock); 01773 01774 *astFormats = *nonAstFormats = 0; 01775 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01776 if (rtp->current_RTP_PT[pt].isAstFormat) { 01777 *astFormats |= rtp->current_RTP_PT[pt].code; 01778 } else { 01779 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01780 } 01781 } 01782 01783 ast_mutex_unlock(&rtp->bridge_lock); 01784 01785 return; 01786 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2113 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().
02114 { 02115 if ((them->sin_family != AF_INET) || 02116 (them->sin_port != rtp->them.sin_port) || 02117 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02118 them->sin_family = AF_INET; 02119 them->sin_port = rtp->them.sin_port; 02120 them->sin_addr = rtp->them.sin_addr; 02121 return 1; 02122 } 02123 return 0; 02124 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2177 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().
02178 { 02179 /* 02180 *ssrc our ssrc 02181 *themssrc their ssrc 02182 *lp lost packets 02183 *rxjitter our calculated jitter(rx) 02184 *rxcount no. received packets 02185 *txjitter reported jitter of the other end 02186 *txcount transmitted packets 02187 *rlp remote lost packets 02188 *rtt round trip time 02189 */ 02190 02191 if (qual && rtp) { 02192 qual->local_ssrc = rtp->ssrc; 02193 qual->local_jitter = rtp->rxjitter; 02194 qual->local_count = rtp->rxcount; 02195 qual->remote_ssrc = rtp->themssrc; 02196 qual->remote_count = rtp->txcount; 02197 if (rtp->rtcp) { 02198 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02199 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02200 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02201 qual->rtt = rtp->rtcp->rtt; 02202 } 02203 } 02204 if (rtp->rtcp) { 02205 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02206 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02207 rtp->ssrc, 02208 rtp->themssrc, 02209 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02210 rtp->rxjitter, 02211 rtp->rxcount, 02212 (double)rtp->rtcp->reported_jitter / 65536.0, 02213 rtp->txcount, 02214 rtp->rtcp->reported_lost, 02215 rtp->rtcp->rtt); 02216 return rtp->rtcp->quality; 02217 } else 02218 return "<Unknown> - RTP/RTCP has already been destroyed"; 02219 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 576 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by do_monitor().
00577 { 00578 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00579 return 0; 00580 return rtp->rtpholdtimeout; 00581 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 584 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by do_monitor().
00585 { 00586 return rtp->rtpkeepalive; 00587 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 568 of file rtp.c.
References 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->rtptimeout; 00573 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2126 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 604 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00605 { 00606 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00607 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 3952 of file rtp.c.
References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp.
Referenced by main().
03953 { 03954 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03955 ast_rtp_reload(); 03956 }
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 1810 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().
01811 { 01812 int pt = 0; 01813 01814 ast_mutex_lock(&rtp->bridge_lock); 01815 01816 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01817 code == rtp->rtp_lookup_code_cache_code) { 01818 /* Use our cached mapping, to avoid the overhead of the loop below */ 01819 pt = rtp->rtp_lookup_code_cache_result; 01820 ast_mutex_unlock(&rtp->bridge_lock); 01821 return pt; 01822 } 01823 01824 /* Check the dynamic list first */ 01825 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01826 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01827 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01828 rtp->rtp_lookup_code_cache_code = code; 01829 rtp->rtp_lookup_code_cache_result = pt; 01830 ast_mutex_unlock(&rtp->bridge_lock); 01831 return pt; 01832 } 01833 } 01834 01835 /* Then the static list */ 01836 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01837 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01838 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01839 rtp->rtp_lookup_code_cache_code = code; 01840 rtp->rtp_lookup_code_cache_result = pt; 01841 ast_mutex_unlock(&rtp->bridge_lock); 01842 return pt; 01843 } 01844 } 01845 01846 ast_mutex_unlock(&rtp->bridge_lock); 01847 01848 return -1; 01849 }
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 1870 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.
Referenced by process_sdp().
01872 { 01873 int format; 01874 unsigned len; 01875 char *end = buf; 01876 char *start = buf; 01877 01878 if (!buf || !size) 01879 return NULL; 01880 01881 snprintf(end, size, "0x%x (", capability); 01882 01883 len = strlen(end); 01884 end += len; 01885 size -= len; 01886 start = end; 01887 01888 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01889 if (capability & format) { 01890 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01891 01892 snprintf(end, size, "%s|", name); 01893 len = strlen(end); 01894 end += len; 01895 size -= len; 01896 } 01897 } 01898 01899 if (start == end) 01900 snprintf(start, size, "nothing)"); 01901 else if (size > 1) 01902 *(end -1) = ')'; 01903 01904 return buf; 01905 }
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 1851 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().
01853 { 01854 unsigned int i; 01855 01856 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01857 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01858 if (isAstFormat && 01859 (code == AST_FORMAT_G726_AAL2) && 01860 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01861 return "G726-32"; 01862 else 01863 return mimeTypes[i].subtype; 01864 } 01865 } 01866 01867 return ""; 01868 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1788 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().
01789 { 01790 struct rtpPayloadType result; 01791 01792 result.isAstFormat = result.code = 0; 01793 01794 if (pt < 0 || pt >= MAX_RTP_PT) 01795 return result; /* bogus payload type */ 01796 01797 /* Start with negotiated codecs */ 01798 ast_mutex_lock(&rtp->bridge_lock); 01799 result = rtp->current_RTP_PT[pt]; 01800 ast_mutex_unlock(&rtp->bridge_lock); 01801 01802 /* If it doesn't exist, check our static RTP type list, just in case */ 01803 if (!result.code) 01804 result = static_RTP_PT[pt]; 01805 01806 return result; 01807 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1633 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, ast_channel::name, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01634 { 01635 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01636 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01637 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01638 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01639 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01640 int srccodec, destcodec; 01641 01642 /* Lock channels */ 01643 ast_channel_lock(dest); 01644 while(ast_channel_trylock(src)) { 01645 ast_channel_unlock(dest); 01646 usleep(1); 01647 ast_channel_lock(dest); 01648 } 01649 01650 /* Find channel driver interfaces */ 01651 if (!(destpr = get_proto(dest))) { 01652 if (option_debug) 01653 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01654 ast_channel_unlock(dest); 01655 ast_channel_unlock(src); 01656 return 0; 01657 } 01658 if (!(srcpr = get_proto(src))) { 01659 if (option_debug) 01660 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01661 ast_channel_unlock(dest); 01662 ast_channel_unlock(src); 01663 return 0; 01664 } 01665 01666 /* Get audio and video interface (if native bridge is possible) */ 01667 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01668 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01669 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01670 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01671 01672 /* Ensure we have at least one matching codec */ 01673 if (srcpr->get_codec) 01674 srccodec = srcpr->get_codec(src); 01675 else 01676 srccodec = 0; 01677 if (destpr->get_codec) 01678 destcodec = destpr->get_codec(dest); 01679 else 01680 destcodec = 0; 01681 01682 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01683 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE) || audio_src_res != AST_RTP_TRY_NATIVE || (video_src_res != AST_RTP_GET_FAILED && video_src_res != AST_RTP_TRY_NATIVE) || !(srccodec & destcodec)) { 01684 /* Somebody doesn't want to play... */ 01685 ast_channel_unlock(dest); 01686 ast_channel_unlock(src); 01687 return 0; 01688 } 01689 ast_rtp_pt_copy(destp, srcp); 01690 if (vdestp && vsrcp) 01691 ast_rtp_pt_copy(vdestp, vsrcp); 01692 if (media) { 01693 /* Bridge early */ 01694 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01695 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01696 } 01697 ast_channel_unlock(dest); 01698 ast_channel_unlock(src); 01699 if (option_debug) 01700 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01701 return 1; 01702 }
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 2060 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
02061 { 02062 struct in_addr ia; 02063 02064 memset(&ia, 0, sizeof(ia)); 02065 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02066 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1954 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().
01955 { 01956 ast_mutex_init(&rtp->bridge_lock); 01957 01958 rtp->them.sin_family = AF_INET; 01959 rtp->us.sin_family = AF_INET; 01960 rtp->ssrc = ast_random(); 01961 rtp->seqno = ast_random() & 0xffff; 01962 ast_set_flag(rtp, FLAG_HAS_DTMF); 01963 01964 return; 01965 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2082 of file rtp.c.
References ast_random(), ast_rtp::constantssrc, ast_rtp::set_marker_bit, and ast_rtp::ssrc.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), sip_write(), and skinny_indicate().
02083 { 02084 if (rtp) { 02085 rtp->set_marker_bit = 1; 02086 if (!rtp->constantssrc) { 02087 rtp->ssrc = ast_random(); 02088 } 02089 } 02090 }
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 1967 of file rtp.c.
References ast_calloc, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), errno, first, free, LOG_DEBUG, LOG_ERROR, option_debug, rtp_socket(), and sched.
Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), sip_alloc(), and start_rtp().
01968 { 01969 struct ast_rtp *rtp; 01970 int x; 01971 int first; 01972 int startplace; 01973 01974 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01975 return NULL; 01976 01977 ast_rtp_new_init(rtp); 01978 01979 rtp->s = rtp_socket(); 01980 if (option_debug > 2) 01981 ast_log(LOG_DEBUG, "socket RTP fd: %i\n", rtp->s); 01982 if (rtp->s < 0) { 01983 free(rtp); 01984 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01985 return NULL; 01986 } 01987 if (sched && rtcpenable) { 01988 rtp->sched = sched; 01989 rtp->rtcp = ast_rtcp_new(); 01990 if (option_debug > 2) 01991 ast_log(LOG_DEBUG, "socket RTCP fd: %i\n", rtp->rtcp->s); 01992 } 01993 01994 /* Select a random port number in the range of possible RTP */ 01995 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 01996 x = x & ~1; 01997 /* Save it for future references. */ 01998 startplace = x; 01999 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 02000 for (;;) { 02001 /* Must be an even port number by RTP spec */ 02002 rtp->us.sin_port = htons(x); 02003 rtp->us.sin_addr = addr; 02004 /* If there's rtcp, initialize it as well. */ 02005 if (rtp->rtcp) { 02006 rtp->rtcp->us.sin_port = htons(x + 1); 02007 rtp->rtcp->us.sin_addr = addr; 02008 } 02009 /* Try to bind it/them. */ 02010 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 02011 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 02012 break; 02013 if (!first) { 02014 /* Primary bind succeeded! Gotta recreate it */ 02015 close(rtp->s); 02016 rtp->s = rtp_socket(); 02017 if (option_debug > 2) 02018 ast_log(LOG_DEBUG, "socket RTP2 fd: %i\n", rtp->s); 02019 } 02020 if (errno != EADDRINUSE) { 02021 /* We got an error that wasn't expected, abort! */ 02022 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 02023 close(rtp->s); 02024 if (rtp->rtcp) { 02025 close(rtp->rtcp->s); 02026 free(rtp->rtcp); 02027 } 02028 free(rtp); 02029 return NULL; 02030 } 02031 /* The port was used, increment it (by two). */ 02032 x += 2; 02033 /* Did we go over the limit ? */ 02034 if (x > rtpend) 02035 /* then, start from the begingig. */ 02036 x = (rtpstart + 1) & ~1; 02037 /* Check if we reached the place were we started. */ 02038 if (x == startplace) { 02039 /* If so, there's no ports available. */ 02040 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 02041 close(rtp->s); 02042 if (rtp->rtcp) { 02043 close(rtp->rtcp->s); 02044 free(rtp->rtcp); 02045 } 02046 free(rtp); 02047 return NULL; 02048 } 02049 } 02050 rtp->sched = sched; 02051 rtp->io = io; 02052 if (callbackmode) { 02053 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 02054 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 02055 } 02056 ast_rtp_pt_default(rtp); 02057 return rtp; 02058 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2968 of file rtp.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_rtp_protocol::list, LOG_WARNING, and ast_rtp_protocol::type.
Referenced by load_module().
02969 { 02970 struct ast_rtp_protocol *cur; 02971 02972 AST_LIST_LOCK(&protos); 02973 AST_LIST_TRAVERSE(&protos, cur, list) { 02974 if (!strcmp(cur->type, proto->type)) { 02975 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02976 AST_LIST_UNLOCK(&protos); 02977 return -1; 02978 } 02979 } 02980 AST_LIST_INSERT_HEAD(&protos, proto, list); 02981 AST_LIST_UNLOCK(&protos); 02982 02983 return 0; 02984 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2960 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by load_module(), and unload_module().
02961 { 02962 AST_LIST_LOCK(&protos); 02963 AST_LIST_REMOVE(&protos, proto, list); 02964 AST_LIST_UNLOCK(&protos); 02965 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1470 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().
01471 { 01472 int i; 01473 01474 if (!rtp) 01475 return; 01476 01477 ast_mutex_lock(&rtp->bridge_lock); 01478 01479 for (i = 0; i < MAX_RTP_PT; ++i) { 01480 rtp->current_RTP_PT[i].isAstFormat = 0; 01481 rtp->current_RTP_PT[i].code = 0; 01482 } 01483 01484 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01485 rtp->rtp_lookup_code_cache_code = 0; 01486 rtp->rtp_lookup_code_cache_result = 0; 01487 01488 ast_mutex_unlock(&rtp->bridge_lock); 01489 }
Copy payload types between RTP structures.
Definition at line 1510 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().
01511 { 01512 unsigned int i; 01513 01514 ast_mutex_lock(&dest->bridge_lock); 01515 ast_mutex_lock(&src->bridge_lock); 01516 01517 for (i=0; i < MAX_RTP_PT; ++i) { 01518 dest->current_RTP_PT[i].isAstFormat = 01519 src->current_RTP_PT[i].isAstFormat; 01520 dest->current_RTP_PT[i].code = 01521 src->current_RTP_PT[i].code; 01522 } 01523 dest->rtp_lookup_code_cache_isAstFormat = 0; 01524 dest->rtp_lookup_code_cache_code = 0; 01525 dest->rtp_lookup_code_cache_result = 0; 01526 01527 ast_mutex_unlock(&src->bridge_lock); 01528 ast_mutex_unlock(&dest->bridge_lock); 01529 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1491 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.
01492 { 01493 int i; 01494 01495 ast_mutex_lock(&rtp->bridge_lock); 01496 01497 /* Initialize to default payload types */ 01498 for (i = 0; i < MAX_RTP_PT; ++i) { 01499 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01500 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01501 } 01502 01503 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01504 rtp->rtp_lookup_code_cache_code = 0; 01505 rtp->rtp_lookup_code_cache_result = 0; 01506 01507 ast_mutex_unlock(&rtp->bridge_lock); 01508 }
Definition at line 2706 of file rtp.c.
References AST_FORMAT_G722, 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_tvzero(), 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(), rtp_get_rate(), ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::set_marker_bit, ast_rtp::ssrc, ast_rtcp::them, ast_rtp::them, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
02707 { 02708 unsigned char *rtpheader; 02709 int hdrlen = 12; 02710 int res; 02711 unsigned int ms; 02712 int pred; 02713 int mark = 0; 02714 int rate = rtp_get_rate(f->subclass) / 1000; 02715 02716 if (f->subclass == AST_FORMAT_G722) { 02717 /* G722 is silllllllllllllllllly */ 02718 f->samples /= 2; 02719 } 02720 02721 if (rtp->sending_digit) { 02722 return 0; 02723 } 02724 02725 ms = calc_txstamp(rtp, &f->delivery); 02726 /* Default prediction */ 02727 if (f->frametype == AST_FRAME_VOICE) { 02728 pred = rtp->lastts + f->samples; 02729 02730 /* Re-calculate last TS */ 02731 rtp->lastts = rtp->lastts + ms * rate; 02732 if (ast_tvzero(f->delivery)) { 02733 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02734 and if so, go with our prediction */ 02735 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02736 rtp->lastts = pred; 02737 else { 02738 if (option_debug > 2) 02739 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02740 mark = 1; 02741 } 02742 } 02743 } else if (f->frametype == AST_FRAME_VIDEO) { 02744 mark = f->subclass & 0x1; 02745 pred = rtp->lastovidtimestamp + f->samples; 02746 /* Re-calculate last TS */ 02747 rtp->lastts = rtp->lastts + ms * 90; 02748 /* If it's close to our prediction, go for it */ 02749 if (ast_tvzero(f->delivery)) { 02750 if (abs(rtp->lastts - pred) < 7200) { 02751 rtp->lastts = pred; 02752 rtp->lastovidtimestamp += f->samples; 02753 } else { 02754 if (option_debug > 2) 02755 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); 02756 rtp->lastovidtimestamp = rtp->lastts; 02757 } 02758 } 02759 } 02760 02761 /* If we have been explicitly told to set the marker bit do so */ 02762 if (rtp->set_marker_bit) { 02763 mark = 1; 02764 rtp->set_marker_bit = 0; 02765 } 02766 02767 /* If the timestamp for non-digit packets has moved beyond the timestamp 02768 for digits, update the digit timestamp. 02769 */ 02770 if (rtp->lastts > rtp->lastdigitts) 02771 rtp->lastdigitts = rtp->lastts; 02772 02773 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 02774 rtp->lastts = f->ts * rate; 02775 02776 /* Get a pointer to the header */ 02777 rtpheader = (unsigned char *)(f->data - hdrlen); 02778 02779 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02780 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02781 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02782 02783 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02784 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02785 if (res <0) { 02786 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02787 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)); 02788 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02789 /* Only give this error message once if we are not RTP debugging */ 02790 if (option_debug || rtpdebug) 02791 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)); 02792 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02793 } 02794 } else { 02795 rtp->txcount++; 02796 rtp->txoctetcount +=(res - hdrlen); 02797 02798 /* Do not schedule RR if RTCP isn't run */ 02799 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 02800 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02801 } 02802 } 02803 02804 if (rtp_debug_test_addr(&rtp->them)) 02805 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02806 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02807 } 02808 02809 rtp->seqno++; 02810 02811 return 0; 02812 }
Definition at line 1160 of file rtp.c.
References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_DTMF_END, 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_samp2tv(), ast_sched_add(), ast_set_flag, ast_tv(), ast_tvdiff_ms(), 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, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, 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::resp, ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), 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, send_dtmf(), 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().
01161 { 01162 int res; 01163 struct sockaddr_in sin; 01164 socklen_t len; 01165 unsigned int seqno; 01166 int version; 01167 int payloadtype; 01168 int hdrlen = 12; 01169 int padding; 01170 int mark; 01171 int ext; 01172 int cc; 01173 unsigned int ssrc; 01174 unsigned int timestamp; 01175 unsigned int *rtpheader; 01176 struct rtpPayloadType rtpPT; 01177 struct ast_rtp *bridged = NULL; 01178 01179 /* If time is up, kill it */ 01180 if (rtp->sending_digit) 01181 ast_rtp_senddigit_continuation(rtp); 01182 01183 len = sizeof(sin); 01184 01185 /* Cache where the header will go */ 01186 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01187 0, (struct sockaddr *)&sin, &len); 01188 if (option_debug > 3) 01189 ast_log(LOG_DEBUG, "socket RTP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 01190 01191 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01192 if (res < 0) { 01193 ast_assert(errno != EBADF); 01194 if (errno != EAGAIN) { 01195 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01196 ast_log(LOG_WARNING, "socket RTP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 01197 return NULL; 01198 } 01199 return &ast_null_frame; 01200 } 01201 01202 if (res < hdrlen) { 01203 ast_log(LOG_WARNING, "RTP Read too short\n"); 01204 return &ast_null_frame; 01205 } 01206 01207 /* Get fields */ 01208 seqno = ntohl(rtpheader[0]); 01209 01210 /* Check RTP version */ 01211 version = (seqno & 0xC0000000) >> 30; 01212 if (!version) { 01213 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01214 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01215 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01216 } 01217 return &ast_null_frame; 01218 } 01219 01220 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01221 /* If we don't have the other side's address, then ignore this */ 01222 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01223 return &ast_null_frame; 01224 #endif 01225 01226 /* Send to whoever send to us if NAT is turned on */ 01227 if (rtp->nat) { 01228 if (((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01229 (rtp->them.sin_port != sin.sin_port)) && 01230 ((rtp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) || 01231 (rtp->altthem.sin_port != sin.sin_port))) { 01232 rtp->them = sin; 01233 if (rtp->rtcp) { 01234 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01235 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01236 } 01237 rtp->rxseqno = 0; 01238 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01239 if (option_debug || rtpdebug) 01240 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)); 01241 } 01242 } 01243 01244 /* If we are bridged to another RTP stream, send direct */ 01245 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01246 return &ast_null_frame; 01247 01248 if (version != 2) 01249 return &ast_null_frame; 01250 01251 payloadtype = (seqno & 0x7f0000) >> 16; 01252 padding = seqno & (1 << 29); 01253 mark = seqno & (1 << 23); 01254 ext = seqno & (1 << 28); 01255 cc = (seqno & 0xF000000) >> 24; 01256 seqno &= 0xffff; 01257 timestamp = ntohl(rtpheader[1]); 01258 ssrc = ntohl(rtpheader[2]); 01259 01260 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01261 if (option_debug || rtpdebug) 01262 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01263 mark = 1; 01264 } 01265 01266 rtp->rxssrc = ssrc; 01267 01268 if (padding) { 01269 /* Remove padding bytes */ 01270 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01271 } 01272 01273 if (cc) { 01274 /* CSRC fields present */ 01275 hdrlen += cc*4; 01276 } 01277 01278 if (ext) { 01279 /* RTP Extension present */ 01280 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01281 hdrlen += 4; 01282 } 01283 01284 if (res < hdrlen) { 01285 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01286 return &ast_null_frame; 01287 } 01288 01289 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01290 01291 if (rtp->rxcount==1) { 01292 /* This is the first RTP packet successfully received from source */ 01293 rtp->seedrxseqno = seqno; 01294 } 01295 01296 /* Do not schedule RR if RTCP isn't run */ 01297 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01298 /* Schedule transmission of Receiver Report */ 01299 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01300 } 01301 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01302 rtp->cycles += RTP_SEQ_MOD; 01303 01304 rtp->lastrxseqno = seqno; 01305 01306 if (rtp->themssrc==0) 01307 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01308 01309 if (rtp_debug_test_addr(&sin)) 01310 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01311 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01312 01313 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01314 if (!rtpPT.isAstFormat) { 01315 struct ast_frame *f = NULL; 01316 01317 /* This is special in-band data that's not one of our codecs */ 01318 if (rtpPT.code == AST_RTP_DTMF) { 01319 /* It's special -- rfc2833 process it */ 01320 if (rtp_debug_test_addr(&sin)) { 01321 unsigned char *data; 01322 unsigned int event; 01323 unsigned int event_end; 01324 unsigned int duration; 01325 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01326 event = ntohl(*((unsigned int *)(data))); 01327 event >>= 24; 01328 event_end = ntohl(*((unsigned int *)(data))); 01329 event_end <<= 8; 01330 event_end >>= 24; 01331 duration = ntohl(*((unsigned int *)(data))); 01332 duration &= 0xFFFF; 01333 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); 01334 } 01335 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01336 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01337 /* It's really special -- process it the Cisco way */ 01338 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01339 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01340 rtp->lastevent = seqno; 01341 } 01342 } else if (rtpPT.code == AST_RTP_CN) { 01343 /* Comfort Noise */ 01344 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01345 } else { 01346 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01347 } 01348 return f ? f : &ast_null_frame; 01349 } 01350 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01351 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01352 01353 rtp->rxseqno = seqno; 01354 01355 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) { 01356 rtp->dtmf_timeout = 0; 01357 01358 if (rtp->resp) { 01359 struct ast_frame *f; 01360 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01361 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01362 rtp->resp = 0; 01363 rtp->dtmf_timeout = rtp->dtmf_duration = 0; 01364 return f; 01365 } 01366 } 01367 01368 /* Record received timestamp as last received now */ 01369 rtp->lastrxts = timestamp; 01370 01371 rtp->f.mallocd = 0; 01372 rtp->f.datalen = res - hdrlen; 01373 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01374 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01375 rtp->f.seqno = seqno; 01376 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01377 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01378 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01379 ast_frame_byteswap_be(&rtp->f); 01380 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01381 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01382 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01383 rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000); 01384 rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000); 01385 } else { 01386 /* Video -- samples is # of samples vs. 90000 */ 01387 if (!rtp->lastividtimestamp) 01388 rtp->lastividtimestamp = timestamp; 01389 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01390 rtp->lastividtimestamp = timestamp; 01391 rtp->f.delivery.tv_sec = 0; 01392 rtp->f.delivery.tv_usec = 0; 01393 if (mark) 01394 rtp->f.subclass |= 0x1; 01395 } 01396 rtp->f.src = "RTP"; 01397 return &rtp->f; 01398 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3887 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().
03888 { 03889 struct ast_config *cfg; 03890 const char *s; 03891 03892 rtpstart = 5000; 03893 rtpend = 31000; 03894 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03895 cfg = ast_config_load("rtp.conf"); 03896 if (cfg) { 03897 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03898 rtpstart = atoi(s); 03899 if (rtpstart < 1024) 03900 rtpstart = 1024; 03901 if (rtpstart > 65535) 03902 rtpstart = 65535; 03903 } 03904 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03905 rtpend = atoi(s); 03906 if (rtpend < 1024) 03907 rtpend = 1024; 03908 if (rtpend > 65535) 03909 rtpend = 65535; 03910 } 03911 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03912 rtcpinterval = atoi(s); 03913 if (rtcpinterval == 0) 03914 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03915 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03916 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03917 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03918 rtcpinterval = RTCP_MAX_INTERVALMS; 03919 } 03920 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03921 #ifdef SO_NO_CHECK 03922 if (ast_false(s)) 03923 nochecksums = 1; 03924 else 03925 nochecksums = 0; 03926 #else 03927 if (ast_false(s)) 03928 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03929 #endif 03930 } 03931 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03932 dtmftimeout = atoi(s); 03933 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) { 03934 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03935 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03936 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03937 }; 03938 } 03939 ast_config_destroy(cfg); 03940 } 03941 if (rtpstart >= rtpend) { 03942 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03943 rtpstart = 5000; 03944 rtpend = 31000; 03945 } 03946 if (option_verbose > 1) 03947 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03948 return 0; 03949 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2158 of file rtp.c.
References ast_rtp::dtmf_timeout, ast_rtp::dtmfmute, 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.
02159 { 02160 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02161 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02162 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02163 rtp->lastts = 0; 02164 rtp->lastdigitts = 0; 02165 rtp->lastrxts = 0; 02166 rtp->lastividtimestamp = 0; 02167 rtp->lastovidtimestamp = 0; 02168 rtp->lasteventseqn = 0; 02169 rtp->lastevent = 0; 02170 rtp->lasttxformat = 0; 02171 rtp->lastrxformat = 0; 02172 rtp->dtmf_timeout = 0; 02173 rtp->seqno = 0; 02174 rtp->rxseqno = 0; 02175 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2672 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), 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().
02673 { 02674 unsigned int *rtpheader; 02675 int hdrlen = 12; 02676 int res; 02677 int payload; 02678 char data[256]; 02679 level = 127 - (level & 0x7f); 02680 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02681 02682 /* If we have no peer, return immediately */ 02683 if (!rtp->them.sin_addr.s_addr) 02684 return 0; 02685 02686 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02687 02688 /* Get a pointer to the header */ 02689 rtpheader = (unsigned int *)data; 02690 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02691 rtpheader[1] = htonl(rtp->lastts); 02692 rtpheader[2] = htonl(rtp->ssrc); 02693 data[12] = level; 02694 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02695 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02696 if (res <0) 02697 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)); 02698 if (rtp_debug_test_addr(&rtp->them)) 02699 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02700 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02701 02702 } 02703 return 0; 02704 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2280 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, 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().
02281 { 02282 unsigned int *rtpheader; 02283 int hdrlen = 12, res = 0, i = 0, payload = 0; 02284 char data[256]; 02285 02286 if ((digit <= '9') && (digit >= '0')) 02287 digit -= '0'; 02288 else if (digit == '*') 02289 digit = 10; 02290 else if (digit == '#') 02291 digit = 11; 02292 else if ((digit >= 'A') && (digit <= 'D')) 02293 digit = digit - 'A' + 12; 02294 else if ((digit >= 'a') && (digit <= 'd')) 02295 digit = digit - 'a' + 12; 02296 else { 02297 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02298 return 0; 02299 } 02300 02301 /* If we have no peer, return immediately */ 02302 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02303 return 0; 02304 02305 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02306 02307 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02308 rtp->send_duration = 160; 02309 rtp->lastdigitts = rtp->lastts + rtp->send_duration; 02310 02311 /* Get a pointer to the header */ 02312 rtpheader = (unsigned int *)data; 02313 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02314 rtpheader[1] = htonl(rtp->lastdigitts); 02315 rtpheader[2] = htonl(rtp->ssrc); 02316 02317 for (i = 0; i < 2; i++) { 02318 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02319 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02320 if (res < 0) 02321 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02322 ast_inet_ntoa(rtp->them.sin_addr), 02323 ntohs(rtp->them.sin_port), strerror(errno)); 02324 if (rtp_debug_test_addr(&rtp->them)) 02325 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02326 ast_inet_ntoa(rtp->them.sin_addr), 02327 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02328 /* Increment sequence number */ 02329 rtp->seqno++; 02330 /* Increment duration */ 02331 rtp->send_duration += 160; 02332 /* Clear marker bit and set seqno */ 02333 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02334 } 02335 02336 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02337 rtp->sending_digit = 1; 02338 rtp->send_digit = digit; 02339 rtp->send_payload = payload; 02340 02341 return 0; 02342 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2345 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().
02346 { 02347 unsigned int *rtpheader; 02348 int hdrlen = 12, res = 0; 02349 char data[256]; 02350 02351 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02352 return 0; 02353 02354 /* Setup packet to send */ 02355 rtpheader = (unsigned int *)data; 02356 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02357 rtpheader[1] = htonl(rtp->lastdigitts); 02358 rtpheader[2] = htonl(rtp->ssrc); 02359 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02360 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02361 02362 /* Transmit */ 02363 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02364 if (res < 0) 02365 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02366 ast_inet_ntoa(rtp->them.sin_addr), 02367 ntohs(rtp->them.sin_port), strerror(errno)); 02368 if (rtp_debug_test_addr(&rtp->them)) 02369 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02370 ast_inet_ntoa(rtp->them.sin_addr), 02371 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02372 02373 /* Increment sequence number */ 02374 rtp->seqno++; 02375 /* Increment duration */ 02376 rtp->send_duration += 160; 02377 02378 return 0; 02379 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2382 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, 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().
02383 { 02384 unsigned int *rtpheader; 02385 int hdrlen = 12, res = 0, i = 0; 02386 char data[256]; 02387 02388 /* If no address, then bail out */ 02389 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02390 return 0; 02391 02392 if ((digit <= '9') && (digit >= '0')) 02393 digit -= '0'; 02394 else if (digit == '*') 02395 digit = 10; 02396 else if (digit == '#') 02397 digit = 11; 02398 else if ((digit >= 'A') && (digit <= 'D')) 02399 digit = digit - 'A' + 12; 02400 else if ((digit >= 'a') && (digit <= 'd')) 02401 digit = digit - 'a' + 12; 02402 else { 02403 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02404 return 0; 02405 } 02406 02407 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02408 02409 rtpheader = (unsigned int *)data; 02410 rtpheader[1] = htonl(rtp->lastdigitts); 02411 rtpheader[2] = htonl(rtp->ssrc); 02412 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02413 /* Set end bit */ 02414 rtpheader[3] |= htonl((1 << 23)); 02415 02416 /* Send 3 termination packets */ 02417 for (i = 0; i < 3; i++) { 02418 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02419 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02420 rtp->seqno++; 02421 if (res < 0) 02422 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02423 ast_inet_ntoa(rtp->them.sin_addr), 02424 ntohs(rtp->them.sin_port), strerror(errno)); 02425 if (rtp_debug_test_addr(&rtp->them)) 02426 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02427 ast_inet_ntoa(rtp->them.sin_addr), 02428 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02429 } 02430 rtp->lastts += rtp->send_duration; 02431 rtp->sending_digit = 0; 02432 rtp->send_digit = 0; 02433 02434 return res; 02435 }
void ast_rtp_set_alt_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | alt | |||
) |
set potential alternate source for RTP media
rtp | The RTP structure we wish to set up an alternate host/port on | |
alt | The address information for the alternate media source |
void |
Definition at line 2103 of file rtp.c.
References ast_rtp::altthem, ast_rtcp::altthem, and ast_rtp::rtcp.
Referenced by handle_request_invite().
02104 { 02105 rtp->altthem.sin_port = alt->sin_port; 02106 rtp->altthem.sin_addr = alt->sin_addr; 02107 if (rtp->rtcp) { 02108 rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1); 02109 rtp->rtcp->altthem.sin_addr = alt->sin_addr; 02110 } 02111 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 594 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00595 { 00596 rtp->callback = callback; 00597 }
void ast_rtp_set_constantssrc | ( | struct ast_rtp * | rtp | ) |
When changing sources, don't generate a new SSRC.
Definition at line 2077 of file rtp.c.
References ast_rtp::constantssrc.
Referenced by create_addr_from_peer(), and handle_request_invite().
02078 { 02079 rtp->constantssrc = 1; 02080 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 589 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00590 { 00591 rtp->data = data; 00592 }
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Activate payload type.
Definition at line 1708 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().
01709 { 01710 if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01711 return; /* bogus payload type */ 01712 01713 ast_mutex_lock(&rtp->bridge_lock); 01714 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01715 ast_mutex_unlock(&rtp->bridge_lock); 01716 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2092 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().
02093 { 02094 rtp->them.sin_port = them->sin_port; 02095 rtp->them.sin_addr = them->sin_addr; 02096 if (rtp->rtcp) { 02097 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02098 rtp->rtcp->them.sin_addr = them->sin_addr; 02099 } 02100 rtp->rxseqno = 0; 02101 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 556 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00557 { 00558 rtp->rtpholdtimeout = timeout; 00559 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 562 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00563 { 00564 rtp->rtpkeepalive = period; 00565 }
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 1735 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(), process_sdp_a_audio(), process_sdp_a_video(), and set_dtmf_payload().
01738 { 01739 unsigned int i; 01740 int found = 0; 01741 01742 if (pt < 0 || pt >= MAX_RTP_PT) 01743 return -1; /* bogus payload type */ 01744 01745 ast_mutex_lock(&rtp->bridge_lock); 01746 01747 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01748 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01749 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01750 found = 1; 01751 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01752 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01753 mimeTypes[i].payloadType.isAstFormat && 01754 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01755 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01756 break; 01757 } 01758 } 01759 01760 ast_mutex_unlock(&rtp->bridge_lock); 01761 01762 return (found ? 0 : -1); 01763 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 550 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00551 { 00552 rtp->rtptimeout = timeout; 00553 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 543 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00544 { 00545 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00546 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00547 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 609 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().
00610 { 00611 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00612 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 614 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().
00615 { 00616 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00617 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 599 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 619 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00620 { 00621 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00622 }
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 2068 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
02069 { 02070 int res; 02071 02072 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 02073 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 02074 return res; 02075 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2142 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().
02143 { 02144 if (rtp->rtcp) { 02145 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02146 } 02147 02148 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02149 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02150 if (rtp->rtcp) { 02151 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02152 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02153 } 02154 02155 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02156 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Definition at line 406 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().
00407 { 00408 struct stun_header *req; 00409 unsigned char reqdata[1024]; 00410 int reqlen, reqleft; 00411 struct stun_attr *attr; 00412 00413 req = (struct stun_header *)reqdata; 00414 stun_req_id(req); 00415 reqlen = 0; 00416 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00417 req->msgtype = 0; 00418 req->msglen = 0; 00419 attr = (struct stun_attr *)req->ies; 00420 if (username) 00421 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00422 req->msglen = htons(reqlen); 00423 req->msgtype = htons(STUN_BINDREQ); 00424 stun_send(rtp->s, suggestion, req); 00425 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
clear payload type
Definition at line 1720 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_a_audio(), and process_sdp_a_video().
01721 { 01722 if (pt < 0 || pt >= MAX_RTP_PT) 01723 return; /* bogus payload type */ 01724 01725 ast_mutex_lock(&rtp->bridge_lock); 01726 rtp->current_RTP_PT[pt].isAstFormat = 0; 01727 rtp->current_RTP_PT[pt].code = 0; 01728 ast_mutex_unlock(&rtp->bridge_lock); 01729 }
Definition at line 2877 of file rtp.c.
References ast_codec_pref_getsize(), AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
Referenced by gtalk_write(), mgcp_write(), oh323_write(), sip_write(), and skinny_write().
02878 { 02879 struct ast_frame *f; 02880 int codec; 02881 int hdrlen = 12; 02882 int subclass; 02883 02884 02885 /* If we have no peer, return immediately */ 02886 if (!rtp->them.sin_addr.s_addr) 02887 return 0; 02888 02889 /* If there is no data length, return immediately */ 02890 if (!_f->datalen) 02891 return 0; 02892 02893 /* Make sure we have enough space for RTP header */ 02894 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02895 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02896 return -1; 02897 } 02898 02899 subclass = _f->subclass; 02900 if (_f->frametype == AST_FRAME_VIDEO) 02901 subclass &= ~0x1; 02902 02903 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02904 if (codec < 0) { 02905 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02906 return -1; 02907 } 02908 02909 if (rtp->lasttxformat != subclass) { 02910 /* New format, reset the smoother */ 02911 if (option_debug) 02912 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02913 rtp->lasttxformat = subclass; 02914 if (rtp->smoother) 02915 ast_smoother_free(rtp->smoother); 02916 rtp->smoother = NULL; 02917 } 02918 02919 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 02920 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02921 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02922 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02923 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)); 02924 return -1; 02925 } 02926 if (fmt.flags) 02927 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02928 if (option_debug) 02929 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)); 02930 } 02931 } 02932 if (rtp->smoother) { 02933 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02934 ast_smoother_feed_be(rtp->smoother, _f); 02935 } else { 02936 ast_smoother_feed(rtp->smoother, _f); 02937 } 02938 02939 while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { 02940 ast_rtp_raw_write(rtp, f, codec); 02941 } 02942 } else { 02943 /* Don't buffer outgoing frames; send them one-per-packet: */ 02944 if (_f->offset < hdrlen) { 02945 f = ast_frdup(_f); 02946 } else { 02947 f = _f; 02948 } 02949 if (f->data) { 02950 ast_rtp_raw_write(rtp, f, codec); 02951 } 02952 if (f != _f) 02953 ast_frfree(f); 02954 } 02955 02956 return 0; 02957 }
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 2987 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, ast_channel::name, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
02988 { 02989 struct ast_frame *fr = NULL; 02990 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02991 int oldcodec0 = codec0, oldcodec1 = codec1; 02992 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02993 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02994 02995 /* Set it up so audio goes directly between the two endpoints */ 02996 02997 /* Test the first channel */ 02998 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02999 ast_rtp_get_peer(p1, &ac1); 03000 if (vp1) 03001 ast_rtp_get_peer(vp1, &vac1); 03002 } else 03003 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 03004 03005 /* Test the second channel */ 03006 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 03007 ast_rtp_get_peer(p0, &ac0); 03008 if (vp0) 03009 ast_rtp_get_peer(vp0, &vac0); 03010 } else 03011 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 03012 03013 /* Now we can unlock and move into our loop */ 03014 ast_channel_unlock(c0); 03015 ast_channel_unlock(c1); 03016 03017 /* Throw our channels into the structure and enter the loop */ 03018 cs[0] = c0; 03019 cs[1] = c1; 03020 cs[2] = NULL; 03021 for (;;) { 03022 /* Check if anything changed */ 03023 if ((c0->tech_pvt != pvt0) || 03024 (c1->tech_pvt != pvt1) || 03025 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03026 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03027 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03028 if (c0->tech_pvt == pvt0) 03029 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03030 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03031 if (c1->tech_pvt == pvt1) 03032 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03033 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03034 return AST_BRIDGE_RETRY; 03035 } 03036 03037 /* Check if they have changed their address */ 03038 ast_rtp_get_peer(p1, &t1); 03039 if (vp1) 03040 ast_rtp_get_peer(vp1, &vt1); 03041 if (pr1->get_codec) 03042 codec1 = pr1->get_codec(c1); 03043 ast_rtp_get_peer(p0, &t0); 03044 if (vp0) 03045 ast_rtp_get_peer(vp0, &vt0); 03046 if (pr0->get_codec) 03047 codec0 = pr0->get_codec(c0); 03048 if ((inaddrcmp(&t1, &ac1)) || 03049 (vp1 && inaddrcmp(&vt1, &vac1)) || 03050 (codec1 != oldcodec1)) { 03051 if (option_debug > 1) { 03052 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03053 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 03054 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 03055 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 03056 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 03057 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 03058 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 03059 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 03060 } 03061 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))) 03062 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 03063 memcpy(&ac1, &t1, sizeof(ac1)); 03064 memcpy(&vac1, &vt1, sizeof(vac1)); 03065 oldcodec1 = codec1; 03066 } 03067 if ((inaddrcmp(&t0, &ac0)) || 03068 (vp0 && inaddrcmp(&vt0, &vac0)) || 03069 (codec0 != oldcodec0)) { 03070 if (option_debug > 1) { 03071 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03072 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 03073 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 03074 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 03075 } 03076 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))) 03077 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 03078 memcpy(&ac0, &t0, sizeof(ac0)); 03079 memcpy(&vac0, &vt0, sizeof(vac0)); 03080 oldcodec0 = codec0; 03081 } 03082 03083 /* Wait for frame to come in on the channels */ 03084 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03085 if (!timeoutms) { 03086 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03087 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03088 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03089 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03090 return AST_BRIDGE_RETRY; 03091 } 03092 if (option_debug) 03093 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 03094 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03095 break; 03096 continue; 03097 } 03098 fr = ast_read(who); 03099 other = (who == c0) ? c1 : c0; 03100 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03101 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 03102 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 03103 /* Break out of bridge */ 03104 *fo = fr; 03105 *rc = who; 03106 if (option_debug) 03107 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03108 if (c0->tech_pvt == pvt0) 03109 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03110 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03111 if (c1->tech_pvt == pvt1) 03112 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03113 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03114 return AST_BRIDGE_COMPLETE; 03115 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03116 if ((fr->subclass == AST_CONTROL_HOLD) || 03117 (fr->subclass == AST_CONTROL_UNHOLD) || 03118 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03119 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03120 if (fr->subclass == AST_CONTROL_HOLD) { 03121 /* If we someone went on hold we want the other side to reinvite back to us */ 03122 if (who == c0) 03123 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 03124 else 03125 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 03126 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03127 /* If they went off hold they should go back to being direct */ 03128 if (who == c0) 03129 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 03130 else 03131 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 03132 } 03133 /* Update local address information */ 03134 ast_rtp_get_peer(p0, &t0); 03135 memcpy(&ac0, &t0, sizeof(ac0)); 03136 ast_rtp_get_peer(p1, &t1); 03137 memcpy(&ac1, &t1, sizeof(ac1)); 03138 /* Update codec information */ 03139 if (pr0->get_codec && c0->tech_pvt) 03140 oldcodec0 = codec0 = pr0->get_codec(c0); 03141 if (pr1->get_codec && c1->tech_pvt) 03142 oldcodec1 = codec1 = pr1->get_codec(c1); 03143 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03144 ast_frfree(fr); 03145 } else { 03146 *fo = fr; 03147 *rc = who; 03148 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03149 return AST_BRIDGE_COMPLETE; 03150 } 03151 } else { 03152 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03153 (fr->frametype == AST_FRAME_DTMF_END) || 03154 (fr->frametype == AST_FRAME_VOICE) || 03155 (fr->frametype == AST_FRAME_VIDEO) || 03156 (fr->frametype == AST_FRAME_IMAGE) || 03157 (fr->frametype == AST_FRAME_HTML) || 03158 (fr->frametype == AST_FRAME_MODEM) || 03159 (fr->frametype == AST_FRAME_TEXT)) { 03160 ast_write(other, fr); 03161 } 03162 ast_frfree(fr); 03163 } 03164 /* Swap priority */ 03165 cs[2] = cs[0]; 03166 cs[0] = cs[1]; 03167 cs[1] = cs[2]; 03168 } 03169 03170 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03171 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03172 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03173 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03174 03175 return AST_BRIDGE_FAILED; 03176 }
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 3274 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().
03275 { 03276 struct ast_frame *fr = NULL; 03277 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03278 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03279 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03280 int p0_callback = 0, p1_callback = 0; 03281 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03282 03283 /* Okay, setup each RTP structure to do P2P forwarding */ 03284 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03285 p2p_set_bridge(p0, p1); 03286 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03287 p2p_set_bridge(p1, p0); 03288 03289 /* Activate callback modes if possible */ 03290 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03291 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03292 03293 /* Now let go of the channel locks and be on our way */ 03294 ast_channel_unlock(c0); 03295 ast_channel_unlock(c1); 03296 03297 /* Go into a loop forwarding frames until we don't need to anymore */ 03298 cs[0] = c0; 03299 cs[1] = c1; 03300 cs[2] = NULL; 03301 for (;;) { 03302 /* If the underlying formats have changed force this bridge to break */ 03303 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 03304 ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n"); 03305 res = AST_BRIDGE_FAILED_NOWARN; 03306 break; 03307 } 03308 /* Check if anything changed */ 03309 if ((c0->tech_pvt != pvt0) || 03310 (c1->tech_pvt != pvt1) || 03311 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03312 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03313 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03314 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03315 ast_frfree(fr); 03316 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03317 ast_frfree(fr); 03318 res = AST_BRIDGE_RETRY; 03319 break; 03320 } 03321 /* Wait on a channel to feed us a frame */ 03322 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03323 if (!timeoutms) { 03324 res = AST_BRIDGE_RETRY; 03325 break; 03326 } 03327 if (option_debug) 03328 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03329 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03330 break; 03331 continue; 03332 } 03333 /* Read in frame from channel */ 03334 fr = ast_read(who); 03335 other = (who == c0) ? c1 : c0; 03336 /* Dependong on the frame we may need to break out of our bridge */ 03337 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03338 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03339 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03340 /* Record received frame and who */ 03341 *fo = fr; 03342 *rc = who; 03343 if (option_debug) 03344 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03345 res = AST_BRIDGE_COMPLETE; 03346 break; 03347 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03348 if ((fr->subclass == AST_CONTROL_HOLD) || 03349 (fr->subclass == AST_CONTROL_UNHOLD) || 03350 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03351 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03352 /* If we are going on hold, then break callback mode and P2P bridging */ 03353 if (fr->subclass == AST_CONTROL_HOLD) { 03354 if (p0_callback) 03355 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03356 if (p1_callback) 03357 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03358 p2p_set_bridge(p0, NULL); 03359 p2p_set_bridge(p1, NULL); 03360 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03361 /* If we are off hold, then go back to callback mode and P2P bridging */ 03362 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03363 p2p_set_bridge(p0, p1); 03364 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03365 p2p_set_bridge(p1, p0); 03366 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03367 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03368 } 03369 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03370 ast_frfree(fr); 03371 } else { 03372 *fo = fr; 03373 *rc = who; 03374 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03375 res = AST_BRIDGE_COMPLETE; 03376 break; 03377 } 03378 } else { 03379 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03380 (fr->frametype == AST_FRAME_DTMF_END) || 03381 (fr->frametype == AST_FRAME_VOICE) || 03382 (fr->frametype == AST_FRAME_VIDEO) || 03383 (fr->frametype == AST_FRAME_IMAGE) || 03384 (fr->frametype == AST_FRAME_HTML) || 03385 (fr->frametype == AST_FRAME_MODEM) || 03386 (fr->frametype == AST_FRAME_TEXT)) { 03387 ast_write(other, fr); 03388 } 03389 03390 ast_frfree(fr); 03391 } 03392 /* Swap priority */ 03393 cs[2] = cs[0]; 03394 cs[0] = cs[1]; 03395 cs[1] = cs[2]; 03396 } 03397 03398 /* If we are totally avoiding the core, then restore our link to it */ 03399 if (p0_callback) 03400 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03401 if (p1_callback) 03402 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03403 03404 /* Break out of the direct bridge */ 03405 p2p_set_bridge(p0, NULL); 03406 p2p_set_bridge(p1, NULL); 03407 03408 return res; 03409 }
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 1106 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().
01107 { 01108 int res = 0, payload = 0, bridged_payload = 0, mark; 01109 struct rtpPayloadType rtpPT; 01110 int reconstruct = ntohl(rtpheader[0]); 01111 01112 /* Get fields from packet */ 01113 payload = (reconstruct & 0x7f0000) >> 16; 01114 mark = (((reconstruct & 0x800000) >> 23) != 0); 01115 01116 /* Check what the payload value should be */ 01117 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01118 01119 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01120 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01121 return -1; 01122 01123 /* Otherwise adjust bridged payload to match */ 01124 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01125 01126 /* 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 */ 01127 if (!bridged->current_RTP_PT[bridged_payload].code) 01128 return -1; 01129 01130 01131 /* If the mark bit has not been sent yet... do it now */ 01132 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01133 mark = 1; 01134 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01135 } 01136 01137 /* Reconstruct part of the packet */ 01138 reconstruct &= 0xFF80FFFF; 01139 reconstruct |= (bridged_payload << 16); 01140 reconstruct |= (mark << 23); 01141 rtpheader[0] = htonl(reconstruct); 01142 01143 /* Send the packet back out */ 01144 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01145 if (res < 0) { 01146 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01147 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)); 01148 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01149 if (option_debug || rtpdebug) 01150 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)); 01151 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01152 } 01153 return 0; 01154 } else if (rtp_debug_test_addr(&bridged->them)) 01155 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); 01156 01157 return 0; 01158 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1063 of file rtp.c.
References ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtp::rxtransit, sanitize_tv(), ast_rtp::seedrxts, and ast_frame::subclass.
Referenced by ast_rtp_read(), and schedule_delivery().
01064 { 01065 struct timeval now; 01066 double transit; 01067 double current_time; 01068 double d; 01069 double dtv; 01070 double prog; 01071 int rate = rtp_get_rate(rtp->f.subclass); 01072 01073 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01074 gettimeofday(&rtp->rxcore, NULL); 01075 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01076 /* map timestamp to a real time */ 01077 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01078 rtp->rxcore.tv_sec -= timestamp / rate; 01079 rtp->rxcore.tv_usec -= (timestamp % rate) * 125; 01080 /* Round to 0.1ms for nice, pretty timestamps */ 01081 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01082 sanitize_tv(&rtp->rxcore); 01083 } 01084 01085 gettimeofday(&now,NULL); 01086 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01087 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / rate; 01088 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % rate) * 125; 01089 sanitize_tv(tv); 01090 prog = (double)((timestamp-rtp->seedrxts)/(float)(rate)); 01091 dtv = (double)rtp->drxcore + (double)(prog); 01092 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01093 transit = current_time - dtv; 01094 d = transit - rtp->rxtransit; 01095 rtp->rxtransit = transit; 01096 if (d<0) 01097 d=-d; 01098 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01099 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01100 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01101 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01102 rtp->rtcp->minrxjitter = rtp->rxjitter; 01103 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2260 of file rtp.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), t, and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02261 { 02262 struct timeval t; 02263 long ms; 02264 if (ast_tvzero(rtp->txcore)) { 02265 rtp->txcore = ast_tvnow(); 02266 /* Round to 20ms for nice, pretty timestamps */ 02267 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02268 } 02269 /* Use previous txcore if available */ 02270 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02271 ms = ast_tvdiff_ms(t, rtp->txcore); 02272 if (ms < 0) 02273 ms = 0; 02274 /* Use what we just got for next time */ 02275 rtp->txcore = t; 02276 return (unsigned int) ms; 02277 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 1532 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_rtp_protocol::list, 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().
01533 { 01534 struct ast_rtp_protocol *cur = NULL; 01535 01536 AST_LIST_LOCK(&protos); 01537 AST_LIST_TRAVERSE(&protos, cur, list) { 01538 if (cur->type == chan->tech->type) 01539 break; 01540 } 01541 AST_LIST_UNLOCK(&protos); 01542 01543 return cur; 01544 }
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 3245 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.
03246 { 03247 ast_channel_lock(chan); 03248 03249 /* Remove the callback from the IO context */ 03250 ast_io_remove(rtp->io, iod[0]); 03251 03252 /* Restore file descriptors */ 03253 chan->fds[0] = fds[0]; 03254 ast_channel_unlock(chan); 03255 03256 /* Restore callback mode if previously used */ 03257 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03258 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03259 03260 return 0; 03261 }
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 3264 of file rtp.c.
References ast_mutex_lock, ast_mutex_unlock, ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03265 { 03266 ast_mutex_lock(&rtp0->bridge_lock); 03267 rtp0->bridged = rtp1; 03268 ast_mutex_unlock(&rtp0->bridge_lock); 03269 03270 return; 03271 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 677 of file rtp.c.
References AST_FRAME_DTMF_END, ast_log(), ast_rtp::dtmf_timeout, f, LOG_DEBUG, option_debug, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00678 { 00679 unsigned int event; 00680 char resp = 0; 00681 struct ast_frame *f = NULL; 00682 event = ntohl(*((unsigned int *)(data))); 00683 event &= 0x001F; 00684 if (option_debug > 2 || rtpdebug) 00685 ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len); 00686 if (event < 10) { 00687 resp = '0' + event; 00688 } else if (event < 11) { 00689 resp = '*'; 00690 } else if (event < 12) { 00691 resp = '#'; 00692 } else if (event < 16) { 00693 resp = 'A' + (event - 12); 00694 } else if (event < 17) { 00695 resp = 'X'; 00696 } 00697 if (rtp->resp && (rtp->resp != resp)) { 00698 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00699 } 00700 rtp->resp = resp; 00701 rtp->dtmf_timeout = 0; 00702 return f; 00703 }
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 716 of file rtp.c.
References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_null_frame, ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, f, FLAG_DTMF_COMPENSATE, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_get_rate(), ast_frame::samples, and send_dtmf().
Referenced by ast_rtp_read().
00717 { 00718 unsigned int event; 00719 unsigned int event_end; 00720 unsigned int samples; 00721 char resp = 0; 00722 struct ast_frame *f = NULL; 00723 00724 /* Figure out event, event end, and samples */ 00725 event = ntohl(*((unsigned int *)(data))); 00726 event >>= 24; 00727 event_end = ntohl(*((unsigned int *)(data))); 00728 event_end <<= 8; 00729 event_end >>= 24; 00730 samples = ntohl(*((unsigned int *)(data))); 00731 samples &= 0xFFFF; 00732 00733 /* Print out debug if turned on */ 00734 if (rtpdebug || option_debug > 2) 00735 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00736 00737 /* Figure out what digit was pressed */ 00738 if (event < 10) { 00739 resp = '0' + event; 00740 } else if (event < 11) { 00741 resp = '*'; 00742 } else if (event < 12) { 00743 resp = '#'; 00744 } else if (event < 16) { 00745 resp = 'A' + (event - 12); 00746 } else if (event < 17) { /* Event 16: Hook flash */ 00747 resp = 'X'; 00748 } else { 00749 /* Not a supported event */ 00750 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 00751 return &ast_null_frame; 00752 } 00753 00754 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00755 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 00756 rtp->resp = resp; 00757 rtp->dtmf_timeout = 0; 00758 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00759 f->len = 0; 00760 rtp->lastevent = timestamp; 00761 } 00762 } else { 00763 /* The duration parameter measures the complete 00764 duration of the event (from the beginning) - RFC2833. 00765 Account for the fact that duration is only 16 bits long 00766 (about 8 seconds at 8000 Hz) and can wrap if digit 00767 is held for too long. */ 00768 unsigned int new_duration = rtp->dtmf_duration; 00769 unsigned int last_duration = new_duration & 0xFFFF; 00770 00771 if (last_duration > 64000 && samples < last_duration) 00772 new_duration += 0xFFFF + 1; 00773 new_duration = (new_duration & ~0xFFFF) | samples; 00774 00775 if (event_end & 0x80) { 00776 /* End event */ 00777 if ((rtp->lastevent != seqno) && rtp->resp) { 00778 rtp->dtmf_duration = new_duration; 00779 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00780 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 00781 rtp->resp = 0; 00782 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 00783 } 00784 } else { 00785 /* Begin/continuation */ 00786 00787 if (rtp->resp && rtp->resp != resp) { 00788 /* Another digit already began. End it */ 00789 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00790 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 00791 rtp->resp = 0; 00792 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 00793 } 00794 00795 00796 if (rtp->resp) { 00797 /* Digit continues */ 00798 rtp->dtmf_duration = new_duration; 00799 } else { 00800 /* New digit began */ 00801 rtp->resp = resp; 00802 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00803 rtp->dtmf_duration = samples; 00804 } 00805 00806 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout; 00807 } 00808 00809 rtp->lastevent = seqno; 00810 } 00811 00812 return f; 00813 }
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 821 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().
00822 { 00823 struct ast_frame *f = NULL; 00824 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00825 totally help us out becuase we don't have an engine to keep it going and we are not 00826 guaranteed to have it every 20ms or anything */ 00827 if (rtpdebug) 00828 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00829 00830 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00831 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00832 ast_inet_ntoa(rtp->them.sin_addr)); 00833 ast_set_flag(rtp, FLAG_3389_WARNING); 00834 } 00835 00836 /* Must have at least one byte */ 00837 if (!len) 00838 return NULL; 00839 if (len < 24) { 00840 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00841 rtp->f.datalen = len - 1; 00842 rtp->f.offset = AST_FRIENDLY_OFFSET; 00843 memcpy(rtp->f.data, data + 1, len - 1); 00844 } else { 00845 rtp->f.data = NULL; 00846 rtp->f.offset = 0; 00847 rtp->f.datalen = 0; 00848 } 00849 rtp->f.frametype = AST_FRAME_CNG; 00850 rtp->f.subclass = data[0] & 0x7f; 00851 rtp->f.samples = 0; 00852 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00853 f = &rtp->f; 00854 return f; 00855 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 663 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00664 { 00665 if (rtcpdebug == 0) 00666 return 0; 00667 if (rtcpdebugaddr.sin_addr.s_addr) { 00668 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00669 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00670 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00671 return 0; 00672 } 00673 return 1; 00674 }
static int rtcp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3684 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip().
03684 { 03685 if (argc != 2) { 03686 if (argc != 4) 03687 return RESULT_SHOWUSAGE; 03688 return rtcp_do_debug_ip(fd, argc, argv); 03689 } 03690 rtcpdebug = 1; 03691 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03692 ast_cli(fd, "RTCP Debugging Enabled\n"); 03693 return RESULT_SUCCESS; 03694 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3672 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip_deprecated().
03672 { 03673 if (argc != 3) { 03674 if (argc != 5) 03675 return RESULT_SHOWUSAGE; 03676 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03677 } 03678 rtcpdebug = 1; 03679 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03680 ast_cli(fd, "RTCP Debugging Enabled\n"); 03681 return RESULT_SUCCESS; 03682 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3629 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtcp_do_debug().
03630 { 03631 struct hostent *hp; 03632 struct ast_hostent ahp; 03633 int port = 0; 03634 char *p, *arg; 03635 if (argc != 4) 03636 return RESULT_SHOWUSAGE; 03637 03638 arg = argv[3]; 03639 p = strstr(arg, ":"); 03640 if (p) { 03641 *p = '\0'; 03642 p++; 03643 port = atoi(p); 03644 } 03645 hp = ast_gethostbyname(arg, &ahp); 03646 if (hp == NULL) 03647 return RESULT_SHOWUSAGE; 03648 rtcpdebugaddr.sin_family = AF_INET; 03649 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03650 rtcpdebugaddr.sin_port = htons(port); 03651 if (port == 0) 03652 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03653 else 03654 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03655 rtcpdebug = 1; 03656 return RESULT_SUCCESS; 03657 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3599 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().
03600 { 03601 struct hostent *hp; 03602 struct ast_hostent ahp; 03603 int port = 0; 03604 char *p, *arg; 03605 if (argc != 5) 03606 return RESULT_SHOWUSAGE; 03607 03608 arg = argv[4]; 03609 p = strstr(arg, ":"); 03610 if (p) { 03611 *p = '\0'; 03612 p++; 03613 port = atoi(p); 03614 } 03615 hp = ast_gethostbyname(arg, &ahp); 03616 if (hp == NULL) 03617 return RESULT_SHOWUSAGE; 03618 rtcpdebugaddr.sin_family = AF_INET; 03619 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03620 rtcpdebugaddr.sin_port = htons(port); 03621 if (port == 0) 03622 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03623 else 03624 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03625 rtcpdebug = 1; 03626 return RESULT_SUCCESS; 03627 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3705 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03705 { 03706 if (argc != 2) { 03707 return RESULT_SHOWUSAGE; 03708 } 03709 rtcpstats = 1; 03710 ast_cli(fd, "RTCP Stats Enabled\n"); 03711 return RESULT_SUCCESS; 03712 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3696 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03696 { 03697 if (argc != 3) { 03698 return RESULT_SHOWUSAGE; 03699 } 03700 rtcpstats = 1; 03701 ast_cli(fd, "RTCP Stats Enabled\n"); 03702 return RESULT_SUCCESS; 03703 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3732 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03733 { 03734 if (argc != 3) 03735 return RESULT_SHOWUSAGE; 03736 rtcpdebug = 0; 03737 ast_cli(fd,"RTCP Debugging Disabled\n"); 03738 return RESULT_SUCCESS; 03739 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3723 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03724 { 03725 if (argc != 4) 03726 return RESULT_SHOWUSAGE; 03727 rtcpdebug = 0; 03728 ast_cli(fd,"RTCP Debugging Disabled\n"); 03729 return RESULT_SUCCESS; 03730 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3750 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03751 { 03752 if (argc != 3) 03753 return RESULT_SHOWUSAGE; 03754 rtcpstats = 0; 03755 ast_cli(fd,"RTCP Stats Disabled\n"); 03756 return RESULT_SUCCESS; 03757 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3741 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03742 { 03743 if (argc != 4) 03744 return RESULT_SHOWUSAGE; 03745 rtcpstats = 0; 03746 ast_cli(fd,"RTCP Stats Disabled\n"); 03747 return RESULT_SUCCESS; 03748 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 650 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().
00651 { 00652 if (rtpdebug == 0) 00653 return 0; 00654 if (rtpdebugaddr.sin_addr.s_addr) { 00655 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00656 && (rtpdebugaddr.sin_port != addr->sin_port)) 00657 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00658 return 0; 00659 } 00660 return 1; 00661 }
static int rtp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3659 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtp_do_debug_ip().
03660 { 03661 if (argc != 2) { 03662 if (argc != 4) 03663 return RESULT_SHOWUSAGE; 03664 return rtp_do_debug_ip(fd, argc, argv); 03665 } 03666 rtpdebug = 1; 03667 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03668 ast_cli(fd, "RTP Debugging Enabled\n"); 03669 return RESULT_SUCCESS; 03670 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3569 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtp_do_debug().
03570 { 03571 struct hostent *hp; 03572 struct ast_hostent ahp; 03573 int port = 0; 03574 char *p, *arg; 03575 03576 if (argc != 4) 03577 return RESULT_SHOWUSAGE; 03578 arg = argv[3]; 03579 p = strstr(arg, ":"); 03580 if (p) { 03581 *p = '\0'; 03582 p++; 03583 port = atoi(p); 03584 } 03585 hp = ast_gethostbyname(arg, &ahp); 03586 if (hp == NULL) 03587 return RESULT_SHOWUSAGE; 03588 rtpdebugaddr.sin_family = AF_INET; 03589 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03590 rtpdebugaddr.sin_port = htons(port); 03591 if (port == 0) 03592 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03593 else 03594 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03595 rtpdebug = 1; 03596 return RESULT_SUCCESS; 03597 }
static int rtp_get_rate | ( | int | subclass | ) | [static] |
Definition at line 528 of file rtp.c.
References AST_FORMAT_G722, and ast_format_rate().
Referenced by ast_rtp_raw_write(), ast_rtp_read(), calc_rxstamp(), and process_rfc2833().
00529 { 00530 return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass); 00531 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3714 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03715 { 03716 if (argc != 3) 03717 return RESULT_SHOWUSAGE; 03718 rtpdebug = 0; 03719 ast_cli(fd,"RTP Debugging Disabled\n"); 03720 return RESULT_SUCCESS; 03721 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1907 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01908 { 01909 int s; 01910 long flags; 01911 s = socket(AF_INET, SOCK_DGRAM, 0); 01912 if (s > -1) { 01913 flags = fcntl(s, F_GETFL); 01914 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01915 #ifdef SO_NO_CHECK 01916 if (nochecksums) 01917 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01918 #endif 01919 } 01920 return s; 01921 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 857 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and f.
Referenced by p2p_callback_disable().
00858 { 00859 struct ast_rtp *rtp = cbdata; 00860 struct ast_frame *f; 00861 f = ast_rtp_read(rtp); 00862 if (f) { 00863 if (rtp->callback) 00864 rtp->callback(rtp, f, rtp->data); 00865 } 00866 return 1; 00867 }
static void sanitize_tv | ( | struct timeval * | tv | ) | [static] |
static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static] |
Definition at line 624 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_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, 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 ast_rtp_read(), process_cisco_dtmf(), and process_rfc2833().
00625 { 00626 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00627 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00628 if (option_debug) 00629 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00630 rtp->resp = 0; 00631 return &ast_null_frame; 00632 } 00633 if (option_debug) 00634 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00635 if (rtp->resp == 'X') { 00636 rtp->f.frametype = AST_FRAME_CONTROL; 00637 rtp->f.subclass = AST_CONTROL_FLASH; 00638 } else { 00639 rtp->f.frametype = type; 00640 rtp->f.subclass = rtp->resp; 00641 } 00642 rtp->f.datalen = 0; 00643 rtp->f.samples = 0; 00644 rtp->f.mallocd = 0; 00645 rtp->f.src = "RTP"; 00646 return &rtp->f; 00647 00648 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
Definition at line 303 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().
00304 { 00305 switch(msg) { 00306 case STUN_MAPPED_ADDRESS: 00307 return "Mapped Address"; 00308 case STUN_RESPONSE_ADDRESS: 00309 return "Response Address"; 00310 case STUN_CHANGE_REQUEST: 00311 return "Change Request"; 00312 case STUN_SOURCE_ADDRESS: 00313 return "Source Address"; 00314 case STUN_CHANGED_ADDRESS: 00315 return "Changed Address"; 00316 case STUN_USERNAME: 00317 return "Username"; 00318 case STUN_PASSWORD: 00319 return "Password"; 00320 case STUN_MESSAGE_INTEGRITY: 00321 return "Message Integrity"; 00322 case STUN_ERROR_CODE: 00323 return "Error Code"; 00324 case STUN_UNKNOWN_ATTRIBUTES: 00325 return "Unknown Attributes"; 00326 case STUN_REFLECTED_FROM: 00327 return "Reflected From"; 00328 } 00329 return "Non-RFC3489 Attribute"; 00330 }
static int stun_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3759 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03760 { 03761 if (argc != 2) { 03762 return RESULT_SHOWUSAGE; 03763 } 03764 stundebug = 1; 03765 ast_cli(fd, "STUN Debugging Enabled\n"); 03766 return RESULT_SUCCESS; 03767 }
static int stun_handle_packet | ( | int | s, | |
struct sockaddr_in * | src, | |||
unsigned char * | data, | |||
size_t | len | |||
) | [static] |
Definition at line 427 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().
00428 { 00429 struct stun_header *resp, *hdr = (struct stun_header *)data; 00430 struct stun_attr *attr; 00431 struct stun_state st; 00432 int ret = STUN_IGNORE; 00433 unsigned char respdata[1024]; 00434 int resplen, respleft; 00435 00436 if (len < sizeof(struct stun_header)) { 00437 if (option_debug) 00438 ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header)); 00439 return -1; 00440 } 00441 if (stundebug) 00442 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen)); 00443 if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) { 00444 if (option_debug) 00445 ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header)); 00446 } else 00447 len = ntohs(hdr->msglen); 00448 data += sizeof(struct stun_header); 00449 memset(&st, 0, sizeof(st)); 00450 while(len) { 00451 if (len < sizeof(struct stun_attr)) { 00452 if (option_debug) 00453 ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr)); 00454 break; 00455 } 00456 attr = (struct stun_attr *)data; 00457 if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) { 00458 if (option_debug) 00459 ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len); 00460 break; 00461 } 00462 if (stun_process_attr(&st, attr)) { 00463 if (option_debug) 00464 ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00465 break; 00466 } 00467 /* Clear attribute in case previous entry was a string */ 00468 attr->attr = 0; 00469 data += ntohs(attr->len) + sizeof(struct stun_attr); 00470 len -= ntohs(attr->len) + sizeof(struct stun_attr); 00471 } 00472 /* Null terminate any string */ 00473 *data = '\0'; 00474 resp = (struct stun_header *)respdata; 00475 resplen = 0; 00476 respleft = sizeof(respdata) - sizeof(struct stun_header); 00477 resp->id = hdr->id; 00478 resp->msgtype = 0; 00479 resp->msglen = 0; 00480 attr = (struct stun_attr *)resp->ies; 00481 if (!len) { 00482 switch(ntohs(hdr->msgtype)) { 00483 case STUN_BINDREQ: 00484 if (stundebug) 00485 ast_verbose("STUN Bind Request, username: %s\n", 00486 st.username ? st.username : "<none>"); 00487 if (st.username) 00488 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00489 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00490 resp->msglen = htons(resplen); 00491 resp->msgtype = htons(STUN_BINDRESP); 00492 stun_send(s, src, resp); 00493 ret = STUN_ACCEPT; 00494 break; 00495 default: 00496 if (stundebug) 00497 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00498 } 00499 } 00500 return ret; 00501 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
Definition at line 284 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00285 { 00286 switch(msg) { 00287 case STUN_BINDREQ: 00288 return "Binding Request"; 00289 case STUN_BINDRESP: 00290 return "Binding Response"; 00291 case STUN_BINDERR: 00292 return "Binding Error Response"; 00293 case STUN_SECREQ: 00294 return "Shared Secret Request"; 00295 case STUN_SECRESP: 00296 return "Shared Secret Response"; 00297 case STUN_SECERR: 00298 return "Shared Secret Error Response"; 00299 } 00300 return "Non-RFC3489 Message"; 00301 }
static int stun_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3769 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03770 { 03771 if (argc != 3) 03772 return RESULT_SHOWUSAGE; 03773 stundebug = 0; 03774 ast_cli(fd, "STUN Debugging Disabled\n"); 03775 return RESULT_SUCCESS; 03776 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 337 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().
00338 { 00339 if (stundebug) 00340 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00341 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00342 switch(ntohs(attr->attr)) { 00343 case STUN_USERNAME: 00344 state->username = (const char *) (attr->value); 00345 break; 00346 case STUN_PASSWORD: 00347 state->password = (const char *) (attr->value); 00348 break; 00349 default: 00350 if (stundebug) 00351 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00352 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00353 } 00354 return 0; 00355 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
Definition at line 394 of file rtp.c.
References ast_random(), stun_trans_id::id, and stun_header::id.
Referenced by ast_rtp_stun_request().
00395 { 00396 int x; 00397 for (x=0;x<4;x++) 00398 req->id.id[x] = ast_random(); 00399 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
Definition at line 388 of file rtp.c.
References stun_header::msglen.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00389 { 00390 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00391 (struct sockaddr *)dst, sizeof(*dst)); 00392 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 506 of file rtp.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00507 { 00508 unsigned int sec, usec, frac; 00509 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00510 usec = tv.tv_usec; 00511 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00512 *msw = sec; 00513 *lsw = frac; 00514 }
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 rtpPayloadType payloadType |
Definition at line 1403 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 1438 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 1404 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), ast_call_forward(), ast_format_str_reduce(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), find_subscription_type(), g723_len(), get_sdp_line(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), parse_information(), parse_setup(), process_sdp(), sla_load_config(), subscription_type2str(), and yyparse().