#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 | frame_list |
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. | |
void | ast_rtp_change_source (struct ast_rtp *rtp) |
Indicate that we need to set the marker bit and change the ssrc. | |
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) |
Indicate that we need to set the marker bit. | |
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) |
int | ast_rtp_senddigit_end_with_duration (struct ast_rtp *rtp, char digit, unsigned int duration) |
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_frame * | create_dtmf_frame (struct ast_rtp *rtp, enum ast_frame_type type) |
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 void | process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct frame_list *frames) |
Process RTP DTMF and events according to RFC 2833. | |
static struct ast_frame * | process_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len) |
Process Comfort Noise RTP. | |
static int | rtcp_debug_test_addr (struct sockaddr_in *addr) |
static int | rtcp_do_debug (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_ip (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_ip_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_do_stats (int fd, int argc, char *argv[]) |
static int | rtcp_do_stats_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_no_debug (int fd, int argc, char *argv[]) |
static int | rtcp_no_debug_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_no_stats (int fd, int argc, char *argv[]) |
static int | rtcp_no_stats_deprecated (int fd, int argc, char *argv[]) |
static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
static int | rtp_do_debug (int fd, int argc, char *argv[]) |
static int | rtp_do_debug_ip (int fd, int argc, char *argv[]) |
static int | rtp_get_rate (int subclass) |
static int | rtp_no_debug (int fd, int argc, char *argv[]) |
static int | rtp_socket (void) |
static int | rtpread (int *id, int fd, short events, void *cbdata) |
static void | sanitize_tv (struct timeval *tv) |
static 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 199 of file rtp.c.
Referenced by ast_rtp_setdtmfcompensate(), create_dtmf_frame(), and process_rfc2833().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 195 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 192 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 193 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 194 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 196 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 267 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 279 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 372 of file rtp.c.
References stun_addr::addr.
Referenced by stun_handle_packet().
00373 { 00374 int size = sizeof(**attr) + 8; 00375 struct stun_addr *addr; 00376 if (*left > size) { 00377 (*attr)->attr = htons(attrval); 00378 (*attr)->len = htons(8); 00379 addr = (struct stun_addr *)((*attr)->value); 00380 addr->unused = 0; 00381 addr->family = 0x01; 00382 addr->port = sin->sin_port; 00383 addr->addr = sin->sin_addr.s_addr; 00384 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00385 *len += size; 00386 *left -= size; 00387 } 00388 }
static void append_attr_string | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
const char * | s, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 359 of file rtp.c.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00360 { 00361 int size = sizeof(**attr) + strlen(s); 00362 if (*left > size) { 00363 (*attr)->attr = htons(attrval); 00364 (*attr)->len = htons(strlen(s)); 00365 memcpy((*attr)->value, s, strlen(s)); 00366 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00367 *len += size; 00368 *left -= size; 00369 } 00370 }
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 535 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00536 { 00537 unsigned int interval; 00538 /*! \todo XXX Do a more reasonable calculation on this one 00539 * Look in RFC 3550 Section A.7 for an example*/ 00540 interval = rtcpinterval; 00541 return interval; 00542 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 523 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 1979 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().
01980 { 01981 struct ast_rtcp *rtcp; 01982 01983 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01984 return NULL; 01985 rtcp->s = rtp_socket(); 01986 if (option_debug > 3) 01987 ast_log(LOG_DEBUG, "socket RTPaux (RTCP) fd: %i\n", rtcp->s); 01988 rtcp->us.sin_family = AF_INET; 01989 rtcp->them.sin_family = AF_INET; 01990 rtcp->schedid = -1; 01991 01992 if (rtcp->s < 0) { 01993 free(rtcp); 01994 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01995 return NULL; 01996 } 01997 01998 return rtcp; 01999 }
Definition at line 887 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().
00888 { 00889 socklen_t len; 00890 int position, i, packetwords; 00891 int res; 00892 struct sockaddr_in sin; 00893 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00894 unsigned int *rtcpheader; 00895 int pt; 00896 struct timeval now; 00897 unsigned int length; 00898 int rc; 00899 double rttsec; 00900 uint64_t rtt = 0; 00901 unsigned int dlsr; 00902 unsigned int lsr; 00903 unsigned int msw; 00904 unsigned int lsw; 00905 unsigned int comp; 00906 struct ast_frame *f = &ast_null_frame; 00907 00908 if (!rtp || !rtp->rtcp) 00909 return &ast_null_frame; 00910 00911 len = sizeof(sin); 00912 00913 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00914 0, (struct sockaddr *)&sin, &len); 00915 if (option_debug > 2) 00916 ast_log(LOG_DEBUG, "socket RTCP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 00917 00918 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00919 00920 if (res < 0) { 00921 ast_assert(errno != EBADF); 00922 if (errno != EAGAIN) { 00923 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00924 ast_log(LOG_WARNING, "socket RTCP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 00925 return NULL; 00926 } 00927 return &ast_null_frame; 00928 } 00929 00930 packetwords = res / 4; 00931 00932 if (rtp->nat) { 00933 /* Send to whoever sent to us */ 00934 if (((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00935 (rtp->rtcp->them.sin_port != sin.sin_port)) && 00936 ((rtp->rtcp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) || 00937 (rtp->rtcp->altthem.sin_port != sin.sin_port))) { 00938 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00939 if (option_debug || rtpdebug) 00940 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)); 00941 } 00942 } 00943 00944 if (option_debug) 00945 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00946 00947 /* Process a compound packet */ 00948 position = 0; 00949 while (position < packetwords) { 00950 i = position; 00951 length = ntohl(rtcpheader[i]); 00952 pt = (length & 0xff0000) >> 16; 00953 rc = (length & 0x1f000000) >> 24; 00954 length &= 0xffff; 00955 00956 if ((i + length) > packetwords) { 00957 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00958 return &ast_null_frame; 00959 } 00960 00961 if (rtcp_debug_test_addr(&sin)) { 00962 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00963 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00964 ast_verbose("Reception reports: %d\n", rc); 00965 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00966 } 00967 00968 i += 2; /* Advance past header and ssrc */ 00969 if (rc == 0 && pt == RTCP_PT_RR) { /* We're receiving a receiver report with no reports, which is ok */ 00970 position += (length + 1); 00971 continue; 00972 } 00973 00974 switch (pt) { 00975 case RTCP_PT_SR: 00976 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00977 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00978 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00979 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00980 00981 if (rtcp_debug_test_addr(&sin)) { 00982 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00983 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00984 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00985 } 00986 i += 5; 00987 if (rc < 1) 00988 break; 00989 /* Intentional fall through */ 00990 case RTCP_PT_RR: 00991 /* Don't handle multiple reception reports (rc > 1) yet */ 00992 /* Calculate RTT per RFC */ 00993 gettimeofday(&now, NULL); 00994 timeval2ntp(now, &msw, &lsw); 00995 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00996 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00997 lsr = ntohl(rtcpheader[i + 4]); 00998 dlsr = ntohl(rtcpheader[i + 5]); 00999 rtt = comp - lsr - dlsr; 01000 01001 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 01002 sess->ee_delay = (eedelay * 1000) / 65536; */ 01003 if (rtt < 4294) { 01004 rtt = (rtt * 1000000) >> 16; 01005 } else { 01006 rtt = (rtt * 1000) >> 16; 01007 rtt *= 1000; 01008 } 01009 rtt = rtt / 1000.; 01010 rttsec = rtt / 1000.; 01011 01012 if (comp - dlsr >= lsr) { 01013 rtp->rtcp->accumulated_transit += rttsec; 01014 rtp->rtcp->rtt = rttsec; 01015 if (rtp->rtcp->maxrtt<rttsec) 01016 rtp->rtcp->maxrtt = rttsec; 01017 if (rtp->rtcp->minrtt>rttsec) 01018 rtp->rtcp->minrtt = rttsec; 01019 } else if (rtcp_debug_test_addr(&sin)) { 01020 ast_verbose("Internal RTCP NTP clock skew detected: " 01021 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 01022 "diff=%d\n", 01023 lsr, comp, dlsr, dlsr / 65536, 01024 (dlsr % 65536) * 1000 / 65536, 01025 dlsr - (comp - lsr)); 01026 } 01027 } 01028 01029 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 01030 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 01031 if (rtcp_debug_test_addr(&sin)) { 01032 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 01033 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 01034 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 01035 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 01036 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 01037 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 01038 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 01039 if (rtt) 01040 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 01041 } 01042 break; 01043 case RTCP_PT_FUR: 01044 if (rtcp_debug_test_addr(&sin)) 01045 ast_verbose("Received an RTCP Fast Update Request\n"); 01046 rtp->f.frametype = AST_FRAME_CONTROL; 01047 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 01048 rtp->f.datalen = 0; 01049 rtp->f.samples = 0; 01050 rtp->f.mallocd = 0; 01051 rtp->f.src = "RTP"; 01052 f = &rtp->f; 01053 break; 01054 case RTCP_PT_SDES: 01055 if (rtcp_debug_test_addr(&sin)) 01056 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01057 break; 01058 case RTCP_PT_BYE: 01059 if (rtcp_debug_test_addr(&sin)) 01060 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01061 break; 01062 default: 01063 if (option_debug) 01064 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)); 01065 break; 01066 } 01067 position += (length + 1); 01068 } 01069 01070 return f; 01071 }
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 2510 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02511 { 02512 struct ast_rtp *rtp = data; 02513 int res; 02514 02515 rtp->rtcp->sendfur = 1; 02516 res = ast_rtcp_write(data); 02517 02518 return res; 02519 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2727 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().
02728 { 02729 struct ast_rtp *rtp = (struct ast_rtp *)data; 02730 int res; 02731 02732 if (!rtp || !rtp->rtcp) 02733 return 0; 02734 02735 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02736 res = ast_rtcp_write_sr(data); 02737 else 02738 res = ast_rtcp_write_rr(data); 02739 02740 return res; 02741 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recepient's report.
Definition at line 2632 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().
02633 { 02634 struct ast_rtp *rtp = (struct ast_rtp *)data; 02635 int res; 02636 int len = 32; 02637 unsigned int lost; 02638 unsigned int extended; 02639 unsigned int expected; 02640 unsigned int expected_interval; 02641 unsigned int received_interval; 02642 int lost_interval; 02643 struct timeval now; 02644 unsigned int *rtcpheader; 02645 char bdata[1024]; 02646 struct timeval dlsr; 02647 int fraction; 02648 02649 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02650 return 0; 02651 02652 if (!rtp->rtcp->them.sin_addr.s_addr) { 02653 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02654 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02655 return 0; 02656 } 02657 02658 extended = rtp->cycles + rtp->lastrxseqno; 02659 expected = extended - rtp->seedrxseqno + 1; 02660 lost = expected - rtp->rxcount; 02661 expected_interval = expected - rtp->rtcp->expected_prior; 02662 rtp->rtcp->expected_prior = expected; 02663 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02664 rtp->rtcp->received_prior = rtp->rxcount; 02665 lost_interval = expected_interval - received_interval; 02666 if (expected_interval == 0 || lost_interval <= 0) 02667 fraction = 0; 02668 else 02669 fraction = (lost_interval << 8) / expected_interval; 02670 gettimeofday(&now, NULL); 02671 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02672 rtcpheader = (unsigned int *)bdata; 02673 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02674 rtcpheader[1] = htonl(rtp->ssrc); 02675 rtcpheader[2] = htonl(rtp->themssrc); 02676 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02677 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02678 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02679 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02680 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02681 02682 if (rtp->rtcp->sendfur) { 02683 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02684 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02685 len += 8; 02686 rtp->rtcp->sendfur = 0; 02687 } 02688 02689 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02690 it can change mid call, and SDES can't) */ 02691 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02692 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02693 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02694 len += 12; 02695 02696 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02697 02698 if (res < 0) { 02699 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02700 /* Remove the scheduler */ 02701 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02702 return 0; 02703 } 02704 02705 rtp->rtcp->rr_count++; 02706 02707 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02708 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02709 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02710 " IA jitter: %.4f\n" 02711 " Their last SR: %u\n" 02712 " DLSR: %4.4f (sec)\n\n", 02713 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02714 ntohs(rtp->rtcp->them.sin_port), 02715 rtp->ssrc, rtp->themssrc, fraction, lost, 02716 rtp->rxjitter, 02717 rtp->rtcp->themrxlsr, 02718 (double)(ntohl(rtcpheader[7])/65536.0)); 02719 } 02720 02721 return res; 02722 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2522 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().
02523 { 02524 struct ast_rtp *rtp = (struct ast_rtp *)data; 02525 int res; 02526 int len = 0; 02527 struct timeval now; 02528 unsigned int now_lsw; 02529 unsigned int now_msw; 02530 unsigned int *rtcpheader; 02531 unsigned int lost; 02532 unsigned int extended; 02533 unsigned int expected; 02534 unsigned int expected_interval; 02535 unsigned int received_interval; 02536 int lost_interval; 02537 int fraction; 02538 struct timeval dlsr; 02539 char bdata[512]; 02540 02541 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02542 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02543 return 0; 02544 02545 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02546 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02547 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02548 return 0; 02549 } 02550 02551 gettimeofday(&now, NULL); 02552 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02553 rtcpheader = (unsigned int *)bdata; 02554 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02555 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02556 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02557 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02558 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02559 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02560 len += 28; 02561 02562 extended = rtp->cycles + rtp->lastrxseqno; 02563 expected = extended - rtp->seedrxseqno + 1; 02564 if (rtp->rxcount > expected) 02565 expected += rtp->rxcount - expected; 02566 lost = expected - rtp->rxcount; 02567 expected_interval = expected - rtp->rtcp->expected_prior; 02568 rtp->rtcp->expected_prior = expected; 02569 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02570 rtp->rtcp->received_prior = rtp->rxcount; 02571 lost_interval = expected_interval - received_interval; 02572 if (expected_interval == 0 || lost_interval <= 0) 02573 fraction = 0; 02574 else 02575 fraction = (lost_interval << 8) / expected_interval; 02576 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02577 rtcpheader[7] = htonl(rtp->themssrc); 02578 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02579 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02580 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02581 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02582 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02583 len += 24; 02584 02585 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02586 02587 if (rtp->rtcp->sendfur) { 02588 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02589 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02590 len += 8; 02591 rtp->rtcp->sendfur = 0; 02592 } 02593 02594 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02595 /* it can change mid call, and SDES can't) */ 02596 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02597 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02598 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02599 len += 12; 02600 02601 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02602 if (res < 0) { 02603 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)); 02604 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02605 return 0; 02606 } 02607 02608 /* FIXME Don't need to get a new one */ 02609 gettimeofday(&rtp->rtcp->txlsr, NULL); 02610 rtp->rtcp->sr_count++; 02611 02612 rtp->rtcp->lastsrtxcount = rtp->txcount; 02613 02614 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02615 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02616 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02617 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02618 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02619 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02620 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02621 ast_verbose(" Report block:\n"); 02622 ast_verbose(" Fraction lost: %u\n", fraction); 02623 ast_verbose(" Cumulative loss: %u\n", lost); 02624 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02625 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02626 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02627 } 02628 return res; 02629 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 403 of file rtp.c.
Referenced by process_sdp().
00404 { 00405 return sizeof(struct ast_rtp); 00406 }
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 3486 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.
03487 { 03488 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03489 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03490 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03491 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03492 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03493 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03494 int codec0 = 0, codec1 = 0; 03495 void *pvt0 = NULL, *pvt1 = NULL; 03496 03497 /* Lock channels */ 03498 ast_channel_lock(c0); 03499 while(ast_channel_trylock(c1)) { 03500 ast_channel_unlock(c0); 03501 usleep(1); 03502 ast_channel_lock(c0); 03503 } 03504 03505 /* Ensure neither channel got hungup during lock avoidance */ 03506 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03507 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03508 ast_channel_unlock(c0); 03509 ast_channel_unlock(c1); 03510 return AST_BRIDGE_FAILED; 03511 } 03512 03513 /* Find channel driver interfaces */ 03514 if (!(pr0 = get_proto(c0))) { 03515 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03516 ast_channel_unlock(c0); 03517 ast_channel_unlock(c1); 03518 return AST_BRIDGE_FAILED; 03519 } 03520 if (!(pr1 = get_proto(c1))) { 03521 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03522 ast_channel_unlock(c0); 03523 ast_channel_unlock(c1); 03524 return AST_BRIDGE_FAILED; 03525 } 03526 03527 /* Get channel specific interface structures */ 03528 pvt0 = c0->tech_pvt; 03529 pvt1 = c1->tech_pvt; 03530 03531 /* Get audio and video interface (if native bridge is possible) */ 03532 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03533 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03534 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03535 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03536 03537 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03538 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03539 audio_p0_res = AST_RTP_GET_FAILED; 03540 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03541 audio_p1_res = AST_RTP_GET_FAILED; 03542 03543 /* Check if a bridge is possible (partial/native) */ 03544 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03545 /* Somebody doesn't want to play... */ 03546 ast_channel_unlock(c0); 03547 ast_channel_unlock(c1); 03548 return AST_BRIDGE_FAILED_NOWARN; 03549 } 03550 03551 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03552 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03553 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03554 audio_p0_res = AST_RTP_TRY_PARTIAL; 03555 } 03556 03557 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03558 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03559 audio_p1_res = AST_RTP_TRY_PARTIAL; 03560 } 03561 03562 /* If both sides are not using the same method of DTMF transmission 03563 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03564 * -------------------------------------------------- 03565 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03566 * |-----------|------------|-----------------------| 03567 * | Inband | False | True | 03568 * | RFC2833 | True | True | 03569 * | SIP INFO | False | False | 03570 * -------------------------------------------------- 03571 * However, if DTMF from both channels is being monitored by the core, then 03572 * we can still do packet-to-packet bridging, because passing through the 03573 * core will handle DTMF mode translation. 03574 */ 03575 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03576 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03577 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03578 ast_channel_unlock(c0); 03579 ast_channel_unlock(c1); 03580 return AST_BRIDGE_FAILED_NOWARN; 03581 } 03582 audio_p0_res = AST_RTP_TRY_PARTIAL; 03583 audio_p1_res = AST_RTP_TRY_PARTIAL; 03584 } 03585 03586 /* If we need to feed frames into the core don't do a P2P bridge */ 03587 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 03588 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 03589 ast_channel_unlock(c0); 03590 ast_channel_unlock(c1); 03591 return AST_BRIDGE_FAILED_NOWARN; 03592 } 03593 03594 /* Get codecs from both sides */ 03595 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03596 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03597 if (codec0 && codec1 && !(codec0 & codec1)) { 03598 /* Hey, we can't do native bridging if both parties speak different codecs */ 03599 if (option_debug) 03600 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03601 ast_channel_unlock(c0); 03602 ast_channel_unlock(c1); 03603 return AST_BRIDGE_FAILED_NOWARN; 03604 } 03605 03606 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03607 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03608 struct ast_format_list fmt0, fmt1; 03609 03610 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03611 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03612 if (option_debug) 03613 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03614 ast_channel_unlock(c0); 03615 ast_channel_unlock(c1); 03616 return AST_BRIDGE_FAILED_NOWARN; 03617 } 03618 /* They must also be using the same packetization */ 03619 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03620 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03621 if (fmt0.cur_ms != fmt1.cur_ms) { 03622 if (option_debug) 03623 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03624 ast_channel_unlock(c0); 03625 ast_channel_unlock(c1); 03626 return AST_BRIDGE_FAILED_NOWARN; 03627 } 03628 03629 if (option_verbose > 2) 03630 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03631 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03632 } else { 03633 if (option_verbose > 2) 03634 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03635 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03636 } 03637 03638 return res; 03639 }
void ast_rtp_change_source | ( | struct ast_rtp * | rtp | ) |
Indicate that we need to set the marker bit and change the ssrc.
Definition at line 2138 of file rtp.c.
References ast_log(), ast_random(), LOG_DEBUG, option_debug, ast_rtp::set_marker_bit, and ast_rtp::ssrc.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), and skinny_indicate().
02139 { 02140 if (rtp) { 02141 unsigned int ssrc = ast_random(); 02142 02143 rtp->set_marker_bit = 1; 02144 if (option_debug > 2) { 02145 ast_log(LOG_DEBUG, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc); 02146 } 02147 rtp->ssrc = ssrc; 02148 } 02149 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2938 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp_a_audio().
02939 { 02940 if (pt < 0 || pt >= MAX_RTP_PT) 02941 return 0; /* bogus payload type */ 02942 02943 if (static_RTP_PT[pt].isAstFormat) 02944 return static_RTP_PT[pt].code; 02945 else 02946 return 0; 02947 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Definition at line 2933 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp_a_audio().
02934 { 02935 return &rtp->pref; 02936 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2886 of file rtp.c.
References ast_codec_pref_getsize(), ast_log(), ast_smoother_new(), ast_smoother_reconfigure(), ast_smoother_set_flags(), ast_format_list::cur_ms, ast_format_list::flags, ast_format_list::fr_len, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, option_debug, ast_rtp::pref, prefs, and ast_rtp::smoother.
Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp_a_audio(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().
02887 { 02888 struct ast_format_list current_format_old, current_format_new; 02889 02890 /* if no packets have been sent through this session yet, then 02891 * changing preferences does not require any extra work 02892 */ 02893 if (rtp->lasttxformat == 0) { 02894 rtp->pref = *prefs; 02895 return 0; 02896 } 02897 02898 current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 02899 02900 rtp->pref = *prefs; 02901 02902 current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 02903 02904 /* if the framing desired for the current format has changed, we may have to create 02905 * or adjust the smoother for this session 02906 */ 02907 if ((current_format_new.inc_ms != 0) && 02908 (current_format_new.cur_ms != current_format_old.cur_ms)) { 02909 int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms; 02910 02911 if (rtp->smoother) { 02912 ast_smoother_reconfigure(rtp->smoother, new_size); 02913 if (option_debug) { 02914 ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size); 02915 } 02916 } else { 02917 if (!(rtp->smoother = ast_smoother_new(new_size))) { 02918 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 02919 return -1; 02920 } 02921 if (current_format_new.flags) { 02922 ast_smoother_set_flags(rtp->smoother, current_format_new.flags); 02923 } 02924 if (option_debug) { 02925 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 02926 } 02927 } 02928 } 02929 02930 return 0; 02931 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2280 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().
02281 { 02282 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02283 /*Print some info on the call here */ 02284 ast_verbose(" RTP-stats\n"); 02285 ast_verbose("* Our Receiver:\n"); 02286 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02287 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02288 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0); 02289 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02290 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02291 ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0); 02292 ast_verbose("* Our Sender:\n"); 02293 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02294 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02295 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0); 02296 ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0); 02297 ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0); 02298 ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0); 02299 } 02300 02301 if (rtp->smoother) 02302 ast_smoother_free(rtp->smoother); 02303 if (rtp->ioid) 02304 ast_io_remove(rtp->io, rtp->ioid); 02305 if (rtp->s > -1) 02306 close(rtp->s); 02307 if (rtp->rtcp) { 02308 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02309 close(rtp->rtcp->s); 02310 free(rtp->rtcp); 02311 rtp->rtcp=NULL; 02312 } 02313 02314 ast_mutex_destroy(&rtp->bridge_lock); 02315 02316 free(rtp); 02317 }
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 1597 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().
01598 { 01599 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01600 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01601 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01602 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01603 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01604 int srccodec, destcodec, nat_active = 0; 01605 01606 /* Lock channels */ 01607 ast_channel_lock(dest); 01608 if (src) { 01609 while(ast_channel_trylock(src)) { 01610 ast_channel_unlock(dest); 01611 usleep(1); 01612 ast_channel_lock(dest); 01613 } 01614 } 01615 01616 /* Find channel driver interfaces */ 01617 destpr = get_proto(dest); 01618 if (src) 01619 srcpr = get_proto(src); 01620 if (!destpr) { 01621 if (option_debug) 01622 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01623 ast_channel_unlock(dest); 01624 if (src) 01625 ast_channel_unlock(src); 01626 return 0; 01627 } 01628 if (!srcpr) { 01629 if (option_debug) 01630 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01631 ast_channel_unlock(dest); 01632 if (src) 01633 ast_channel_unlock(src); 01634 return 0; 01635 } 01636 01637 /* Get audio and video interface (if native bridge is possible) */ 01638 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01639 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01640 if (srcpr) { 01641 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01642 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01643 } 01644 01645 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01646 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) { 01647 /* Somebody doesn't want to play... */ 01648 ast_channel_unlock(dest); 01649 if (src) 01650 ast_channel_unlock(src); 01651 return 0; 01652 } 01653 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) 01654 srccodec = srcpr->get_codec(src); 01655 else 01656 srccodec = 0; 01657 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) 01658 destcodec = destpr->get_codec(dest); 01659 else 01660 destcodec = 0; 01661 /* Ensure we have at least one matching codec */ 01662 if (srcp && !(srccodec & destcodec)) { 01663 ast_channel_unlock(dest); 01664 ast_channel_unlock(src); 01665 return 0; 01666 } 01667 /* Consider empty media as non-existant */ 01668 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01669 srcp = NULL; 01670 /* If the client has NAT stuff turned on then just safe NAT is active */ 01671 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01672 nat_active = 1; 01673 /* Bridge media early */ 01674 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01675 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01676 ast_channel_unlock(dest); 01677 if (src) 01678 ast_channel_unlock(src); 01679 if (option_debug) 01680 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01681 return 1; 01682 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 518 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().
00519 { 00520 return rtp->s; 00521 }
Definition at line 2190 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().
02191 { 02192 struct ast_rtp *bridged = NULL; 02193 02194 ast_mutex_lock(&rtp->bridge_lock); 02195 bridged = rtp->bridged; 02196 ast_mutex_unlock(&rtp->bridge_lock); 02197 02198 return bridged; 02199 }
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 1818 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().
01820 { 01821 int pt; 01822 01823 ast_mutex_lock(&rtp->bridge_lock); 01824 01825 *astFormats = *nonAstFormats = 0; 01826 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01827 if (rtp->current_RTP_PT[pt].isAstFormat) { 01828 *astFormats |= rtp->current_RTP_PT[pt].code; 01829 } else { 01830 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01831 } 01832 } 01833 01834 ast_mutex_unlock(&rtp->bridge_lock); 01835 01836 return; 01837 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2172 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().
02173 { 02174 if ((them->sin_family != AF_INET) || 02175 (them->sin_port != rtp->them.sin_port) || 02176 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02177 them->sin_family = AF_INET; 02178 them->sin_port = rtp->them.sin_port; 02179 them->sin_addr = rtp->them.sin_addr; 02180 return 1; 02181 } 02182 return 0; 02183 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2236 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().
02237 { 02238 /* 02239 *ssrc our ssrc 02240 *themssrc their ssrc 02241 *lp lost packets 02242 *rxjitter our calculated jitter(rx) 02243 *rxcount no. received packets 02244 *txjitter reported jitter of the other end 02245 *txcount transmitted packets 02246 *rlp remote lost packets 02247 *rtt round trip time 02248 */ 02249 02250 if (qual && rtp) { 02251 qual->local_ssrc = rtp->ssrc; 02252 qual->local_jitter = rtp->rxjitter; 02253 qual->local_count = rtp->rxcount; 02254 qual->remote_ssrc = rtp->themssrc; 02255 qual->remote_count = rtp->txcount; 02256 if (rtp->rtcp) { 02257 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02258 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02259 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02260 qual->rtt = rtp->rtcp->rtt; 02261 } 02262 } 02263 if (rtp->rtcp) { 02264 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02265 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02266 rtp->ssrc, 02267 rtp->themssrc, 02268 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02269 rtp->rxjitter, 02270 rtp->rxcount, 02271 (double)rtp->rtcp->reported_jitter / 65536.0, 02272 rtp->txcount, 02273 rtp->rtcp->reported_lost, 02274 rtp->rtcp->rtt); 02275 return rtp->rtcp->quality; 02276 } else 02277 return "<Unknown> - RTP/RTCP has already been destroyed"; 02278 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 578 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by do_monitor().
00579 { 00580 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00581 return 0; 00582 return rtp->rtpholdtimeout; 00583 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 586 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by do_monitor().
00587 { 00588 return rtp->rtpkeepalive; 00589 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 570 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by do_monitor().
00571 { 00572 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00573 return 0; 00574 return rtp->rtptimeout; 00575 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2185 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 606 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00607 { 00608 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00609 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 4024 of file rtp.c.
References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp.
Referenced by main().
04025 { 04026 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 04027 ast_rtp_reload(); 04028 }
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 1861 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().
01862 { 01863 int pt = 0; 01864 01865 ast_mutex_lock(&rtp->bridge_lock); 01866 01867 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01868 code == rtp->rtp_lookup_code_cache_code) { 01869 /* Use our cached mapping, to avoid the overhead of the loop below */ 01870 pt = rtp->rtp_lookup_code_cache_result; 01871 ast_mutex_unlock(&rtp->bridge_lock); 01872 return pt; 01873 } 01874 01875 /* Check the dynamic list first */ 01876 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01877 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01878 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01879 rtp->rtp_lookup_code_cache_code = code; 01880 rtp->rtp_lookup_code_cache_result = pt; 01881 ast_mutex_unlock(&rtp->bridge_lock); 01882 return pt; 01883 } 01884 } 01885 01886 /* Then the static list */ 01887 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01888 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01889 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01890 rtp->rtp_lookup_code_cache_code = code; 01891 rtp->rtp_lookup_code_cache_result = pt; 01892 ast_mutex_unlock(&rtp->bridge_lock); 01893 return pt; 01894 } 01895 } 01896 01897 ast_mutex_unlock(&rtp->bridge_lock); 01898 01899 return -1; 01900 }
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 1921 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.
Referenced by process_sdp().
01923 { 01924 int format; 01925 unsigned len; 01926 char *end = buf; 01927 char *start = buf; 01928 01929 if (!buf || !size) 01930 return NULL; 01931 01932 snprintf(end, size, "0x%x (", capability); 01933 01934 len = strlen(end); 01935 end += len; 01936 size -= len; 01937 start = end; 01938 01939 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01940 if (capability & format) { 01941 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01942 01943 snprintf(end, size, "%s|", name); 01944 len = strlen(end); 01945 end += len; 01946 size -= len; 01947 } 01948 } 01949 01950 if (start == end) 01951 snprintf(start, size, "nothing)"); 01952 else if (size > 1) 01953 *(end -1) = ')'; 01954 01955 return buf; 01956 }
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 1902 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().
01904 { 01905 unsigned int i; 01906 01907 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01908 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01909 if (isAstFormat && 01910 (code == AST_FORMAT_G726_AAL2) && 01911 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01912 return "G726-32"; 01913 else 01914 return mimeTypes[i].subtype; 01915 } 01916 } 01917 01918 return ""; 01919 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1839 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().
01840 { 01841 struct rtpPayloadType result; 01842 01843 result.isAstFormat = result.code = 0; 01844 01845 if (pt < 0 || pt >= MAX_RTP_PT) 01846 return result; /* bogus payload type */ 01847 01848 /* Start with negotiated codecs */ 01849 ast_mutex_lock(&rtp->bridge_lock); 01850 result = rtp->current_RTP_PT[pt]; 01851 ast_mutex_unlock(&rtp->bridge_lock); 01852 01853 /* If it doesn't exist, check our static RTP type list, just in case */ 01854 if (!result.code) 01855 result = static_RTP_PT[pt]; 01856 01857 return result; 01858 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1684 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().
01685 { 01686 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01687 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01688 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01689 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01690 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01691 int srccodec, destcodec; 01692 01693 /* Lock channels */ 01694 ast_channel_lock(dest); 01695 while(ast_channel_trylock(src)) { 01696 ast_channel_unlock(dest); 01697 usleep(1); 01698 ast_channel_lock(dest); 01699 } 01700 01701 /* Find channel driver interfaces */ 01702 if (!(destpr = get_proto(dest))) { 01703 if (option_debug) 01704 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01705 ast_channel_unlock(dest); 01706 ast_channel_unlock(src); 01707 return 0; 01708 } 01709 if (!(srcpr = get_proto(src))) { 01710 if (option_debug) 01711 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01712 ast_channel_unlock(dest); 01713 ast_channel_unlock(src); 01714 return 0; 01715 } 01716 01717 /* Get audio and video interface (if native bridge is possible) */ 01718 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01719 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01720 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01721 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01722 01723 /* Ensure we have at least one matching codec */ 01724 if (srcpr->get_codec) 01725 srccodec = srcpr->get_codec(src); 01726 else 01727 srccodec = 0; 01728 if (destpr->get_codec) 01729 destcodec = destpr->get_codec(dest); 01730 else 01731 destcodec = 0; 01732 01733 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01734 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)) { 01735 /* Somebody doesn't want to play... */ 01736 ast_channel_unlock(dest); 01737 ast_channel_unlock(src); 01738 return 0; 01739 } 01740 ast_rtp_pt_copy(destp, srcp); 01741 if (vdestp && vsrcp) 01742 ast_rtp_pt_copy(vdestp, vsrcp); 01743 if (media) { 01744 /* Bridge early */ 01745 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01746 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01747 } 01748 ast_channel_unlock(dest); 01749 ast_channel_unlock(src); 01750 if (option_debug) 01751 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01752 return 1; 01753 }
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 2111 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
02112 { 02113 struct in_addr ia; 02114 02115 memset(&ia, 0, sizeof(ia)); 02116 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02117 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 2005 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().
02006 { 02007 ast_mutex_init(&rtp->bridge_lock); 02008 02009 rtp->them.sin_family = AF_INET; 02010 rtp->us.sin_family = AF_INET; 02011 rtp->ssrc = ast_random(); 02012 rtp->seqno = ast_random() & 0xffff; 02013 ast_set_flag(rtp, FLAG_HAS_DTMF); 02014 02015 return; 02016 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Indicate that we need to set the marker bit.
Definition at line 2128 of file rtp.c.
References ast_log(), LOG_DEBUG, option_debug, and ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_answer(), sip_indicate(), sip_write(), and skinny_indicate().
02129 { 02130 if (rtp) { 02131 rtp->set_marker_bit = 1; 02132 if (option_debug > 2) { 02133 ast_log(LOG_DEBUG, "Setting the marker bit due to a source update\n"); 02134 } 02135 } 02136 }
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 2018 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().
02019 { 02020 struct ast_rtp *rtp; 02021 int x; 02022 int first; 02023 int startplace; 02024 02025 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 02026 return NULL; 02027 02028 ast_rtp_new_init(rtp); 02029 02030 rtp->s = rtp_socket(); 02031 if (option_debug > 2) 02032 ast_log(LOG_DEBUG, "socket RTP fd: %i\n", rtp->s); 02033 if (rtp->s < 0) { 02034 free(rtp); 02035 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 02036 return NULL; 02037 } 02038 if (sched && rtcpenable) { 02039 rtp->sched = sched; 02040 rtp->rtcp = ast_rtcp_new(); 02041 if (option_debug > 2) 02042 ast_log(LOG_DEBUG, "socket RTCP fd: %i\n", rtp->rtcp->s); 02043 } 02044 02045 /* Select a random port number in the range of possible RTP */ 02046 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 02047 x = x & ~1; 02048 /* Save it for future references. */ 02049 startplace = x; 02050 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 02051 for (;;) { 02052 /* Must be an even port number by RTP spec */ 02053 rtp->us.sin_port = htons(x); 02054 rtp->us.sin_addr = addr; 02055 /* If there's rtcp, initialize it as well. */ 02056 if (rtp->rtcp) { 02057 rtp->rtcp->us.sin_port = htons(x + 1); 02058 rtp->rtcp->us.sin_addr = addr; 02059 } 02060 /* Try to bind it/them. */ 02061 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 02062 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 02063 break; 02064 if (!first) { 02065 /* Primary bind succeeded! Gotta recreate it */ 02066 close(rtp->s); 02067 rtp->s = rtp_socket(); 02068 if (option_debug > 2) 02069 ast_log(LOG_DEBUG, "socket RTP2 fd: %i\n", rtp->s); 02070 } 02071 if (errno != EADDRINUSE) { 02072 /* We got an error that wasn't expected, abort! */ 02073 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 02074 close(rtp->s); 02075 if (rtp->rtcp) { 02076 close(rtp->rtcp->s); 02077 free(rtp->rtcp); 02078 } 02079 free(rtp); 02080 return NULL; 02081 } 02082 /* The port was used, increment it (by two). */ 02083 x += 2; 02084 /* Did we go over the limit ? */ 02085 if (x > rtpend) 02086 /* then, start from the begingig. */ 02087 x = (rtpstart + 1) & ~1; 02088 /* Check if we reached the place were we started. */ 02089 if (x == startplace) { 02090 /* If so, there's no ports available. */ 02091 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 02092 close(rtp->s); 02093 if (rtp->rtcp) { 02094 close(rtp->rtcp->s); 02095 free(rtp->rtcp); 02096 } 02097 free(rtp); 02098 return NULL; 02099 } 02100 } 02101 rtp->sched = sched; 02102 rtp->io = io; 02103 if (callbackmode) { 02104 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 02105 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 02106 } 02107 ast_rtp_pt_default(rtp); 02108 return rtp; 02109 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 3040 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().
03041 { 03042 struct ast_rtp_protocol *cur; 03043 03044 AST_LIST_LOCK(&protos); 03045 AST_LIST_TRAVERSE(&protos, cur, list) { 03046 if (!strcmp(cur->type, proto->type)) { 03047 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 03048 AST_LIST_UNLOCK(&protos); 03049 return -1; 03050 } 03051 } 03052 AST_LIST_INSERT_HEAD(&protos, proto, list); 03053 AST_LIST_UNLOCK(&protos); 03054 03055 return 0; 03056 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 3032 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by load_module(), and unload_module().
03033 { 03034 AST_LIST_LOCK(&protos); 03035 AST_LIST_REMOVE(&protos, proto, list); 03036 AST_LIST_UNLOCK(&protos); 03037 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1521 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().
01522 { 01523 int i; 01524 01525 if (!rtp) 01526 return; 01527 01528 ast_mutex_lock(&rtp->bridge_lock); 01529 01530 for (i = 0; i < MAX_RTP_PT; ++i) { 01531 rtp->current_RTP_PT[i].isAstFormat = 0; 01532 rtp->current_RTP_PT[i].code = 0; 01533 } 01534 01535 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01536 rtp->rtp_lookup_code_cache_code = 0; 01537 rtp->rtp_lookup_code_cache_result = 0; 01538 01539 ast_mutex_unlock(&rtp->bridge_lock); 01540 }
Copy payload types between RTP structures.
Definition at line 1561 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().
01562 { 01563 unsigned int i; 01564 01565 ast_mutex_lock(&dest->bridge_lock); 01566 ast_mutex_lock(&src->bridge_lock); 01567 01568 for (i=0; i < MAX_RTP_PT; ++i) { 01569 dest->current_RTP_PT[i].isAstFormat = 01570 src->current_RTP_PT[i].isAstFormat; 01571 dest->current_RTP_PT[i].code = 01572 src->current_RTP_PT[i].code; 01573 } 01574 dest->rtp_lookup_code_cache_isAstFormat = 0; 01575 dest->rtp_lookup_code_cache_code = 0; 01576 dest->rtp_lookup_code_cache_result = 0; 01577 01578 ast_mutex_unlock(&src->bridge_lock); 01579 ast_mutex_unlock(&dest->bridge_lock); 01580 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1542 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.
01543 { 01544 int i; 01545 01546 ast_mutex_lock(&rtp->bridge_lock); 01547 01548 /* Initialize to default payload types */ 01549 for (i = 0; i < MAX_RTP_PT; ++i) { 01550 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01551 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01552 } 01553 01554 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01555 rtp->rtp_lookup_code_cache_code = 0; 01556 rtp->rtp_lookup_code_cache_result = 0; 01557 01558 ast_mutex_unlock(&rtp->bridge_lock); 01559 }
Definition at line 2778 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().
02779 { 02780 unsigned char *rtpheader; 02781 int hdrlen = 12; 02782 int res; 02783 unsigned int ms; 02784 int pred; 02785 int mark = 0; 02786 int rate = rtp_get_rate(f->subclass) / 1000; 02787 02788 if (f->subclass == AST_FORMAT_G722) { 02789 /* G722 is silllllllllllllllllly */ 02790 f->samples /= 2; 02791 } 02792 02793 if (rtp->sending_digit) { 02794 return 0; 02795 } 02796 02797 ms = calc_txstamp(rtp, &f->delivery); 02798 /* Default prediction */ 02799 if (f->frametype == AST_FRAME_VOICE) { 02800 pred = rtp->lastts + f->samples; 02801 02802 /* Re-calculate last TS */ 02803 rtp->lastts = rtp->lastts + ms * rate; 02804 if (ast_tvzero(f->delivery)) { 02805 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02806 and if so, go with our prediction */ 02807 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02808 rtp->lastts = pred; 02809 else { 02810 if (option_debug > 2) 02811 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02812 mark = 1; 02813 } 02814 } 02815 } else if (f->frametype == AST_FRAME_VIDEO) { 02816 mark = f->subclass & 0x1; 02817 pred = rtp->lastovidtimestamp + f->samples; 02818 /* Re-calculate last TS */ 02819 rtp->lastts = rtp->lastts + ms * 90; 02820 /* If it's close to our prediction, go for it */ 02821 if (ast_tvzero(f->delivery)) { 02822 if (abs(rtp->lastts - pred) < 7200) { 02823 rtp->lastts = pred; 02824 rtp->lastovidtimestamp += f->samples; 02825 } else { 02826 if (option_debug > 2) 02827 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); 02828 rtp->lastovidtimestamp = rtp->lastts; 02829 } 02830 } 02831 } 02832 02833 /* If we have been explicitly told to set the marker bit do so */ 02834 if (rtp->set_marker_bit) { 02835 mark = 1; 02836 rtp->set_marker_bit = 0; 02837 } 02838 02839 /* If the timestamp for non-digit packets has moved beyond the timestamp 02840 for digits, update the digit timestamp. 02841 */ 02842 if (rtp->lastts > rtp->lastdigitts) 02843 rtp->lastdigitts = rtp->lastts; 02844 02845 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 02846 rtp->lastts = f->ts * rate; 02847 02848 /* Get a pointer to the header */ 02849 rtpheader = (unsigned char *)(f->data - hdrlen); 02850 02851 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02852 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02853 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02854 02855 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02856 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02857 if (res <0) { 02858 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02859 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)); 02860 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02861 /* Only give this error message once if we are not RTP debugging */ 02862 if (option_debug || rtpdebug) 02863 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)); 02864 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02865 } 02866 } else { 02867 rtp->txcount++; 02868 rtp->txoctetcount +=(res - hdrlen); 02869 02870 /* Do not schedule RR if RTCP isn't run */ 02871 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 02872 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02873 } 02874 } 02875 02876 if (rtp_debug_test_addr(&rtp->them)) 02877 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02878 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02879 } 02880 02881 rtp->seqno++; 02882 02883 return 0; 02884 }
Definition at line 1182 of file rtp.c.
References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, 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, create_dtmf_frame(), 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, frames, 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, 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().
01183 { 01184 int res; 01185 struct sockaddr_in sin; 01186 socklen_t len; 01187 unsigned int seqno; 01188 int version; 01189 int payloadtype; 01190 int hdrlen = 12; 01191 int padding; 01192 int mark; 01193 int ext; 01194 int cc; 01195 unsigned int ssrc; 01196 unsigned int timestamp; 01197 unsigned int *rtpheader; 01198 struct rtpPayloadType rtpPT; 01199 struct ast_rtp *bridged = NULL; 01200 struct frame_list frames; 01201 01202 /* If time is up, kill it */ 01203 if (rtp->sending_digit) 01204 ast_rtp_senddigit_continuation(rtp); 01205 01206 len = sizeof(sin); 01207 01208 /* Cache where the header will go */ 01209 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01210 0, (struct sockaddr *)&sin, &len); 01211 if (option_debug > 3) 01212 ast_log(LOG_DEBUG, "socket RTP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 01213 01214 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01215 if (res < 0) { 01216 ast_assert(errno != EBADF); 01217 if (errno != EAGAIN) { 01218 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01219 ast_log(LOG_WARNING, "socket RTP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 01220 return NULL; 01221 } 01222 return &ast_null_frame; 01223 } 01224 01225 if (res < hdrlen) { 01226 ast_log(LOG_WARNING, "RTP Read too short\n"); 01227 return &ast_null_frame; 01228 } 01229 01230 /* Get fields */ 01231 seqno = ntohl(rtpheader[0]); 01232 01233 /* Check RTP version */ 01234 version = (seqno & 0xC0000000) >> 30; 01235 if (!version) { 01236 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01237 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01238 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01239 } 01240 return &ast_null_frame; 01241 } 01242 01243 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01244 /* If we don't have the other side's address, then ignore this */ 01245 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01246 return &ast_null_frame; 01247 #endif 01248 01249 /* Send to whoever send to us if NAT is turned on */ 01250 if (rtp->nat) { 01251 if (((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01252 (rtp->them.sin_port != sin.sin_port)) && 01253 ((rtp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) || 01254 (rtp->altthem.sin_port != sin.sin_port))) { 01255 rtp->them = sin; 01256 if (rtp->rtcp) { 01257 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01258 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01259 } 01260 rtp->rxseqno = 0; 01261 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01262 if (option_debug || rtpdebug) 01263 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)); 01264 } 01265 } 01266 01267 /* If we are bridged to another RTP stream, send direct */ 01268 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01269 return &ast_null_frame; 01270 01271 if (version != 2) 01272 return &ast_null_frame; 01273 01274 payloadtype = (seqno & 0x7f0000) >> 16; 01275 padding = seqno & (1 << 29); 01276 mark = seqno & (1 << 23); 01277 ext = seqno & (1 << 28); 01278 cc = (seqno & 0xF000000) >> 24; 01279 seqno &= 0xffff; 01280 timestamp = ntohl(rtpheader[1]); 01281 ssrc = ntohl(rtpheader[2]); 01282 01283 AST_LIST_HEAD_INIT_NOLOCK(&frames); 01284 /* Force a marker bit and change SSRC if the SSRC changes */ 01285 if (rtp->rxssrc && rtp->rxssrc != ssrc) { 01286 struct ast_frame *f, srcupdate = { 01287 AST_FRAME_CONTROL, 01288 .subclass = AST_CONTROL_SRCCHANGE, 01289 }; 01290 01291 if (!mark) { 01292 if (option_debug || rtpdebug) { 01293 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01294 } 01295 mark = 1; 01296 } 01297 f = ast_frisolate(&srcupdate); 01298 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01299 } 01300 01301 rtp->rxssrc = ssrc; 01302 01303 if (padding) { 01304 /* Remove padding bytes */ 01305 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01306 } 01307 01308 if (cc) { 01309 /* CSRC fields present */ 01310 hdrlen += cc*4; 01311 } 01312 01313 if (ext) { 01314 /* RTP Extension present */ 01315 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01316 hdrlen += 4; 01317 } 01318 01319 if (res < hdrlen) { 01320 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01321 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 01322 } 01323 01324 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01325 01326 if (rtp->rxcount==1) { 01327 /* This is the first RTP packet successfully received from source */ 01328 rtp->seedrxseqno = seqno; 01329 } 01330 01331 /* Do not schedule RR if RTCP isn't run */ 01332 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01333 /* Schedule transmission of Receiver Report */ 01334 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01335 } 01336 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01337 rtp->cycles += RTP_SEQ_MOD; 01338 01339 rtp->lastrxseqno = seqno; 01340 01341 if (rtp->themssrc==0) 01342 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01343 01344 if (rtp_debug_test_addr(&sin)) 01345 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01346 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01347 01348 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01349 if (!rtpPT.isAstFormat) { 01350 struct ast_frame *f = NULL; 01351 01352 /* This is special in-band data that's not one of our codecs */ 01353 if (rtpPT.code == AST_RTP_DTMF) { 01354 /* It's special -- rfc2833 process it */ 01355 if (rtp_debug_test_addr(&sin)) { 01356 unsigned char *data; 01357 unsigned int event; 01358 unsigned int event_end; 01359 unsigned int duration; 01360 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01361 event = ntohl(*((unsigned int *)(data))); 01362 event >>= 24; 01363 event_end = ntohl(*((unsigned int *)(data))); 01364 event_end <<= 8; 01365 event_end >>= 24; 01366 duration = ntohl(*((unsigned int *)(data))); 01367 duration &= 0xFFFF; 01368 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); 01369 } 01370 /* process_rfc2833 may need to return multiple frames. We do this 01371 * by passing the pointer to the frame list to it so that the method 01372 * can append frames to the list as needed 01373 */ 01374 process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &frames); 01375 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01376 /* It's really special -- process it the Cisco way */ 01377 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01378 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01379 rtp->lastevent = seqno; 01380 } 01381 } else if (rtpPT.code == AST_RTP_CN) { 01382 /* Comfort Noise */ 01383 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01384 } else { 01385 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01386 } 01387 if (f) { 01388 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01389 } 01390 /* Even if no frame was returned by one of the above methods, 01391 * we may have a frame to return in our frame list 01392 */ 01393 if (!AST_LIST_EMPTY(&frames)) { 01394 return AST_LIST_FIRST(&frames); 01395 } 01396 return &ast_null_frame; 01397 } 01398 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01399 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01400 01401 rtp->rxseqno = seqno; 01402 01403 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) { 01404 rtp->dtmf_timeout = 0; 01405 01406 if (rtp->resp) { 01407 struct ast_frame *f; 01408 f = create_dtmf_frame(rtp, AST_FRAME_DTMF_END); 01409 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01410 rtp->resp = 0; 01411 rtp->dtmf_timeout = rtp->dtmf_duration = 0; 01412 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01413 return AST_LIST_FIRST(&frames); 01414 } 01415 } 01416 01417 /* Record received timestamp as last received now */ 01418 rtp->lastrxts = timestamp; 01419 01420 rtp->f.mallocd = 0; 01421 rtp->f.datalen = res - hdrlen; 01422 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01423 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01424 rtp->f.seqno = seqno; 01425 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01426 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01427 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01428 ast_frame_byteswap_be(&rtp->f); 01429 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01430 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01431 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01432 rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000); 01433 rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000); 01434 } else { 01435 /* Video -- samples is # of samples vs. 90000 */ 01436 if (!rtp->lastividtimestamp) 01437 rtp->lastividtimestamp = timestamp; 01438 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01439 rtp->lastividtimestamp = timestamp; 01440 rtp->f.delivery.tv_sec = 0; 01441 rtp->f.delivery.tv_usec = 0; 01442 if (mark) 01443 rtp->f.subclass |= 0x1; 01444 } 01445 rtp->f.src = "RTP"; 01446 01447 AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list); 01448 return AST_LIST_FIRST(&frames); 01449 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3959 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().
03960 { 03961 struct ast_config *cfg; 03962 const char *s; 03963 03964 rtpstart = 5000; 03965 rtpend = 31000; 03966 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03967 cfg = ast_config_load("rtp.conf"); 03968 if (cfg) { 03969 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03970 rtpstart = atoi(s); 03971 if (rtpstart < 1024) 03972 rtpstart = 1024; 03973 if (rtpstart > 65535) 03974 rtpstart = 65535; 03975 } 03976 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03977 rtpend = atoi(s); 03978 if (rtpend < 1024) 03979 rtpend = 1024; 03980 if (rtpend > 65535) 03981 rtpend = 65535; 03982 } 03983 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03984 rtcpinterval = atoi(s); 03985 if (rtcpinterval == 0) 03986 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03987 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03988 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03989 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03990 rtcpinterval = RTCP_MAX_INTERVALMS; 03991 } 03992 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03993 #ifdef SO_NO_CHECK 03994 if (ast_false(s)) 03995 nochecksums = 1; 03996 else 03997 nochecksums = 0; 03998 #else 03999 if (ast_false(s)) 04000 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 04001 #endif 04002 } 04003 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 04004 dtmftimeout = atoi(s); 04005 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) { 04006 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 04007 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 04008 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04009 }; 04010 } 04011 ast_config_destroy(cfg); 04012 } 04013 if (rtpstart >= rtpend) { 04014 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 04015 rtpstart = 5000; 04016 rtpend = 31000; 04017 } 04018 if (option_verbose > 1) 04019 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 04020 return 0; 04021 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2217 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.
02218 { 02219 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02220 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02221 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02222 rtp->lastts = 0; 02223 rtp->lastdigitts = 0; 02224 rtp->lastrxts = 0; 02225 rtp->lastividtimestamp = 0; 02226 rtp->lastovidtimestamp = 0; 02227 rtp->lasteventseqn = 0; 02228 rtp->lastevent = 0; 02229 rtp->lasttxformat = 0; 02230 rtp->lastrxformat = 0; 02231 rtp->dtmf_timeout = 0; 02232 rtp->seqno = 0; 02233 rtp->rxseqno = 0; 02234 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2744 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().
02745 { 02746 unsigned int *rtpheader; 02747 int hdrlen = 12; 02748 int res; 02749 int payload; 02750 char data[256]; 02751 level = 127 - (level & 0x7f); 02752 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02753 02754 /* If we have no peer, return immediately */ 02755 if (!rtp->them.sin_addr.s_addr) 02756 return 0; 02757 02758 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02759 02760 /* Get a pointer to the header */ 02761 rtpheader = (unsigned int *)data; 02762 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02763 rtpheader[1] = htonl(rtp->lastts); 02764 rtpheader[2] = htonl(rtp->ssrc); 02765 data[12] = level; 02766 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02767 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02768 if (res <0) 02769 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)); 02770 if (rtp_debug_test_addr(&rtp->them)) 02771 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02772 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02773 02774 } 02775 return 0; 02776 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2339 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().
02340 { 02341 unsigned int *rtpheader; 02342 int hdrlen = 12, res = 0, i = 0, payload = 0; 02343 char data[256]; 02344 02345 if ((digit <= '9') && (digit >= '0')) 02346 digit -= '0'; 02347 else if (digit == '*') 02348 digit = 10; 02349 else if (digit == '#') 02350 digit = 11; 02351 else if ((digit >= 'A') && (digit <= 'D')) 02352 digit = digit - 'A' + 12; 02353 else if ((digit >= 'a') && (digit <= 'd')) 02354 digit = digit - 'a' + 12; 02355 else { 02356 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02357 return 0; 02358 } 02359 02360 /* If we have no peer, return immediately */ 02361 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02362 return 0; 02363 02364 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02365 02366 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02367 rtp->send_duration = 160; 02368 rtp->lastdigitts = rtp->lastts + rtp->send_duration; 02369 02370 /* Get a pointer to the header */ 02371 rtpheader = (unsigned int *)data; 02372 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02373 rtpheader[1] = htonl(rtp->lastdigitts); 02374 rtpheader[2] = htonl(rtp->ssrc); 02375 02376 for (i = 0; i < 2; i++) { 02377 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02378 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02379 if (res < 0) 02380 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02381 ast_inet_ntoa(rtp->them.sin_addr), 02382 ntohs(rtp->them.sin_port), strerror(errno)); 02383 if (rtp_debug_test_addr(&rtp->them)) 02384 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02385 ast_inet_ntoa(rtp->them.sin_addr), 02386 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02387 /* Increment sequence number */ 02388 rtp->seqno++; 02389 /* Increment duration */ 02390 rtp->send_duration += 160; 02391 /* Clear marker bit and set seqno */ 02392 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02393 } 02394 02395 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02396 rtp->sending_digit = 1; 02397 rtp->send_digit = digit; 02398 rtp->send_payload = payload; 02399 02400 return 0; 02401 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2404 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().
02405 { 02406 unsigned int *rtpheader; 02407 int hdrlen = 12, res = 0; 02408 char data[256]; 02409 02410 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02411 return 0; 02412 02413 /* Setup packet to send */ 02414 rtpheader = (unsigned int *)data; 02415 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02416 rtpheader[1] = htonl(rtp->lastdigitts); 02417 rtpheader[2] = htonl(rtp->ssrc); 02418 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02419 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02420 02421 /* Transmit */ 02422 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02423 if (res < 0) 02424 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02425 ast_inet_ntoa(rtp->them.sin_addr), 02426 ntohs(rtp->them.sin_port), strerror(errno)); 02427 if (rtp_debug_test_addr(&rtp->them)) 02428 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02429 ast_inet_ntoa(rtp->them.sin_addr), 02430 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02431 02432 /* Increment sequence number */ 02433 rtp->seqno++; 02434 /* Increment duration */ 02435 rtp->send_duration += 160; 02436 02437 return 0; 02438 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Definition at line 2440 of file rtp.c.
References ast_rtp_senddigit_end_with_duration().
Referenced by mgcp_senddigit_end(), and oh323_digit_end().
02441 { 02442 return ast_rtp_senddigit_end_with_duration(rtp, digit, 0); 02443 }
int ast_rtp_senddigit_end_with_duration | ( | struct ast_rtp * | rtp, | |
char | digit, | |||
unsigned int | duration | |||
) |
Send end packets for DTMF.
Definition at line 2446 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::f, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_DEBUG, LOG_ERROR, LOG_WARNING, option_debug, rtp_debug_test_addr(), rtp_get_rate(), 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, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_senddigit_end(), and sip_senddigit_end().
02447 { 02448 unsigned int *rtpheader; 02449 int hdrlen = 12, res = 0, i = 0; 02450 char data[256]; 02451 unsigned int measured_samples; 02452 02453 /* If no address, then bail out */ 02454 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02455 return 0; 02456 02457 if ((digit <= '9') && (digit >= '0')) 02458 digit -= '0'; 02459 else if (digit == '*') 02460 digit = 10; 02461 else if (digit == '#') 02462 digit = 11; 02463 else if ((digit >= 'A') && (digit <= 'D')) 02464 digit = digit - 'A' + 12; 02465 else if ((digit >= 'a') && (digit <= 'd')) 02466 digit = digit - 'a' + 12; 02467 else { 02468 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02469 return 0; 02470 } 02471 02472 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02473 02474 if (duration > 0 && (measured_samples = duration * rtp_get_rate(rtp->f.subclass) / 1000) > rtp->send_duration) { 02475 if (option_debug > 1) { 02476 ast_log(LOG_DEBUG, "Adjusting final end duration from %u to %u\n", rtp->send_duration, measured_samples); 02477 } 02478 rtp->send_duration = measured_samples; 02479 } 02480 02481 rtpheader = (unsigned int *)data; 02482 rtpheader[1] = htonl(rtp->lastdigitts); 02483 rtpheader[2] = htonl(rtp->ssrc); 02484 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02485 /* Set end bit */ 02486 rtpheader[3] |= htonl((1 << 23)); 02487 02488 /* Send 3 termination packets */ 02489 for (i = 0; i < 3; i++) { 02490 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02491 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02492 rtp->seqno++; 02493 if (res < 0) 02494 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02495 ast_inet_ntoa(rtp->them.sin_addr), 02496 ntohs(rtp->them.sin_port), strerror(errno)); 02497 if (rtp_debug_test_addr(&rtp->them)) 02498 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02499 ast_inet_ntoa(rtp->them.sin_addr), 02500 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02501 } 02502 rtp->lastts += rtp->send_duration; 02503 rtp->sending_digit = 0; 02504 rtp->send_digit = 0; 02505 02506 return res; 02507 }
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 2162 of file rtp.c.
References ast_rtp::altthem, ast_rtcp::altthem, and ast_rtp::rtcp.
Referenced by handle_request_invite().
02163 { 02164 rtp->altthem.sin_port = alt->sin_port; 02165 rtp->altthem.sin_addr = alt->sin_addr; 02166 if (rtp->rtcp) { 02167 rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1); 02168 rtp->rtcp->altthem.sin_addr = alt->sin_addr; 02169 } 02170 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 596 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00597 { 00598 rtp->callback = callback; 00599 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 591 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00592 { 00593 rtp->data = data; 00594 }
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Activate payload type.
Definition at line 1759 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().
01760 { 01761 if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01762 return; /* bogus payload type */ 01763 01764 ast_mutex_lock(&rtp->bridge_lock); 01765 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01766 ast_mutex_unlock(&rtp->bridge_lock); 01767 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2151 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().
02152 { 02153 rtp->them.sin_port = them->sin_port; 02154 rtp->them.sin_addr = them->sin_addr; 02155 if (rtp->rtcp) { 02156 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02157 rtp->rtcp->them.sin_addr = them->sin_addr; 02158 } 02159 rtp->rxseqno = 0; 02160 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 558 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00559 { 00560 rtp->rtpholdtimeout = timeout; 00561 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 564 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00565 { 00566 rtp->rtpkeepalive = period; 00567 }
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 1786 of file rtp.c.
References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, subtype, and type.
Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), process_sdp(), process_sdp_a_audio(), process_sdp_a_video(), and set_dtmf_payload().
01789 { 01790 unsigned int i; 01791 int found = 0; 01792 01793 if (pt < 0 || pt >= MAX_RTP_PT) 01794 return -1; /* bogus payload type */ 01795 01796 ast_mutex_lock(&rtp->bridge_lock); 01797 01798 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01799 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01800 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01801 found = 1; 01802 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01803 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01804 mimeTypes[i].payloadType.isAstFormat && 01805 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01806 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01807 break; 01808 } 01809 } 01810 01811 ast_mutex_unlock(&rtp->bridge_lock); 01812 01813 return (found ? 0 : -1); 01814 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 552 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00553 { 00554 rtp->rtptimeout = timeout; 00555 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 545 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00546 { 00547 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00548 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00549 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 611 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().
00612 { 00613 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00614 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 616 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().
00617 { 00618 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00619 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 601 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 621 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00622 { 00623 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00624 }
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 2119 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
02120 { 02121 int res; 02122 02123 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 02124 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 02125 return res; 02126 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2201 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().
02202 { 02203 if (rtp->rtcp) { 02204 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02205 } 02206 02207 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02208 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02209 if (rtp->rtcp) { 02210 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02211 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02212 } 02213 02214 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02215 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Definition at line 408 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().
00409 { 00410 struct stun_header *req; 00411 unsigned char reqdata[1024]; 00412 int reqlen, reqleft; 00413 struct stun_attr *attr; 00414 00415 req = (struct stun_header *)reqdata; 00416 stun_req_id(req); 00417 reqlen = 0; 00418 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00419 req->msgtype = 0; 00420 req->msglen = 0; 00421 attr = (struct stun_attr *)req->ies; 00422 if (username) 00423 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00424 req->msglen = htons(reqlen); 00425 req->msgtype = htons(STUN_BINDREQ); 00426 stun_send(rtp->s, suggestion, req); 00427 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
clear payload type
Definition at line 1771 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by process_sdp_a_audio(), and process_sdp_a_video().
01772 { 01773 if (pt < 0 || pt >= MAX_RTP_PT) 01774 return; /* bogus payload type */ 01775 01776 ast_mutex_lock(&rtp->bridge_lock); 01777 rtp->current_RTP_PT[pt].isAstFormat = 0; 01778 rtp->current_RTP_PT[pt].code = 0; 01779 ast_mutex_unlock(&rtp->bridge_lock); 01780 }
Definition at line 2949 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().
02950 { 02951 struct ast_frame *f; 02952 int codec; 02953 int hdrlen = 12; 02954 int subclass; 02955 02956 02957 /* If we have no peer, return immediately */ 02958 if (!rtp->them.sin_addr.s_addr) 02959 return 0; 02960 02961 /* If there is no data length, return immediately */ 02962 if (!_f->datalen) 02963 return 0; 02964 02965 /* Make sure we have enough space for RTP header */ 02966 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02967 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02968 return -1; 02969 } 02970 02971 subclass = _f->subclass; 02972 if (_f->frametype == AST_FRAME_VIDEO) 02973 subclass &= ~0x1; 02974 02975 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02976 if (codec < 0) { 02977 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02978 return -1; 02979 } 02980 02981 if (rtp->lasttxformat != subclass) { 02982 /* New format, reset the smoother */ 02983 if (option_debug) 02984 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02985 rtp->lasttxformat = subclass; 02986 if (rtp->smoother) 02987 ast_smoother_free(rtp->smoother); 02988 rtp->smoother = NULL; 02989 } 02990 02991 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 02992 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02993 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02994 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02995 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)); 02996 return -1; 02997 } 02998 if (fmt.flags) 02999 ast_smoother_set_flags(rtp->smoother, fmt.flags); 03000 if (option_debug) 03001 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)); 03002 } 03003 } 03004 if (rtp->smoother) { 03005 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 03006 ast_smoother_feed_be(rtp->smoother, _f); 03007 } else { 03008 ast_smoother_feed(rtp->smoother, _f); 03009 } 03010 03011 while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { 03012 ast_rtp_raw_write(rtp, f, codec); 03013 } 03014 } else { 03015 /* Don't buffer outgoing frames; send them one-per-packet: */ 03016 if (_f->offset < hdrlen) { 03017 f = ast_frdup(_f); 03018 } else { 03019 f = _f; 03020 } 03021 if (f->data) { 03022 ast_rtp_raw_write(rtp, f, codec); 03023 } 03024 if (f != _f) 03025 ast_frfree(f); 03026 } 03027 03028 return 0; 03029 }
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 3059 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().
03060 { 03061 struct ast_frame *fr = NULL; 03062 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03063 int oldcodec0 = codec0, oldcodec1 = codec1; 03064 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 03065 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 03066 03067 /* Set it up so audio goes directly between the two endpoints */ 03068 03069 /* Test the first channel */ 03070 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 03071 ast_rtp_get_peer(p1, &ac1); 03072 if (vp1) 03073 ast_rtp_get_peer(vp1, &vac1); 03074 } else 03075 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 03076 03077 /* Test the second channel */ 03078 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 03079 ast_rtp_get_peer(p0, &ac0); 03080 if (vp0) 03081 ast_rtp_get_peer(vp0, &vac0); 03082 } else 03083 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 03084 03085 /* Now we can unlock and move into our loop */ 03086 ast_channel_unlock(c0); 03087 ast_channel_unlock(c1); 03088 03089 /* Throw our channels into the structure and enter the loop */ 03090 cs[0] = c0; 03091 cs[1] = c1; 03092 cs[2] = NULL; 03093 for (;;) { 03094 /* Check if anything changed */ 03095 if ((c0->tech_pvt != pvt0) || 03096 (c1->tech_pvt != pvt1) || 03097 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03098 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03099 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03100 if (c0->tech_pvt == pvt0) 03101 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03102 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03103 if (c1->tech_pvt == pvt1) 03104 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03105 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03106 return AST_BRIDGE_RETRY; 03107 } 03108 03109 /* Check if they have changed their address */ 03110 ast_rtp_get_peer(p1, &t1); 03111 if (vp1) 03112 ast_rtp_get_peer(vp1, &vt1); 03113 if (pr1->get_codec) 03114 codec1 = pr1->get_codec(c1); 03115 ast_rtp_get_peer(p0, &t0); 03116 if (vp0) 03117 ast_rtp_get_peer(vp0, &vt0); 03118 if (pr0->get_codec) 03119 codec0 = pr0->get_codec(c0); 03120 if ((inaddrcmp(&t1, &ac1)) || 03121 (vp1 && inaddrcmp(&vt1, &vac1)) || 03122 (codec1 != oldcodec1)) { 03123 if (option_debug > 1) { 03124 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03125 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 03126 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 03127 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 03128 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 03129 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 03130 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 03131 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 03132 } 03133 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))) 03134 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 03135 memcpy(&ac1, &t1, sizeof(ac1)); 03136 memcpy(&vac1, &vt1, sizeof(vac1)); 03137 oldcodec1 = codec1; 03138 } 03139 if ((inaddrcmp(&t0, &ac0)) || 03140 (vp0 && inaddrcmp(&vt0, &vac0)) || 03141 (codec0 != oldcodec0)) { 03142 if (option_debug > 1) { 03143 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03144 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 03145 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 03146 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 03147 } 03148 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))) 03149 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 03150 memcpy(&ac0, &t0, sizeof(ac0)); 03151 memcpy(&vac0, &vt0, sizeof(vac0)); 03152 oldcodec0 = codec0; 03153 } 03154 03155 /* Wait for frame to come in on the channels */ 03156 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03157 if (!timeoutms) { 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 return AST_BRIDGE_RETRY; 03163 } 03164 if (option_debug) 03165 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 03166 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03167 break; 03168 continue; 03169 } 03170 fr = ast_read(who); 03171 other = (who == c0) ? c1 : c0; 03172 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03173 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 03174 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 03175 /* Break out of bridge */ 03176 *fo = fr; 03177 *rc = who; 03178 if (option_debug) 03179 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03180 if (c0->tech_pvt == pvt0) 03181 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03182 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03183 if (c1->tech_pvt == pvt1) 03184 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03185 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03186 return AST_BRIDGE_COMPLETE; 03187 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03188 if ((fr->subclass == AST_CONTROL_HOLD) || 03189 (fr->subclass == AST_CONTROL_UNHOLD) || 03190 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03191 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03192 if (fr->subclass == AST_CONTROL_HOLD) { 03193 /* If we someone went on hold we want the other side to reinvite back to us */ 03194 if (who == c0) 03195 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 03196 else 03197 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 03198 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03199 /* If they went off hold they should go back to being direct */ 03200 if (who == c0) 03201 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 03202 else 03203 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 03204 } 03205 /* Update local address information */ 03206 ast_rtp_get_peer(p0, &t0); 03207 memcpy(&ac0, &t0, sizeof(ac0)); 03208 ast_rtp_get_peer(p1, &t1); 03209 memcpy(&ac1, &t1, sizeof(ac1)); 03210 /* Update codec information */ 03211 if (pr0->get_codec && c0->tech_pvt) 03212 oldcodec0 = codec0 = pr0->get_codec(c0); 03213 if (pr1->get_codec && c1->tech_pvt) 03214 oldcodec1 = codec1 = pr1->get_codec(c1); 03215 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03216 ast_frfree(fr); 03217 } else { 03218 *fo = fr; 03219 *rc = who; 03220 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03221 return AST_BRIDGE_COMPLETE; 03222 } 03223 } else { 03224 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03225 (fr->frametype == AST_FRAME_DTMF_END) || 03226 (fr->frametype == AST_FRAME_VOICE) || 03227 (fr->frametype == AST_FRAME_VIDEO) || 03228 (fr->frametype == AST_FRAME_IMAGE) || 03229 (fr->frametype == AST_FRAME_HTML) || 03230 (fr->frametype == AST_FRAME_MODEM) || 03231 (fr->frametype == AST_FRAME_TEXT)) { 03232 ast_write(other, fr); 03233 } 03234 ast_frfree(fr); 03235 } 03236 /* Swap priority */ 03237 cs[2] = cs[0]; 03238 cs[0] = cs[1]; 03239 cs[1] = cs[2]; 03240 } 03241 03242 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03243 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03244 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03245 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03246 03247 return AST_BRIDGE_FAILED; 03248 }
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 3346 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().
03347 { 03348 struct ast_frame *fr = NULL; 03349 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03350 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03351 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03352 int p0_callback = 0, p1_callback = 0; 03353 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03354 03355 /* Okay, setup each RTP structure to do P2P forwarding */ 03356 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03357 p2p_set_bridge(p0, p1); 03358 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03359 p2p_set_bridge(p1, p0); 03360 03361 /* Activate callback modes if possible */ 03362 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03363 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03364 03365 /* Now let go of the channel locks and be on our way */ 03366 ast_channel_unlock(c0); 03367 ast_channel_unlock(c1); 03368 03369 /* Go into a loop forwarding frames until we don't need to anymore */ 03370 cs[0] = c0; 03371 cs[1] = c1; 03372 cs[2] = NULL; 03373 for (;;) { 03374 /* If the underlying formats have changed force this bridge to break */ 03375 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 03376 ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n"); 03377 res = AST_BRIDGE_FAILED_NOWARN; 03378 break; 03379 } 03380 /* Check if anything changed */ 03381 if ((c0->tech_pvt != pvt0) || 03382 (c1->tech_pvt != pvt1) || 03383 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03384 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03385 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03386 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03387 ast_frfree(fr); 03388 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03389 ast_frfree(fr); 03390 res = AST_BRIDGE_RETRY; 03391 break; 03392 } 03393 /* Wait on a channel to feed us a frame */ 03394 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03395 if (!timeoutms) { 03396 res = AST_BRIDGE_RETRY; 03397 break; 03398 } 03399 if (option_debug) 03400 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03401 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03402 break; 03403 continue; 03404 } 03405 /* Read in frame from channel */ 03406 fr = ast_read(who); 03407 other = (who == c0) ? c1 : c0; 03408 /* Dependong on the frame we may need to break out of our bridge */ 03409 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03410 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03411 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03412 /* Record received frame and who */ 03413 *fo = fr; 03414 *rc = who; 03415 if (option_debug) 03416 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03417 res = AST_BRIDGE_COMPLETE; 03418 break; 03419 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03420 if ((fr->subclass == AST_CONTROL_HOLD) || 03421 (fr->subclass == AST_CONTROL_UNHOLD) || 03422 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03423 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03424 /* If we are going on hold, then break callback mode and P2P bridging */ 03425 if (fr->subclass == AST_CONTROL_HOLD) { 03426 if (p0_callback) 03427 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03428 if (p1_callback) 03429 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03430 p2p_set_bridge(p0, NULL); 03431 p2p_set_bridge(p1, NULL); 03432 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03433 /* If we are off hold, then go back to callback mode and P2P bridging */ 03434 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03435 p2p_set_bridge(p0, p1); 03436 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03437 p2p_set_bridge(p1, p0); 03438 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03439 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03440 } 03441 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03442 ast_frfree(fr); 03443 } else { 03444 *fo = fr; 03445 *rc = who; 03446 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03447 res = AST_BRIDGE_COMPLETE; 03448 break; 03449 } 03450 } else { 03451 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03452 (fr->frametype == AST_FRAME_DTMF_END) || 03453 (fr->frametype == AST_FRAME_VOICE) || 03454 (fr->frametype == AST_FRAME_VIDEO) || 03455 (fr->frametype == AST_FRAME_IMAGE) || 03456 (fr->frametype == AST_FRAME_HTML) || 03457 (fr->frametype == AST_FRAME_MODEM) || 03458 (fr->frametype == AST_FRAME_TEXT)) { 03459 ast_write(other, fr); 03460 } 03461 03462 ast_frfree(fr); 03463 } 03464 /* Swap priority */ 03465 cs[2] = cs[0]; 03466 cs[0] = cs[1]; 03467 cs[1] = cs[2]; 03468 } 03469 03470 /* If we are totally avoiding the core, then restore our link to it */ 03471 if (p0_callback) 03472 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03473 if (p1_callback) 03474 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03475 03476 /* Break out of the direct bridge */ 03477 p2p_set_bridge(p0, NULL); 03478 p2p_set_bridge(p1, NULL); 03479 03480 return res; 03481 }
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 1128 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().
01129 { 01130 int res = 0, payload = 0, bridged_payload = 0, mark; 01131 struct rtpPayloadType rtpPT; 01132 int reconstruct = ntohl(rtpheader[0]); 01133 01134 /* Get fields from packet */ 01135 payload = (reconstruct & 0x7f0000) >> 16; 01136 mark = (((reconstruct & 0x800000) >> 23) != 0); 01137 01138 /* Check what the payload value should be */ 01139 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01140 01141 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01142 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01143 return -1; 01144 01145 /* Otherwise adjust bridged payload to match */ 01146 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01147 01148 /* 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 */ 01149 if (!bridged->current_RTP_PT[bridged_payload].code) 01150 return -1; 01151 01152 01153 /* If the mark bit has not been sent yet... do it now */ 01154 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01155 mark = 1; 01156 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01157 } 01158 01159 /* Reconstruct part of the packet */ 01160 reconstruct &= 0xFF80FFFF; 01161 reconstruct |= (bridged_payload << 16); 01162 reconstruct |= (mark << 23); 01163 rtpheader[0] = htonl(reconstruct); 01164 01165 /* Send the packet back out */ 01166 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01167 if (res < 0) { 01168 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01169 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)); 01170 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01171 if (option_debug || rtpdebug) 01172 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)); 01173 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01174 } 01175 return 0; 01176 } else if (rtp_debug_test_addr(&bridged->them)) 01177 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); 01178 01179 return 0; 01180 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1085 of file rtp.c.
References ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtp::rxtransit, sanitize_tv(), ast_rtp::seedrxts, and ast_frame::subclass.
Referenced by ast_rtp_read(), and schedule_delivery().
01086 { 01087 struct timeval now; 01088 double transit; 01089 double current_time; 01090 double d; 01091 double dtv; 01092 double prog; 01093 int rate = rtp_get_rate(rtp->f.subclass); 01094 01095 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01096 gettimeofday(&rtp->rxcore, NULL); 01097 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01098 /* map timestamp to a real time */ 01099 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01100 rtp->rxcore.tv_sec -= timestamp / rate; 01101 rtp->rxcore.tv_usec -= (timestamp % rate) * 125; 01102 /* Round to 0.1ms for nice, pretty timestamps */ 01103 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01104 sanitize_tv(&rtp->rxcore); 01105 } 01106 01107 gettimeofday(&now,NULL); 01108 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01109 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / rate; 01110 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % rate) * 125; 01111 sanitize_tv(tv); 01112 prog = (double)((timestamp-rtp->seedrxts)/(float)(rate)); 01113 dtv = (double)rtp->drxcore + (double)(prog); 01114 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01115 transit = current_time - dtv; 01116 d = transit - rtp->rxtransit; 01117 rtp->rxtransit = transit; 01118 if (d<0) 01119 d=-d; 01120 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01121 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01122 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01123 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01124 rtp->rtcp->minrxjitter = rtp->rxjitter; 01125 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2319 of file rtp.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), t, and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02320 { 02321 struct timeval t; 02322 long ms; 02323 if (ast_tvzero(rtp->txcore)) { 02324 rtp->txcore = ast_tvnow(); 02325 /* Round to 20ms for nice, pretty timestamps */ 02326 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02327 } 02328 /* Use previous txcore if available */ 02329 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02330 ms = ast_tvdiff_ms(t, rtp->txcore); 02331 if (ms < 0) 02332 ms = 0; 02333 /* Use what we just got for next time */ 02334 rtp->txcore = t; 02335 return (unsigned int) ms; 02336 }
static struct ast_frame* create_dtmf_frame | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static] |
Definition at line 626 of file rtp.c.
References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), AST_LIST_NEXT, 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().
00627 { 00628 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00629 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00630 if (option_debug) 00631 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00632 rtp->resp = 0; 00633 return &ast_null_frame; 00634 } 00635 if (option_debug) 00636 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00637 if (rtp->resp == 'X') { 00638 rtp->f.frametype = AST_FRAME_CONTROL; 00639 rtp->f.subclass = AST_CONTROL_FLASH; 00640 } else { 00641 rtp->f.frametype = type; 00642 rtp->f.subclass = rtp->resp; 00643 } 00644 rtp->f.datalen = 0; 00645 rtp->f.samples = 0; 00646 rtp->f.mallocd = 0; 00647 rtp->f.src = "RTP"; 00648 AST_LIST_NEXT(&rtp->f, frame_list) = NULL; 00649 return &rtp->f; 00650 00651 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 1583 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().
01584 { 01585 struct ast_rtp_protocol *cur = NULL; 01586 01587 AST_LIST_LOCK(&protos); 01588 AST_LIST_TRAVERSE(&protos, cur, list) { 01589 if (cur->type == chan->tech->type) 01590 break; 01591 } 01592 AST_LIST_UNLOCK(&protos); 01593 01594 return cur; 01595 }
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 3317 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.
03318 { 03319 ast_channel_lock(chan); 03320 03321 /* Remove the callback from the IO context */ 03322 ast_io_remove(rtp->io, iod[0]); 03323 03324 /* Restore file descriptors */ 03325 chan->fds[0] = fds[0]; 03326 ast_channel_unlock(chan); 03327 03328 /* Restore callback mode if previously used */ 03329 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03330 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03331 03332 return 0; 03333 }
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 3336 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03337 { 03338 ast_mutex_lock(&rtp0->bridge_lock); 03339 rtp0->bridged = rtp1; 03340 ast_mutex_unlock(&rtp0->bridge_lock); 03341 03342 return; 03343 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 680 of file rtp.c.
References AST_FRAME_DTMF_END, ast_log(), create_dtmf_frame(), ast_rtp::dtmf_timeout, f, LOG_DEBUG, option_debug, and ast_rtp::resp.
Referenced by ast_rtp_read().
00681 { 00682 unsigned int event; 00683 char resp = 0; 00684 struct ast_frame *f = NULL; 00685 event = ntohl(*((unsigned int *)(data))); 00686 event &= 0x001F; 00687 if (option_debug > 2 || rtpdebug) 00688 ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len); 00689 if (event < 10) { 00690 resp = '0' + event; 00691 } else if (event < 11) { 00692 resp = '*'; 00693 } else if (event < 12) { 00694 resp = '#'; 00695 } else if (event < 16) { 00696 resp = 'A' + (event - 12); 00697 } else if (event < 17) { 00698 resp = 'X'; 00699 } 00700 if (rtp->resp && (rtp->resp != resp)) { 00701 f = create_dtmf_frame(rtp, AST_FRAME_DTMF_END); 00702 } 00703 rtp->resp = resp; 00704 rtp->dtmf_timeout = 0; 00705 return f; 00706 }
static void process_rfc2833 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp, | |||
struct frame_list * | frames | |||
) | [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 | ||
frames |
Definition at line 720 of file rtp.c.
References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup(), AST_LIST_INSERT_TAIL, ast_log(), ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), create_dtmf_frame(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, f, FLAG_DTMF_COMPENSATE, frames, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_get_rate(), and ast_frame::samples.
Referenced by ast_rtp_read().
00721 { 00722 unsigned int event; 00723 unsigned int event_end; 00724 unsigned int samples; 00725 char resp = 0; 00726 struct ast_frame *f = NULL; 00727 00728 /* Figure out event, event end, and samples */ 00729 event = ntohl(*((unsigned int *)(data))); 00730 event >>= 24; 00731 event_end = ntohl(*((unsigned int *)(data))); 00732 event_end <<= 8; 00733 event_end >>= 24; 00734 samples = ntohl(*((unsigned int *)(data))); 00735 samples &= 0xFFFF; 00736 00737 /* Print out debug if turned on */ 00738 if (rtpdebug || option_debug > 2) 00739 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00740 00741 /* Figure out what digit was pressed */ 00742 if (event < 10) { 00743 resp = '0' + event; 00744 } else if (event < 11) { 00745 resp = '*'; 00746 } else if (event < 12) { 00747 resp = '#'; 00748 } else if (event < 16) { 00749 resp = 'A' + (event - 12); 00750 } else if (event < 17) { /* Event 16: Hook flash */ 00751 resp = 'X'; 00752 } else { 00753 /* Not a supported event */ 00754 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 00755 return; 00756 } 00757 00758 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00759 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 00760 rtp->resp = resp; 00761 rtp->dtmf_timeout = 0; 00762 f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_END)); 00763 f->len = 0; 00764 rtp->lastevent = timestamp; 00765 AST_LIST_INSERT_TAIL(frames, f, frame_list); 00766 } 00767 } else { 00768 /* The duration parameter measures the complete 00769 duration of the event (from the beginning) - RFC2833. 00770 Account for the fact that duration is only 16 bits long 00771 (about 8 seconds at 8000 Hz) and can wrap if digit 00772 is held for too long. */ 00773 unsigned int new_duration = rtp->dtmf_duration; 00774 unsigned int last_duration = new_duration & 0xFFFF; 00775 00776 if (last_duration > 64000 && samples < last_duration) 00777 new_duration += 0xFFFF + 1; 00778 new_duration = (new_duration & ~0xFFFF) | samples; 00779 00780 /* The second portion of this check is to not mistakenly 00781 * stop accepting DTMF if the seqno rolls over beyond 00782 * 65535. 00783 */ 00784 if (rtp->lastevent > seqno && rtp->lastevent - seqno < 50) { 00785 /* Out of order frame. Processing this can cause us to 00786 * improperly duplicate incoming DTMF, so just drop 00787 * this. 00788 */ 00789 return; 00790 } 00791 00792 if (event_end & 0x80) { 00793 /* End event */ 00794 if ((rtp->lastevent != seqno) && rtp->resp) { 00795 rtp->dtmf_duration = new_duration; 00796 f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_END)); 00797 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 00798 rtp->resp = 0; 00799 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 00800 AST_LIST_INSERT_TAIL(frames, f, frame_list); 00801 } 00802 } else { 00803 /* Begin/continuation */ 00804 00805 if (rtp->resp && rtp->resp != resp) { 00806 /* Another digit already began. End it */ 00807 f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_END)); 00808 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 00809 rtp->resp = 0; 00810 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 00811 AST_LIST_INSERT_TAIL(frames, f, frame_list); 00812 } 00813 00814 00815 if (rtp->resp) { 00816 /* Digit continues */ 00817 rtp->dtmf_duration = new_duration; 00818 } else { 00819 /* New digit began */ 00820 rtp->resp = resp; 00821 f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_BEGIN)); 00822 rtp->dtmf_duration = samples; 00823 AST_LIST_INSERT_TAIL(frames, f, frame_list); 00824 } 00825 00826 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout; 00827 } 00828 00829 rtp->lastevent = seqno; 00830 } 00831 }
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 839 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().
00840 { 00841 struct ast_frame *f = NULL; 00842 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00843 totally help us out becuase we don't have an engine to keep it going and we are not 00844 guaranteed to have it every 20ms or anything */ 00845 if (rtpdebug) 00846 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00847 00848 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00849 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00850 ast_inet_ntoa(rtp->them.sin_addr)); 00851 ast_set_flag(rtp, FLAG_3389_WARNING); 00852 } 00853 00854 /* Must have at least one byte */ 00855 if (!len) 00856 return NULL; 00857 if (len < 24) { 00858 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00859 rtp->f.datalen = len - 1; 00860 rtp->f.offset = AST_FRIENDLY_OFFSET; 00861 memcpy(rtp->f.data, data + 1, len - 1); 00862 } else { 00863 rtp->f.data = NULL; 00864 rtp->f.offset = 0; 00865 rtp->f.datalen = 0; 00866 } 00867 rtp->f.frametype = AST_FRAME_CNG; 00868 rtp->f.subclass = data[0] & 0x7f; 00869 rtp->f.samples = 0; 00870 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00871 f = &rtp->f; 00872 return f; 00873 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 666 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00667 { 00668 if (rtcpdebug == 0) 00669 return 0; 00670 if (rtcpdebugaddr.sin_addr.s_addr) { 00671 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00672 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00673 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00674 return 0; 00675 } 00676 return 1; 00677 }
static int rtcp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3756 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip().
03756 { 03757 if (argc != 2) { 03758 if (argc != 4) 03759 return RESULT_SHOWUSAGE; 03760 return rtcp_do_debug_ip(fd, argc, argv); 03761 } 03762 rtcpdebug = 1; 03763 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03764 ast_cli(fd, "RTCP Debugging Enabled\n"); 03765 return RESULT_SUCCESS; 03766 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3744 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip_deprecated().
03744 { 03745 if (argc != 3) { 03746 if (argc != 5) 03747 return RESULT_SHOWUSAGE; 03748 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03749 } 03750 rtcpdebug = 1; 03751 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03752 ast_cli(fd, "RTCP Debugging Enabled\n"); 03753 return RESULT_SUCCESS; 03754 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3701 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtcp_do_debug().
03702 { 03703 struct hostent *hp; 03704 struct ast_hostent ahp; 03705 int port = 0; 03706 char *p, *arg; 03707 if (argc != 4) 03708 return RESULT_SHOWUSAGE; 03709 03710 arg = argv[3]; 03711 p = strstr(arg, ":"); 03712 if (p) { 03713 *p = '\0'; 03714 p++; 03715 port = atoi(p); 03716 } 03717 hp = ast_gethostbyname(arg, &ahp); 03718 if (hp == NULL) 03719 return RESULT_SHOWUSAGE; 03720 rtcpdebugaddr.sin_family = AF_INET; 03721 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03722 rtcpdebugaddr.sin_port = htons(port); 03723 if (port == 0) 03724 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03725 else 03726 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03727 rtcpdebug = 1; 03728 return RESULT_SUCCESS; 03729 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3671 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().
03672 { 03673 struct hostent *hp; 03674 struct ast_hostent ahp; 03675 int port = 0; 03676 char *p, *arg; 03677 if (argc != 5) 03678 return RESULT_SHOWUSAGE; 03679 03680 arg = argv[4]; 03681 p = strstr(arg, ":"); 03682 if (p) { 03683 *p = '\0'; 03684 p++; 03685 port = atoi(p); 03686 } 03687 hp = ast_gethostbyname(arg, &ahp); 03688 if (hp == NULL) 03689 return RESULT_SHOWUSAGE; 03690 rtcpdebugaddr.sin_family = AF_INET; 03691 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03692 rtcpdebugaddr.sin_port = htons(port); 03693 if (port == 0) 03694 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03695 else 03696 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03697 rtcpdebug = 1; 03698 return RESULT_SUCCESS; 03699 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3777 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03777 { 03778 if (argc != 2) { 03779 return RESULT_SHOWUSAGE; 03780 } 03781 rtcpstats = 1; 03782 ast_cli(fd, "RTCP Stats Enabled\n"); 03783 return RESULT_SUCCESS; 03784 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3768 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03768 { 03769 if (argc != 3) { 03770 return RESULT_SHOWUSAGE; 03771 } 03772 rtcpstats = 1; 03773 ast_cli(fd, "RTCP Stats Enabled\n"); 03774 return RESULT_SUCCESS; 03775 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3804 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03805 { 03806 if (argc != 3) 03807 return RESULT_SHOWUSAGE; 03808 rtcpdebug = 0; 03809 ast_cli(fd,"RTCP Debugging Disabled\n"); 03810 return RESULT_SUCCESS; 03811 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3795 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03796 { 03797 if (argc != 4) 03798 return RESULT_SHOWUSAGE; 03799 rtcpdebug = 0; 03800 ast_cli(fd,"RTCP Debugging Disabled\n"); 03801 return RESULT_SUCCESS; 03802 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3822 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03823 { 03824 if (argc != 3) 03825 return RESULT_SHOWUSAGE; 03826 rtcpstats = 0; 03827 ast_cli(fd,"RTCP Stats Disabled\n"); 03828 return RESULT_SUCCESS; 03829 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3813 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03814 { 03815 if (argc != 4) 03816 return RESULT_SHOWUSAGE; 03817 rtcpstats = 0; 03818 ast_cli(fd,"RTCP Stats Disabled\n"); 03819 return RESULT_SUCCESS; 03820 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 653 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_with_duration(), and bridge_p2p_rtp_write().
00654 { 00655 if (rtpdebug == 0) 00656 return 0; 00657 if (rtpdebugaddr.sin_addr.s_addr) { 00658 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00659 && (rtpdebugaddr.sin_port != addr->sin_port)) 00660 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00661 return 0; 00662 } 00663 return 1; 00664 }
static int rtp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3731 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtp_do_debug_ip().
03732 { 03733 if (argc != 2) { 03734 if (argc != 4) 03735 return RESULT_SHOWUSAGE; 03736 return rtp_do_debug_ip(fd, argc, argv); 03737 } 03738 rtpdebug = 1; 03739 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03740 ast_cli(fd, "RTP Debugging Enabled\n"); 03741 return RESULT_SUCCESS; 03742 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3641 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtp_do_debug().
03642 { 03643 struct hostent *hp; 03644 struct ast_hostent ahp; 03645 int port = 0; 03646 char *p, *arg; 03647 03648 if (argc != 4) 03649 return RESULT_SHOWUSAGE; 03650 arg = argv[3]; 03651 p = strstr(arg, ":"); 03652 if (p) { 03653 *p = '\0'; 03654 p++; 03655 port = atoi(p); 03656 } 03657 hp = ast_gethostbyname(arg, &ahp); 03658 if (hp == NULL) 03659 return RESULT_SHOWUSAGE; 03660 rtpdebugaddr.sin_family = AF_INET; 03661 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03662 rtpdebugaddr.sin_port = htons(port); 03663 if (port == 0) 03664 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03665 else 03666 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03667 rtpdebug = 1; 03668 return RESULT_SUCCESS; 03669 }
static int rtp_get_rate | ( | int | subclass | ) | [static] |
Definition at line 530 of file rtp.c.
References AST_FORMAT_G722, and ast_format_rate().
Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_senddigit_end_with_duration(), calc_rxstamp(), and process_rfc2833().
00531 { 00532 return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass); 00533 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3786 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03787 { 03788 if (argc != 3) 03789 return RESULT_SHOWUSAGE; 03790 rtpdebug = 0; 03791 ast_cli(fd,"RTP Debugging Disabled\n"); 03792 return RESULT_SUCCESS; 03793 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1958 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01959 { 01960 int s; 01961 long flags; 01962 s = socket(AF_INET, SOCK_DGRAM, 0); 01963 if (s > -1) { 01964 flags = fcntl(s, F_GETFL); 01965 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01966 #ifdef SO_NO_CHECK 01967 if (nochecksums) 01968 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01969 #endif 01970 } 01971 return s; 01972 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 875 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and f.
Referenced by p2p_callback_disable().
00876 { 00877 struct ast_rtp *rtp = cbdata; 00878 struct ast_frame *f; 00879 f = ast_rtp_read(rtp); 00880 if (f) { 00881 if (rtp->callback) 00882 rtp->callback(rtp, f, rtp->data); 00883 } 00884 return 1; 00885 }
static void sanitize_tv | ( | struct timeval * | tv | ) | [static] |
static const char* stun_attr2str | ( | int | msg | ) | [static] |
Definition at line 305 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().
00306 { 00307 switch(msg) { 00308 case STUN_MAPPED_ADDRESS: 00309 return "Mapped Address"; 00310 case STUN_RESPONSE_ADDRESS: 00311 return "Response Address"; 00312 case STUN_CHANGE_REQUEST: 00313 return "Change Request"; 00314 case STUN_SOURCE_ADDRESS: 00315 return "Source Address"; 00316 case STUN_CHANGED_ADDRESS: 00317 return "Changed Address"; 00318 case STUN_USERNAME: 00319 return "Username"; 00320 case STUN_PASSWORD: 00321 return "Password"; 00322 case STUN_MESSAGE_INTEGRITY: 00323 return "Message Integrity"; 00324 case STUN_ERROR_CODE: 00325 return "Error Code"; 00326 case STUN_UNKNOWN_ATTRIBUTES: 00327 return "Unknown Attributes"; 00328 case STUN_REFLECTED_FROM: 00329 return "Reflected From"; 00330 } 00331 return "Non-RFC3489 Attribute"; 00332 }
static int stun_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3831 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03832 { 03833 if (argc != 2) { 03834 return RESULT_SHOWUSAGE; 03835 } 03836 stundebug = 1; 03837 ast_cli(fd, "STUN Debugging Enabled\n"); 03838 return RESULT_SUCCESS; 03839 }
static int stun_handle_packet | ( | int | s, | |
struct sockaddr_in * | src, | |||
unsigned char * | data, | |||
size_t | len | |||
) | [static] |
Definition at line 429 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().
00430 { 00431 struct stun_header *resp, *hdr = (struct stun_header *)data; 00432 struct stun_attr *attr; 00433 struct stun_state st; 00434 int ret = STUN_IGNORE; 00435 unsigned char respdata[1024]; 00436 int resplen, respleft; 00437 00438 if (len < sizeof(struct stun_header)) { 00439 if (option_debug) 00440 ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header)); 00441 return -1; 00442 } 00443 if (stundebug) 00444 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen)); 00445 if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) { 00446 if (option_debug) 00447 ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header)); 00448 } else 00449 len = ntohs(hdr->msglen); 00450 data += sizeof(struct stun_header); 00451 memset(&st, 0, sizeof(st)); 00452 while(len) { 00453 if (len < sizeof(struct stun_attr)) { 00454 if (option_debug) 00455 ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr)); 00456 break; 00457 } 00458 attr = (struct stun_attr *)data; 00459 if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) { 00460 if (option_debug) 00461 ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len); 00462 break; 00463 } 00464 if (stun_process_attr(&st, attr)) { 00465 if (option_debug) 00466 ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00467 break; 00468 } 00469 /* Clear attribute in case previous entry was a string */ 00470 attr->attr = 0; 00471 data += ntohs(attr->len) + sizeof(struct stun_attr); 00472 len -= ntohs(attr->len) + sizeof(struct stun_attr); 00473 } 00474 /* Null terminate any string */ 00475 *data = '\0'; 00476 resp = (struct stun_header *)respdata; 00477 resplen = 0; 00478 respleft = sizeof(respdata) - sizeof(struct stun_header); 00479 resp->id = hdr->id; 00480 resp->msgtype = 0; 00481 resp->msglen = 0; 00482 attr = (struct stun_attr *)resp->ies; 00483 if (!len) { 00484 switch(ntohs(hdr->msgtype)) { 00485 case STUN_BINDREQ: 00486 if (stundebug) 00487 ast_verbose("STUN Bind Request, username: %s\n", 00488 st.username ? st.username : "<none>"); 00489 if (st.username) 00490 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00491 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00492 resp->msglen = htons(resplen); 00493 resp->msgtype = htons(STUN_BINDRESP); 00494 stun_send(s, src, resp); 00495 ret = STUN_ACCEPT; 00496 break; 00497 default: 00498 if (stundebug) 00499 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00500 } 00501 } 00502 return ret; 00503 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
Definition at line 286 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00287 { 00288 switch(msg) { 00289 case STUN_BINDREQ: 00290 return "Binding Request"; 00291 case STUN_BINDRESP: 00292 return "Binding Response"; 00293 case STUN_BINDERR: 00294 return "Binding Error Response"; 00295 case STUN_SECREQ: 00296 return "Shared Secret Request"; 00297 case STUN_SECRESP: 00298 return "Shared Secret Response"; 00299 case STUN_SECERR: 00300 return "Shared Secret Error Response"; 00301 } 00302 return "Non-RFC3489 Message"; 00303 }
static int stun_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3841 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03842 { 03843 if (argc != 3) 03844 return RESULT_SHOWUSAGE; 03845 stundebug = 0; 03846 ast_cli(fd, "STUN Debugging Disabled\n"); 03847 return RESULT_SUCCESS; 03848 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 339 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().
00340 { 00341 if (stundebug) 00342 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00343 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00344 switch(ntohs(attr->attr)) { 00345 case STUN_USERNAME: 00346 state->username = (const char *) (attr->value); 00347 break; 00348 case STUN_PASSWORD: 00349 state->password = (const char *) (attr->value); 00350 break; 00351 default: 00352 if (stundebug) 00353 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00354 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00355 } 00356 return 0; 00357 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
Definition at line 396 of file rtp.c.
References ast_random(), stun_trans_id::id, and stun_header::id.
Referenced by ast_rtp_stun_request().
00397 { 00398 int x; 00399 for (x=0;x<4;x++) 00400 req->id.id[x] = ast_random(); 00401 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
Definition at line 390 of file rtp.c.
References stun_header::msglen.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00391 { 00392 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00393 (struct sockaddr *)dst, sizeof(*dst)); 00394 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 508 of file rtp.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00509 { 00510 unsigned int sec, usec, frac; 00511 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00512 usec = tv.tv_usec; 00513 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00514 *msw = sec; 00515 *lsw = frac; 00516 }
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 1454 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 1489 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 1455 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), ast_call_forward(), ast_format_str_reduce(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), find_subscription_type(), g723_len(), get_sdp_line(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), parse_information(), parse_setup(), process_sdp(), sla_load_config(), subscription_type2str(), and yyparse().