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