#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"
Go to the source code of this file.
Data Structures | |
struct | ast_rtcp |
Structure defining an RTCP session. More... | |
struct | ast_rtp |
RTP session description. More... | |
struct | protos |
List of current sessions. More... | |
struct | rtpPayloadType |
Structure representing a RTP session.The value of each payload format mapping:. More... | |
struct | stun_addr |
struct | stun_attr |
struct | stun_header |
struct | stun_state |
struct | stun_trans_id |
Defines | |
#define | DEFAULT_DTMF_TIMEOUT 3000 |
#define | FLAG_3389_WARNING (1 << 0) |
#define | FLAG_CALLBACK_MODE (1 << 6) |
#define | FLAG_DTMF_COMPENSATE (1 << 7) |
#define | FLAG_HAS_DTMF (1 << 3) |
#define | FLAG_HAS_STUN (1 << 8) |
#define | FLAG_NAT_ACTIVE (3 << 1) |
#define | FLAG_NAT_INACTIVE (0 << 1) |
#define | FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
#define | FLAG_P2P_NEED_DTMF (1 << 5) |
#define | FLAG_P2P_SENT_MARK (1 << 4) |
#define | MAX_TIMESTAMP_SKEW 640 |
#define | RTCP_DEFAULT_INTERVALMS 5000 |
#define | RTCP_MAX_INTERVALMS 60000 |
#define | RTCP_MIN_INTERVALMS 500 |
#define | RTCP_PT_APP 204 |
#define | RTCP_PT_BYE 203 |
#define | RTCP_PT_FUR 192 |
#define | RTCP_PT_RR 201 |
#define | RTCP_PT_SDES 202 |
#define | RTCP_PT_SR 200 |
#define | RTP_MTU 1200 |
#define | RTP_SEQ_MOD (1<<16) |
#define | STUN_ACCEPT (1) |
#define | STUN_BINDERR 0x0111 |
#define | STUN_BINDREQ 0x0001 |
#define | STUN_BINDRESP 0x0101 |
#define | STUN_CHANGE_REQUEST 0x0003 |
#define | STUN_CHANGED_ADDRESS 0x0005 |
#define | STUN_ERROR_CODE 0x0009 |
#define | STUN_IGNORE (0) |
#define | STUN_MAPPED_ADDRESS 0x0001 |
#define | STUN_MESSAGE_INTEGRITY 0x0008 |
#define | STUN_PASSWORD 0x0007 |
#define | STUN_REFLECTED_FROM 0x000b |
#define | STUN_RESPONSE_ADDRESS 0x0002 |
#define | STUN_SECERR 0x0112 |
#define | STUN_SECREQ 0x0002 |
#define | STUN_SECRESP 0x0102 |
#define | STUN_SOURCE_ADDRESS 0x0004 |
#define | STUN_UNKNOWN_ATTRIBUTES 0x000a |
#define | STUN_USERNAME 0x0006 |
Functions | |
static void | append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left) |
static void | append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left) |
static unsigned int | ast_rtcp_calc_interval (struct ast_rtp *rtp) |
int | ast_rtcp_fd (struct ast_rtp *rtp) |
static struct ast_rtcp * | ast_rtcp_new (void) |
Initialize a new RTCP session. | |
ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
int | ast_rtcp_send_h261fur (void *data) |
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP. | |
static int | ast_rtcp_write (const void *data) |
Write and RTCP packet to the far end. | |
static int | ast_rtcp_write_rr (const void *data) |
Send RTCP recepient's report. | |
static int | ast_rtcp_write_sr (const void *data) |
Send RTCP sender's report. | |
size_t | ast_rtp_alloc_size (void) |
Get the amount of space required to hold an RTP session. | |
enum ast_bridge_result | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk. | |
int | ast_rtp_codec_getformat (int pt) |
ast_codec_pref * | ast_rtp_codec_getpref (struct ast_rtp *rtp) |
int | ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs) |
void | ast_rtp_destroy (struct ast_rtp *rtp) |
int | ast_rtp_early_bridge (struct ast_channel *dest, struct ast_channel *src) |
If possible, create an early bridge directly between the devices without having to send a re-invite later. | |
int | ast_rtp_fd (struct ast_rtp *rtp) |
ast_rtp * | ast_rtp_get_bridged (struct ast_rtp *rtp) |
void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs. | |
int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
char * | ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual) |
Return RTCP quality string. | |
int | ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp) |
Get rtp hold timeout. | |
int | ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp) |
Get RTP keepalive interval. | |
int | ast_rtp_get_rtptimeout (struct ast_rtp *rtp) |
Get rtp timeout. | |
void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
int | ast_rtp_getnat (struct ast_rtp *rtp) |
void | ast_rtp_init (void) |
Initialize the RTP system in Asterisk. | |
int | ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code) |
Looks up an RTP code out of our *static* outbound list. | |
char * | ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options) |
Build a string of MIME subtype names from a capability list. | |
const char * | ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code, enum ast_rtp_options options) |
Mapping an Asterisk code into a MIME subtype (string):. | |
rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
Mapping between RTP payload format codes and Asterisk codes:. | |
int | ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media) |
ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
Initializate a RTP session. | |
void | ast_rtp_new_init (struct ast_rtp *rtp) |
Initialize a new RTP structure. | |
void | ast_rtp_new_source (struct ast_rtp *rtp) |
ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr) |
Initializate a RTP session using an in_addr structure. | |
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
Register interface to channel driver. | |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
Unregister interface to channel driver. | |
void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
Setting RTP payload types from lines in a SDP description:. | |
void | ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src) |
Copy payload types between RTP structures. | |
void | ast_rtp_pt_default (struct ast_rtp *rtp) |
Set payload types to defaults. | |
static int | ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec) |
ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
int | ast_rtp_reload (void) |
void | ast_rtp_reset (struct ast_rtp *rtp) |
int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
generate comfort noice (CNG) | |
int | ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit) |
Send begin frames for DTMF. | |
static int | ast_rtp_senddigit_continuation (struct ast_rtp *rtp) |
Send continuation frame for DTMF. | |
int | ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit) |
Send end packets for DTMF. | |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
Activate payload type. | |
void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
void | ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout) |
Set rtp hold timeout. | |
void | ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period) |
set RTP keepalive interval | |
int | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options) |
Initiate payload type to a known MIME media type for a codec. | |
void | ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout) |
Set rtp timeout. | |
void | ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp) |
void | ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf) |
Indicate whether this RTP session is carrying DTMF or not. | |
void | ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate) |
Compensate for devices that send RFC2833 packets all at once. | |
void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
void | ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable) |
Enable STUN capability. | |
int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
void | ast_rtp_stop (struct ast_rtp *rtp) |
void | ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username) |
void | ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt) |
clear payload type | |
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f) |
static enum ast_bridge_result | bridge_native_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1) |
Bridge loop for true native bridge (reinvite). | |
static enum ast_bridge_result | bridge_p2p_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1) |
Bridge loop for partial native bridge (packet2packet). | |
static int | bridge_p2p_rtp_write (struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen) |
Perform a Packet2Packet RTP write. | |
static void | calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark) |
static unsigned int | calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery) |
static struct ast_rtp_protocol * | get_proto (struct ast_channel *chan) |
Get channel driver interface structure. | |
static int | p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod) |
Helper function to switch a channel and RTP stream out of callback mode. | |
static int | p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod) |
P2P RTP Callback. | |
static void | p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1) |
Helper function that sets what an RTP structure is bridged to. | |
static struct ast_frame * | process_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len) |
static struct ast_frame * | process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp) |
Process RTP DTMF and events according to RFC 2833. | |
static struct ast_frame * | process_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len) |
Process Comfort Noise RTP. | |
static int | rtcp_debug_test_addr (struct sockaddr_in *addr) |
static int | rtcp_do_debug (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_ip (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_ip_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_do_stats (int fd, int argc, char *argv[]) |
static int | rtcp_do_stats_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_no_debug (int fd, int argc, char *argv[]) |
static int | rtcp_no_debug_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_no_stats (int fd, int argc, char *argv[]) |
static int | rtcp_no_stats_deprecated (int fd, int argc, char *argv[]) |
static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
static int | rtp_do_debug (int fd, int argc, char *argv[]) |
static int | rtp_do_debug_ip (int fd, int argc, char *argv[]) |
static int | rtp_no_debug (int fd, int argc, char *argv[]) |
static int | rtp_socket (void) |
static int | rtpread (int *id, int fd, short events, void *cbdata) |
static struct ast_frame * | send_dtmf (struct ast_rtp *rtp, enum ast_frame_type type) |
static const char * | stun_attr2str (int msg) |
static int | stun_do_debug (int fd, int argc, char *argv[]) |
static int | stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len) |
static const char * | stun_msg2str (int msg) |
static int | stun_no_debug (int fd, int argc, char *argv[]) |
static int | stun_process_attr (struct stun_state *state, struct stun_attr *attr) |
static void | stun_req_id (struct stun_header *req) |
static int | stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp) |
static void | timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw) |
Variables | |
static struct ast_cli_entry | cli_rtp [] |
static struct ast_cli_entry | cli_rtp_no_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_debug_ip_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_no_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_no_stats_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_stats_deprecated |
static struct ast_cli_entry | cli_stun_no_debug_deprecated |
static char | debug_usage [] |
static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
struct { | |
rtpPayloadType payloadType | |
char * subtype | |
char * type | |
} | mimeTypes [] |
static char | no_debug_usage [] |
static char | rtcp_debug_usage [] |
static char | rtcp_no_debug_usage [] |
static char | rtcp_no_stats_usage [] |
static char | rtcp_stats_usage [] |
static int | rtcpdebug |
static struct sockaddr_in | rtcpdebugaddr |
static int | rtcpinterval = RTCP_DEFAULT_INTERVALMS |
static int | rtcpstats |
static int | rtpdebug |
static struct sockaddr_in | rtpdebugaddr |
static int | rtpend |
static int | rtpstart |
static struct rtpPayloadType | static_RTP_PT [MAX_RTP_PT] |
static char | stun_debug_usage [] |
static char | stun_no_debug_usage [] |
static int | stundebug |
Definition in file rtp.c.
#define DEFAULT_DTMF_TIMEOUT 3000 |
#define FLAG_3389_WARNING (1 << 0) |
#define FLAG_CALLBACK_MODE (1 << 6) |
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 194 of file rtp.c.
Referenced by ast_rtp_setdtmfcompensate(), process_rfc2833(), and send_dtmf().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 190 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 187 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 188 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 189 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 191 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 261 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 273 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 366 of file rtp.c.
References stun_addr::addr.
Referenced by stun_handle_packet().
00367 { 00368 int size = sizeof(**attr) + 8; 00369 struct stun_addr *addr; 00370 if (*left > size) { 00371 (*attr)->attr = htons(attrval); 00372 (*attr)->len = htons(8); 00373 addr = (struct stun_addr *)((*attr)->value); 00374 addr->unused = 0; 00375 addr->family = 0x01; 00376 addr->port = sin->sin_port; 00377 addr->addr = sin->sin_addr.s_addr; 00378 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00379 *len += size; 00380 *left -= size; 00381 } 00382 }
static void append_attr_string | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
const char * | s, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 353 of file rtp.c.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00354 { 00355 int size = sizeof(**attr) + strlen(s); 00356 if (*left > size) { 00357 (*attr)->attr = htons(attrval); 00358 (*attr)->len = htons(strlen(s)); 00359 memcpy((*attr)->value, s, strlen(s)); 00360 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00361 *len += size; 00362 *left -= size; 00363 } 00364 }
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 524 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00525 { 00526 unsigned int interval; 00527 /*! \todo XXX Do a more reasonable calculation on this one 00528 * Look in RFC 3550 Section A.7 for an example*/ 00529 interval = rtcpinterval; 00530 return interval; 00531 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 517 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 1876 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().
01877 { 01878 struct ast_rtcp *rtcp; 01879 01880 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01881 return NULL; 01882 rtcp->s = rtp_socket(); 01883 if (option_debug > 3) 01884 ast_log(LOG_DEBUG, "socket RTPaux (RTCP) fd: %i\n", rtcp->s); 01885 rtcp->us.sin_family = AF_INET; 01886 rtcp->them.sin_family = AF_INET; 01887 rtcp->schedid = -1; 01888 01889 if (rtcp->s < 0) { 01890 free(rtcp); 01891 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01892 return NULL; 01893 } 01894 01895 return rtcp; 01896 }
Definition at line 825 of file rtp.c.
References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, f, ast_rtp::f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().
Referenced by oh323_read(), sip_rtp_read(), and skinny_rtp_read().
00826 { 00827 socklen_t len; 00828 int position, i, packetwords; 00829 int res; 00830 struct sockaddr_in sin; 00831 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00832 unsigned int *rtcpheader; 00833 int pt; 00834 struct timeval now; 00835 unsigned int length; 00836 int rc; 00837 double rttsec; 00838 uint64_t rtt = 0; 00839 unsigned int dlsr; 00840 unsigned int lsr; 00841 unsigned int msw; 00842 unsigned int lsw; 00843 unsigned int comp; 00844 struct ast_frame *f = &ast_null_frame; 00845 00846 if (!rtp || !rtp->rtcp) 00847 return &ast_null_frame; 00848 00849 len = sizeof(sin); 00850 00851 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00852 0, (struct sockaddr *)&sin, &len); 00853 if (option_debug > 2) 00854 ast_log(LOG_DEBUG, "socket RTCP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 00855 00856 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00857 00858 if (res < 0) { 00859 ast_assert(errno != EBADF); 00860 if (errno != EAGAIN) { 00861 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00862 ast_log(LOG_WARNING, "socket RTCP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 00863 return NULL; 00864 } 00865 return &ast_null_frame; 00866 } 00867 00868 packetwords = res / 4; 00869 00870 if (rtp->nat) { 00871 /* Send to whoever sent to us */ 00872 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00873 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00874 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00875 if (option_debug || rtpdebug) 00876 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)); 00877 } 00878 } 00879 00880 if (option_debug) 00881 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00882 00883 /* Process a compound packet */ 00884 position = 0; 00885 while (position < packetwords) { 00886 i = position; 00887 length = ntohl(rtcpheader[i]); 00888 pt = (length & 0xff0000) >> 16; 00889 rc = (length & 0x1f000000) >> 24; 00890 length &= 0xffff; 00891 00892 if ((i + length) > packetwords) { 00893 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00894 return &ast_null_frame; 00895 } 00896 00897 if (rtcp_debug_test_addr(&sin)) { 00898 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00899 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00900 ast_verbose("Reception reports: %d\n", rc); 00901 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00902 } 00903 00904 i += 2; /* Advance past header and ssrc */ 00905 00906 switch (pt) { 00907 case RTCP_PT_SR: 00908 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00909 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00910 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00911 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00912 00913 if (rtcp_debug_test_addr(&sin)) { 00914 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00915 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00916 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00917 } 00918 i += 5; 00919 if (rc < 1) 00920 break; 00921 /* Intentional fall through */ 00922 case RTCP_PT_RR: 00923 /* Don't handle multiple reception reports (rc > 1) yet */ 00924 /* Calculate RTT per RFC */ 00925 gettimeofday(&now, NULL); 00926 timeval2ntp(now, &msw, &lsw); 00927 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00928 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00929 lsr = ntohl(rtcpheader[i + 4]); 00930 dlsr = ntohl(rtcpheader[i + 5]); 00931 rtt = comp - lsr - dlsr; 00932 00933 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00934 sess->ee_delay = (eedelay * 1000) / 65536; */ 00935 if (rtt < 4294) { 00936 rtt = (rtt * 1000000) >> 16; 00937 } else { 00938 rtt = (rtt * 1000) >> 16; 00939 rtt *= 1000; 00940 } 00941 rtt = rtt / 1000.; 00942 rttsec = rtt / 1000.; 00943 00944 if (comp - dlsr >= lsr) { 00945 rtp->rtcp->accumulated_transit += rttsec; 00946 rtp->rtcp->rtt = rttsec; 00947 if (rtp->rtcp->maxrtt<rttsec) 00948 rtp->rtcp->maxrtt = rttsec; 00949 if (rtp->rtcp->minrtt>rttsec) 00950 rtp->rtcp->minrtt = rttsec; 00951 } else if (rtcp_debug_test_addr(&sin)) { 00952 ast_verbose("Internal RTCP NTP clock skew detected: " 00953 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 00954 "diff=%d\n", 00955 lsr, comp, dlsr, dlsr / 65536, 00956 (dlsr % 65536) * 1000 / 65536, 00957 dlsr - (comp - lsr)); 00958 } 00959 } 00960 00961 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00962 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00963 if (rtcp_debug_test_addr(&sin)) { 00964 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00965 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00966 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00967 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00968 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00969 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00970 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00971 if (rtt) 00972 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 00973 } 00974 break; 00975 case RTCP_PT_FUR: 00976 if (rtcp_debug_test_addr(&sin)) 00977 ast_verbose("Received an RTCP Fast Update Request\n"); 00978 rtp->f.frametype = AST_FRAME_CONTROL; 00979 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00980 rtp->f.datalen = 0; 00981 rtp->f.samples = 0; 00982 rtp->f.mallocd = 0; 00983 rtp->f.src = "RTP"; 00984 f = &rtp->f; 00985 break; 00986 case RTCP_PT_SDES: 00987 if (rtcp_debug_test_addr(&sin)) 00988 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00989 break; 00990 case RTCP_PT_BYE: 00991 if (rtcp_debug_test_addr(&sin)) 00992 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00993 break; 00994 default: 00995 if (option_debug) 00996 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)); 00997 break; 00998 } 00999 position += (length + 1); 01000 } 01001 01002 return f; 01003 }
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 2369 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02370 { 02371 struct ast_rtp *rtp = data; 02372 int res; 02373 02374 rtp->rtcp->sendfur = 1; 02375 res = ast_rtcp_write(data); 02376 02377 return res; 02378 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2586 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().
02587 { 02588 struct ast_rtp *rtp = (struct ast_rtp *)data; 02589 int res; 02590 02591 if (!rtp || !rtp->rtcp) 02592 return 0; 02593 02594 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02595 res = ast_rtcp_write_sr(data); 02596 else 02597 res = ast_rtcp_write_rr(data); 02598 02599 return res; 02600 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recepient's report.
Definition at line 2491 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().
02492 { 02493 struct ast_rtp *rtp = (struct ast_rtp *)data; 02494 int res; 02495 int len = 32; 02496 unsigned int lost; 02497 unsigned int extended; 02498 unsigned int expected; 02499 unsigned int expected_interval; 02500 unsigned int received_interval; 02501 int lost_interval; 02502 struct timeval now; 02503 unsigned int *rtcpheader; 02504 char bdata[1024]; 02505 struct timeval dlsr; 02506 int fraction; 02507 02508 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02509 return 0; 02510 02511 if (!rtp->rtcp->them.sin_addr.s_addr) { 02512 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02513 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02514 return 0; 02515 } 02516 02517 extended = rtp->cycles + rtp->lastrxseqno; 02518 expected = extended - rtp->seedrxseqno + 1; 02519 lost = expected - rtp->rxcount; 02520 expected_interval = expected - rtp->rtcp->expected_prior; 02521 rtp->rtcp->expected_prior = expected; 02522 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02523 rtp->rtcp->received_prior = rtp->rxcount; 02524 lost_interval = expected_interval - received_interval; 02525 if (expected_interval == 0 || lost_interval <= 0) 02526 fraction = 0; 02527 else 02528 fraction = (lost_interval << 8) / expected_interval; 02529 gettimeofday(&now, NULL); 02530 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02531 rtcpheader = (unsigned int *)bdata; 02532 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02533 rtcpheader[1] = htonl(rtp->ssrc); 02534 rtcpheader[2] = htonl(rtp->themssrc); 02535 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02536 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02537 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02538 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02539 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02540 02541 if (rtp->rtcp->sendfur) { 02542 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02543 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02544 len += 8; 02545 rtp->rtcp->sendfur = 0; 02546 } 02547 02548 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02549 it can change mid call, and SDES can't) */ 02550 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02551 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02552 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02553 len += 12; 02554 02555 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02556 02557 if (res < 0) { 02558 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02559 /* Remove the scheduler */ 02560 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02561 return 0; 02562 } 02563 02564 rtp->rtcp->rr_count++; 02565 02566 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02567 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02568 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02569 " IA jitter: %.4f\n" 02570 " Their last SR: %u\n" 02571 " DLSR: %4.4f (sec)\n\n", 02572 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02573 ntohs(rtp->rtcp->them.sin_port), 02574 rtp->ssrc, rtp->themssrc, fraction, lost, 02575 rtp->rxjitter, 02576 rtp->rtcp->themrxlsr, 02577 (double)(ntohl(rtcpheader[7])/65536.0)); 02578 } 02579 02580 return res; 02581 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2381 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().
02382 { 02383 struct ast_rtp *rtp = (struct ast_rtp *)data; 02384 int res; 02385 int len = 0; 02386 struct timeval now; 02387 unsigned int now_lsw; 02388 unsigned int now_msw; 02389 unsigned int *rtcpheader; 02390 unsigned int lost; 02391 unsigned int extended; 02392 unsigned int expected; 02393 unsigned int expected_interval; 02394 unsigned int received_interval; 02395 int lost_interval; 02396 int fraction; 02397 struct timeval dlsr; 02398 char bdata[512]; 02399 02400 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02401 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02402 return 0; 02403 02404 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02405 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02406 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02407 return 0; 02408 } 02409 02410 gettimeofday(&now, NULL); 02411 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02412 rtcpheader = (unsigned int *)bdata; 02413 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02414 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02415 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02416 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02417 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02418 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02419 len += 28; 02420 02421 extended = rtp->cycles + rtp->lastrxseqno; 02422 expected = extended - rtp->seedrxseqno + 1; 02423 if (rtp->rxcount > expected) 02424 expected += rtp->rxcount - expected; 02425 lost = expected - rtp->rxcount; 02426 expected_interval = expected - rtp->rtcp->expected_prior; 02427 rtp->rtcp->expected_prior = expected; 02428 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02429 rtp->rtcp->received_prior = rtp->rxcount; 02430 lost_interval = expected_interval - received_interval; 02431 if (expected_interval == 0 || lost_interval <= 0) 02432 fraction = 0; 02433 else 02434 fraction = (lost_interval << 8) / expected_interval; 02435 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02436 rtcpheader[7] = htonl(rtp->themssrc); 02437 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02438 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02439 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02440 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02441 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02442 len += 24; 02443 02444 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02445 02446 if (rtp->rtcp->sendfur) { 02447 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02448 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02449 len += 8; 02450 rtp->rtcp->sendfur = 0; 02451 } 02452 02453 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02454 /* it can change mid call, and SDES can't) */ 02455 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02456 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02457 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02458 len += 12; 02459 02460 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02461 if (res < 0) { 02462 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)); 02463 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02464 return 0; 02465 } 02466 02467 /* FIXME Don't need to get a new one */ 02468 gettimeofday(&rtp->rtcp->txlsr, NULL); 02469 rtp->rtcp->sr_count++; 02470 02471 rtp->rtcp->lastsrtxcount = rtp->txcount; 02472 02473 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02474 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02475 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02476 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02477 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02478 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02479 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02480 ast_verbose(" Report block:\n"); 02481 ast_verbose(" Fraction lost: %u\n", fraction); 02482 ast_verbose(" Cumulative loss: %u\n", lost); 02483 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02484 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02485 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02486 } 02487 return res; 02488 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 397 of file rtp.c.
Referenced by process_sdp().
00398 { 00399 return sizeof(struct ast_rtp); 00400 }
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 3347 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.
03348 { 03349 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03350 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03351 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03352 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03353 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03354 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03355 int codec0 = 0, codec1 = 0; 03356 void *pvt0 = NULL, *pvt1 = NULL; 03357 03358 /* Lock channels */ 03359 ast_channel_lock(c0); 03360 while(ast_channel_trylock(c1)) { 03361 ast_channel_unlock(c0); 03362 usleep(1); 03363 ast_channel_lock(c0); 03364 } 03365 03366 /* Ensure neither channel got hungup during lock avoidance */ 03367 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03368 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03369 ast_channel_unlock(c0); 03370 ast_channel_unlock(c1); 03371 return AST_BRIDGE_FAILED; 03372 } 03373 03374 /* Find channel driver interfaces */ 03375 if (!(pr0 = get_proto(c0))) { 03376 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03377 ast_channel_unlock(c0); 03378 ast_channel_unlock(c1); 03379 return AST_BRIDGE_FAILED; 03380 } 03381 if (!(pr1 = get_proto(c1))) { 03382 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03383 ast_channel_unlock(c0); 03384 ast_channel_unlock(c1); 03385 return AST_BRIDGE_FAILED; 03386 } 03387 03388 /* Get channel specific interface structures */ 03389 pvt0 = c0->tech_pvt; 03390 pvt1 = c1->tech_pvt; 03391 03392 /* Get audio and video interface (if native bridge is possible) */ 03393 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03394 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03395 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03396 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03397 03398 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03399 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03400 audio_p0_res = AST_RTP_GET_FAILED; 03401 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03402 audio_p1_res = AST_RTP_GET_FAILED; 03403 03404 /* Check if a bridge is possible (partial/native) */ 03405 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03406 /* Somebody doesn't want to play... */ 03407 ast_channel_unlock(c0); 03408 ast_channel_unlock(c1); 03409 return AST_BRIDGE_FAILED_NOWARN; 03410 } 03411 03412 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03413 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03414 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03415 audio_p0_res = AST_RTP_TRY_PARTIAL; 03416 } 03417 03418 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03419 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03420 audio_p1_res = AST_RTP_TRY_PARTIAL; 03421 } 03422 03423 /* If both sides are not using the same method of DTMF transmission 03424 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03425 * -------------------------------------------------- 03426 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03427 * |-----------|------------|-----------------------| 03428 * | Inband | False | True | 03429 * | RFC2833 | True | True | 03430 * | SIP INFO | False | False | 03431 * -------------------------------------------------- 03432 * However, if DTMF from both channels is being monitored by the core, then 03433 * we can still do packet-to-packet bridging, because passing through the 03434 * core will handle DTMF mode translation. 03435 */ 03436 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03437 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03438 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03439 ast_channel_unlock(c0); 03440 ast_channel_unlock(c1); 03441 return AST_BRIDGE_FAILED_NOWARN; 03442 } 03443 audio_p0_res = AST_RTP_TRY_PARTIAL; 03444 audio_p1_res = AST_RTP_TRY_PARTIAL; 03445 } 03446 03447 /* If we need to feed frames into the core don't do a P2P bridge */ 03448 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 03449 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 03450 ast_channel_unlock(c0); 03451 ast_channel_unlock(c1); 03452 return AST_BRIDGE_FAILED_NOWARN; 03453 } 03454 03455 /* Get codecs from both sides */ 03456 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03457 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03458 if (codec0 && codec1 && !(codec0 & codec1)) { 03459 /* Hey, we can't do native bridging if both parties speak different codecs */ 03460 if (option_debug) 03461 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03462 ast_channel_unlock(c0); 03463 ast_channel_unlock(c1); 03464 return AST_BRIDGE_FAILED_NOWARN; 03465 } 03466 03467 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03468 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03469 struct ast_format_list fmt0, fmt1; 03470 03471 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03472 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03473 if (option_debug) 03474 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03475 ast_channel_unlock(c0); 03476 ast_channel_unlock(c1); 03477 return AST_BRIDGE_FAILED_NOWARN; 03478 } 03479 /* They must also be using the same packetization */ 03480 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03481 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03482 if (fmt0.cur_ms != fmt1.cur_ms) { 03483 if (option_debug) 03484 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03485 ast_channel_unlock(c0); 03486 ast_channel_unlock(c1); 03487 return AST_BRIDGE_FAILED_NOWARN; 03488 } 03489 03490 if (option_verbose > 2) 03491 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03492 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03493 } else { 03494 if (option_verbose > 2) 03495 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03496 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03497 } 03498 03499 return res; 03500 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2791 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp().
02792 { 02793 if (pt < 0 || pt > MAX_RTP_PT) 02794 return 0; /* bogus payload type */ 02795 02796 if (static_RTP_PT[pt].isAstFormat) 02797 return static_RTP_PT[pt].code; 02798 else 02799 return 0; 02800 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Definition at line 2786 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
02787 { 02788 return &rtp->pref; 02789 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2739 of file rtp.c.
References ast_codec_pref_getsize(), ast_log(), ast_smoother_new(), ast_smoother_reconfigure(), ast_smoother_set_flags(), ast_format_list::cur_ms, ast_format_list::flags, ast_format_list::fr_len, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, option_debug, ast_rtp::pref, prefs, and ast_rtp::smoother.
Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().
02740 { 02741 struct ast_format_list current_format_old, current_format_new; 02742 02743 /* if no packets have been sent through this session yet, then 02744 * changing preferences does not require any extra work 02745 */ 02746 if (rtp->lasttxformat == 0) { 02747 rtp->pref = *prefs; 02748 return 0; 02749 } 02750 02751 current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 02752 02753 rtp->pref = *prefs; 02754 02755 current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 02756 02757 /* if the framing desired for the current format has changed, we may have to create 02758 * or adjust the smoother for this session 02759 */ 02760 if ((current_format_new.inc_ms != 0) && 02761 (current_format_new.cur_ms != current_format_old.cur_ms)) { 02762 int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms; 02763 02764 if (rtp->smoother) { 02765 ast_smoother_reconfigure(rtp->smoother, new_size); 02766 if (option_debug) { 02767 ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size); 02768 } 02769 } else { 02770 if (!(rtp->smoother = ast_smoother_new(new_size))) { 02771 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 02772 return -1; 02773 } 02774 if (current_format_new.flags) { 02775 ast_smoother_set_flags(rtp->smoother, current_format_new.flags); 02776 } 02777 if (option_debug) { 02778 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 02779 } 02780 } 02781 } 02782 02783 return 0; 02784 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2152 of file rtp.c.
References ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose(), ast_rtp::bridge_lock, ast_rtcp::expected_prior, free, ast_rtp::io, ast_rtp::ioid, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtp::s, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.
Referenced by __oh323_destroy(), __sip_destroy(), check_user_full(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().
02153 { 02154 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02155 /*Print some info on the call here */ 02156 ast_verbose(" RTP-stats\n"); 02157 ast_verbose("* Our Receiver:\n"); 02158 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02159 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02160 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0); 02161 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02162 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02163 ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0); 02164 ast_verbose("* Our Sender:\n"); 02165 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02166 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02167 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0); 02168 ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0); 02169 ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0); 02170 ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0); 02171 } 02172 02173 if (rtp->smoother) 02174 ast_smoother_free(rtp->smoother); 02175 if (rtp->ioid) 02176 ast_io_remove(rtp->io, rtp->ioid); 02177 if (rtp->s > -1) 02178 close(rtp->s); 02179 if (rtp->rtcp) { 02180 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02181 close(rtp->rtcp->s); 02182 free(rtp->rtcp); 02183 rtp->rtcp=NULL; 02184 } 02185 02186 ast_mutex_destroy(&rtp->bridge_lock); 02187 02188 free(rtp); 02189 }
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 1494 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().
01495 { 01496 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01497 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01498 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01499 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01500 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01501 int srccodec, destcodec, nat_active = 0; 01502 01503 /* Lock channels */ 01504 ast_channel_lock(dest); 01505 if (src) { 01506 while(ast_channel_trylock(src)) { 01507 ast_channel_unlock(dest); 01508 usleep(1); 01509 ast_channel_lock(dest); 01510 } 01511 } 01512 01513 /* Find channel driver interfaces */ 01514 destpr = get_proto(dest); 01515 if (src) 01516 srcpr = get_proto(src); 01517 if (!destpr) { 01518 if (option_debug) 01519 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01520 ast_channel_unlock(dest); 01521 if (src) 01522 ast_channel_unlock(src); 01523 return 0; 01524 } 01525 if (!srcpr) { 01526 if (option_debug) 01527 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01528 ast_channel_unlock(dest); 01529 if (src) 01530 ast_channel_unlock(src); 01531 return 0; 01532 } 01533 01534 /* Get audio and video interface (if native bridge is possible) */ 01535 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01536 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01537 if (srcpr) { 01538 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01539 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01540 } 01541 01542 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01543 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) { 01544 /* Somebody doesn't want to play... */ 01545 ast_channel_unlock(dest); 01546 if (src) 01547 ast_channel_unlock(src); 01548 return 0; 01549 } 01550 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) 01551 srccodec = srcpr->get_codec(src); 01552 else 01553 srccodec = 0; 01554 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) 01555 destcodec = destpr->get_codec(dest); 01556 else 01557 destcodec = 0; 01558 /* Ensure we have at least one matching codec */ 01559 if (srcp && !(srccodec & destcodec)) { 01560 ast_channel_unlock(dest); 01561 ast_channel_unlock(src); 01562 return 0; 01563 } 01564 /* Consider empty media as non-existant */ 01565 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01566 srcp = NULL; 01567 /* If the client has NAT stuff turned on then just safe NAT is active */ 01568 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01569 nat_active = 1; 01570 /* Bridge media early */ 01571 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01572 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01573 ast_channel_unlock(dest); 01574 if (src) 01575 ast_channel_unlock(src); 01576 if (option_debug) 01577 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01578 return 1; 01579 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 512 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().
00513 { 00514 return rtp->s; 00515 }
Definition at line 2062 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().
02063 { 02064 struct ast_rtp *bridged = NULL; 02065 02066 ast_mutex_lock(&rtp->bridge_lock); 02067 bridged = rtp->bridged; 02068 ast_mutex_unlock(&rtp->bridge_lock); 02069 02070 return bridged; 02071 }
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 1715 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().
01717 { 01718 int pt; 01719 01720 ast_mutex_lock(&rtp->bridge_lock); 01721 01722 *astFormats = *nonAstFormats = 0; 01723 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01724 if (rtp->current_RTP_PT[pt].isAstFormat) { 01725 *astFormats |= rtp->current_RTP_PT[pt].code; 01726 } else { 01727 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01728 } 01729 } 01730 01731 ast_mutex_unlock(&rtp->bridge_lock); 01732 01733 return; 01734 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2044 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().
02045 { 02046 if ((them->sin_family != AF_INET) || 02047 (them->sin_port != rtp->them.sin_port) || 02048 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02049 them->sin_family = AF_INET; 02050 them->sin_port = rtp->them.sin_port; 02051 them->sin_addr = rtp->them.sin_addr; 02052 return 1; 02053 } 02054 return 0; 02055 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2108 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().
02109 { 02110 /* 02111 *ssrc our ssrc 02112 *themssrc their ssrc 02113 *lp lost packets 02114 *rxjitter our calculated jitter(rx) 02115 *rxcount no. received packets 02116 *txjitter reported jitter of the other end 02117 *txcount transmitted packets 02118 *rlp remote lost packets 02119 *rtt round trip time 02120 */ 02121 02122 if (qual && rtp) { 02123 qual->local_ssrc = rtp->ssrc; 02124 qual->local_jitter = rtp->rxjitter; 02125 qual->local_count = rtp->rxcount; 02126 qual->remote_ssrc = rtp->themssrc; 02127 qual->remote_count = rtp->txcount; 02128 if (rtp->rtcp) { 02129 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02130 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02131 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02132 qual->rtt = rtp->rtcp->rtt; 02133 } 02134 } 02135 if (rtp->rtcp) { 02136 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02137 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02138 rtp->ssrc, 02139 rtp->themssrc, 02140 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02141 rtp->rxjitter, 02142 rtp->rxcount, 02143 (double)rtp->rtcp->reported_jitter / 65536.0, 02144 rtp->txcount, 02145 rtp->rtcp->reported_lost, 02146 rtp->rtcp->rtt); 02147 return rtp->rtcp->quality; 02148 } else 02149 return "<Unknown> - RTP/RTCP has already been destroyed"; 02150 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 567 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by do_monitor().
00568 { 00569 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00570 return 0; 00571 return rtp->rtpholdtimeout; 00572 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 575 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by do_monitor().
00576 { 00577 return rtp->rtpkeepalive; 00578 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 559 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by do_monitor().
00560 { 00561 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00562 return 0; 00563 return rtp->rtptimeout; 00564 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2057 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 595 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00596 { 00597 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00598 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 3885 of file rtp.c.
References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp.
Referenced by main().
03886 { 03887 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03888 ast_rtp_reload(); 03889 }
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 1758 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().
01759 { 01760 int pt = 0; 01761 01762 ast_mutex_lock(&rtp->bridge_lock); 01763 01764 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01765 code == rtp->rtp_lookup_code_cache_code) { 01766 /* Use our cached mapping, to avoid the overhead of the loop below */ 01767 pt = rtp->rtp_lookup_code_cache_result; 01768 ast_mutex_unlock(&rtp->bridge_lock); 01769 return pt; 01770 } 01771 01772 /* Check the dynamic list first */ 01773 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01774 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01775 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01776 rtp->rtp_lookup_code_cache_code = code; 01777 rtp->rtp_lookup_code_cache_result = pt; 01778 ast_mutex_unlock(&rtp->bridge_lock); 01779 return pt; 01780 } 01781 } 01782 01783 /* Then the static list */ 01784 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01785 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01786 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01787 rtp->rtp_lookup_code_cache_code = code; 01788 rtp->rtp_lookup_code_cache_result = pt; 01789 ast_mutex_unlock(&rtp->bridge_lock); 01790 return pt; 01791 } 01792 } 01793 01794 ast_mutex_unlock(&rtp->bridge_lock); 01795 01796 return -1; 01797 }
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 1818 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.
Referenced by process_sdp().
01820 { 01821 int format; 01822 unsigned len; 01823 char *end = buf; 01824 char *start = buf; 01825 01826 if (!buf || !size) 01827 return NULL; 01828 01829 snprintf(end, size, "0x%x (", capability); 01830 01831 len = strlen(end); 01832 end += len; 01833 size -= len; 01834 start = end; 01835 01836 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01837 if (capability & format) { 01838 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01839 01840 snprintf(end, size, "%s|", name); 01841 len = strlen(end); 01842 end += len; 01843 size -= len; 01844 } 01845 } 01846 01847 if (start == end) 01848 snprintf(start, size, "nothing)"); 01849 else if (size > 1) 01850 *(end -1) = ')'; 01851 01852 return buf; 01853 }
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 1799 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().
01801 { 01802 unsigned int i; 01803 01804 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01805 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01806 if (isAstFormat && 01807 (code == AST_FORMAT_G726_AAL2) && 01808 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01809 return "G726-32"; 01810 else 01811 return mimeTypes[i].subtype; 01812 } 01813 } 01814 01815 return ""; 01816 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1736 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().
01737 { 01738 struct rtpPayloadType result; 01739 01740 result.isAstFormat = result.code = 0; 01741 01742 if (pt < 0 || pt > MAX_RTP_PT) 01743 return result; /* bogus payload type */ 01744 01745 /* Start with negotiated codecs */ 01746 ast_mutex_lock(&rtp->bridge_lock); 01747 result = rtp->current_RTP_PT[pt]; 01748 ast_mutex_unlock(&rtp->bridge_lock); 01749 01750 /* If it doesn't exist, check our static RTP type list, just in case */ 01751 if (!result.code) 01752 result = static_RTP_PT[pt]; 01753 01754 return result; 01755 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1581 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().
01582 { 01583 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01584 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01585 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01586 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01587 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01588 int srccodec, destcodec; 01589 01590 /* Lock channels */ 01591 ast_channel_lock(dest); 01592 while(ast_channel_trylock(src)) { 01593 ast_channel_unlock(dest); 01594 usleep(1); 01595 ast_channel_lock(dest); 01596 } 01597 01598 /* Find channel driver interfaces */ 01599 if (!(destpr = get_proto(dest))) { 01600 if (option_debug) 01601 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01602 ast_channel_unlock(dest); 01603 ast_channel_unlock(src); 01604 return 0; 01605 } 01606 if (!(srcpr = get_proto(src))) { 01607 if (option_debug) 01608 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01609 ast_channel_unlock(dest); 01610 ast_channel_unlock(src); 01611 return 0; 01612 } 01613 01614 /* Get audio and video interface (if native bridge is possible) */ 01615 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01616 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01617 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01618 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01619 01620 /* Ensure we have at least one matching codec */ 01621 if (srcpr->get_codec) 01622 srccodec = srcpr->get_codec(src); 01623 else 01624 srccodec = 0; 01625 if (destpr->get_codec) 01626 destcodec = destpr->get_codec(dest); 01627 else 01628 destcodec = 0; 01629 01630 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01631 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)) { 01632 /* Somebody doesn't want to play... */ 01633 ast_channel_unlock(dest); 01634 ast_channel_unlock(src); 01635 return 0; 01636 } 01637 ast_rtp_pt_copy(destp, srcp); 01638 if (vdestp && vsrcp) 01639 ast_rtp_pt_copy(vdestp, vsrcp); 01640 if (media) { 01641 /* Bridge early */ 01642 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01643 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01644 } 01645 ast_channel_unlock(dest); 01646 ast_channel_unlock(src); 01647 if (option_debug) 01648 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01649 return 1; 01650 }
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 2008 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
02009 { 02010 struct in_addr ia; 02011 02012 memset(&ia, 0, sizeof(ia)); 02013 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02014 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1902 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().
01903 { 01904 ast_mutex_init(&rtp->bridge_lock); 01905 01906 rtp->them.sin_family = AF_INET; 01907 rtp->us.sin_family = AF_INET; 01908 rtp->ssrc = ast_random(); 01909 rtp->seqno = ast_random() & 0xffff; 01910 ast_set_flag(rtp, FLAG_HAS_DTMF); 01911 01912 return; 01913 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2025 of file rtp.c.
References ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), sip_write(), and skinny_indicate().
struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode, | |||
struct in_addr | in | |||
) |
Initializate a RTP session using an in_addr structure.
This fuction gets called by ast_rtp_new().
sched | ||
io | ||
rtcpenable | ||
callbackmode | ||
in |
Definition at line 1915 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().
01916 { 01917 struct ast_rtp *rtp; 01918 int x; 01919 int first; 01920 int startplace; 01921 01922 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01923 return NULL; 01924 01925 ast_rtp_new_init(rtp); 01926 01927 rtp->s = rtp_socket(); 01928 if (option_debug > 2) 01929 ast_log(LOG_DEBUG, "socket RTP fd: %i\n", rtp->s); 01930 if (rtp->s < 0) { 01931 free(rtp); 01932 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01933 return NULL; 01934 } 01935 if (sched && rtcpenable) { 01936 rtp->sched = sched; 01937 rtp->rtcp = ast_rtcp_new(); 01938 if (option_debug > 2) 01939 ast_log(LOG_DEBUG, "socket RTCP fd: %i\n", rtp->rtcp->s); 01940 } 01941 01942 /* Select a random port number in the range of possible RTP */ 01943 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 01944 x = x & ~1; 01945 /* Save it for future references. */ 01946 startplace = x; 01947 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01948 for (;;) { 01949 /* Must be an even port number by RTP spec */ 01950 rtp->us.sin_port = htons(x); 01951 rtp->us.sin_addr = addr; 01952 /* If there's rtcp, initialize it as well. */ 01953 if (rtp->rtcp) { 01954 rtp->rtcp->us.sin_port = htons(x + 1); 01955 rtp->rtcp->us.sin_addr = addr; 01956 } 01957 /* Try to bind it/them. */ 01958 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01959 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01960 break; 01961 if (!first) { 01962 /* Primary bind succeeded! Gotta recreate it */ 01963 close(rtp->s); 01964 rtp->s = rtp_socket(); 01965 if (option_debug > 2) 01966 ast_log(LOG_DEBUG, "socket RTP2 fd: %i\n", rtp->s); 01967 } 01968 if (errno != EADDRINUSE) { 01969 /* We got an error that wasn't expected, abort! */ 01970 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01971 close(rtp->s); 01972 if (rtp->rtcp) { 01973 close(rtp->rtcp->s); 01974 free(rtp->rtcp); 01975 } 01976 free(rtp); 01977 return NULL; 01978 } 01979 /* The port was used, increment it (by two). */ 01980 x += 2; 01981 /* Did we go over the limit ? */ 01982 if (x > rtpend) 01983 /* then, start from the begingig. */ 01984 x = (rtpstart + 1) & ~1; 01985 /* Check if we reached the place were we started. */ 01986 if (x == startplace) { 01987 /* If so, there's no ports available. */ 01988 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01989 close(rtp->s); 01990 if (rtp->rtcp) { 01991 close(rtp->rtcp->s); 01992 free(rtp->rtcp); 01993 } 01994 free(rtp); 01995 return NULL; 01996 } 01997 } 01998 rtp->sched = sched; 01999 rtp->io = io; 02000 if (callbackmode) { 02001 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 02002 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 02003 } 02004 ast_rtp_pt_default(rtp); 02005 return rtp; 02006 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2902 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().
02903 { 02904 struct ast_rtp_protocol *cur; 02905 02906 AST_LIST_LOCK(&protos); 02907 AST_LIST_TRAVERSE(&protos, cur, list) { 02908 if (!strcmp(cur->type, proto->type)) { 02909 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02910 AST_LIST_UNLOCK(&protos); 02911 return -1; 02912 } 02913 } 02914 AST_LIST_INSERT_HEAD(&protos, proto, list); 02915 AST_LIST_UNLOCK(&protos); 02916 02917 return 0; 02918 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2894 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by load_module(), and unload_module().
02895 { 02896 AST_LIST_LOCK(&protos); 02897 AST_LIST_REMOVE(&protos, proto, list); 02898 AST_LIST_UNLOCK(&protos); 02899 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1418 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().
01419 { 01420 int i; 01421 01422 if (!rtp) 01423 return; 01424 01425 ast_mutex_lock(&rtp->bridge_lock); 01426 01427 for (i = 0; i < MAX_RTP_PT; ++i) { 01428 rtp->current_RTP_PT[i].isAstFormat = 0; 01429 rtp->current_RTP_PT[i].code = 0; 01430 } 01431 01432 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01433 rtp->rtp_lookup_code_cache_code = 0; 01434 rtp->rtp_lookup_code_cache_result = 0; 01435 01436 ast_mutex_unlock(&rtp->bridge_lock); 01437 }
Copy payload types between RTP structures.
Definition at line 1458 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().
01459 { 01460 unsigned int i; 01461 01462 ast_mutex_lock(&dest->bridge_lock); 01463 ast_mutex_lock(&src->bridge_lock); 01464 01465 for (i=0; i < MAX_RTP_PT; ++i) { 01466 dest->current_RTP_PT[i].isAstFormat = 01467 src->current_RTP_PT[i].isAstFormat; 01468 dest->current_RTP_PT[i].code = 01469 src->current_RTP_PT[i].code; 01470 } 01471 dest->rtp_lookup_code_cache_isAstFormat = 0; 01472 dest->rtp_lookup_code_cache_code = 0; 01473 dest->rtp_lookup_code_cache_result = 0; 01474 01475 ast_mutex_unlock(&src->bridge_lock); 01476 ast_mutex_unlock(&dest->bridge_lock); 01477 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1439 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.
01440 { 01441 int i; 01442 01443 ast_mutex_lock(&rtp->bridge_lock); 01444 01445 /* Initialize to default payload types */ 01446 for (i = 0; i < MAX_RTP_PT; ++i) { 01447 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01448 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01449 } 01450 01451 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01452 rtp->rtp_lookup_code_cache_code = 0; 01453 rtp->rtp_lookup_code_cache_result = 0; 01454 01455 ast_mutex_unlock(&rtp->bridge_lock); 01456 }
Definition at line 2637 of file rtp.c.
References AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_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(), 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().
02638 { 02639 unsigned char *rtpheader; 02640 int hdrlen = 12; 02641 int res; 02642 unsigned int ms; 02643 int pred; 02644 int mark = 0; 02645 02646 if (rtp->sending_digit) { 02647 return 0; 02648 } 02649 02650 ms = calc_txstamp(rtp, &f->delivery); 02651 /* Default prediction */ 02652 if (f->frametype == AST_FRAME_VOICE) { 02653 pred = rtp->lastts + f->samples; 02654 02655 /* Re-calculate last TS */ 02656 rtp->lastts = rtp->lastts + ms * 8; 02657 if (ast_tvzero(f->delivery)) { 02658 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02659 and if so, go with our prediction */ 02660 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02661 rtp->lastts = pred; 02662 else { 02663 if (option_debug > 2) 02664 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02665 mark = 1; 02666 } 02667 } 02668 } else if (f->frametype == AST_FRAME_VIDEO) { 02669 mark = f->subclass & 0x1; 02670 pred = rtp->lastovidtimestamp + f->samples; 02671 /* Re-calculate last TS */ 02672 rtp->lastts = rtp->lastts + ms * 90; 02673 /* If it's close to our prediction, go for it */ 02674 if (ast_tvzero(f->delivery)) { 02675 if (abs(rtp->lastts - pred) < 7200) { 02676 rtp->lastts = pred; 02677 rtp->lastovidtimestamp += f->samples; 02678 } else { 02679 if (option_debug > 2) 02680 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); 02681 rtp->lastovidtimestamp = rtp->lastts; 02682 } 02683 } 02684 } 02685 02686 /* If we have been explicitly told to set the marker bit do so */ 02687 if (rtp->set_marker_bit) { 02688 mark = 1; 02689 rtp->set_marker_bit = 0; 02690 } 02691 02692 /* If the timestamp for non-digit packets has moved beyond the timestamp 02693 for digits, update the digit timestamp. 02694 */ 02695 if (rtp->lastts > rtp->lastdigitts) 02696 rtp->lastdigitts = rtp->lastts; 02697 02698 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 02699 rtp->lastts = f->ts * 8; 02700 02701 /* Get a pointer to the header */ 02702 rtpheader = (unsigned char *)(f->data - hdrlen); 02703 02704 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02705 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02706 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02707 02708 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02709 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02710 if (res <0) { 02711 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02712 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)); 02713 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02714 /* Only give this error message once if we are not RTP debugging */ 02715 if (option_debug || rtpdebug) 02716 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)); 02717 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02718 } 02719 } else { 02720 rtp->txcount++; 02721 rtp->txoctetcount +=(res - hdrlen); 02722 02723 /* Do not schedule RR if RTCP isn't run */ 02724 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 02725 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02726 } 02727 } 02728 02729 if (rtp_debug_test_addr(&rtp->them)) 02730 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02731 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02732 } 02733 02734 rtp->seqno++; 02735 02736 return 0; 02737 }
Definition at line 1108 of file rtp.c.
References ast_assert, ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_DTMF_END, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, errno, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len(), ast_frame::len, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, rtp_debug_test_addr(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_rtcp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, send_dtmf(), ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtp::them, ast_rtcp::them, ast_rtp::themssrc, and ast_frame::ts.
Referenced by gtalk_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().
01109 { 01110 int res; 01111 struct sockaddr_in sin; 01112 socklen_t len; 01113 unsigned int seqno; 01114 int version; 01115 int payloadtype; 01116 int hdrlen = 12; 01117 int padding; 01118 int mark; 01119 int ext; 01120 int cc; 01121 unsigned int ssrc; 01122 unsigned int timestamp; 01123 unsigned int *rtpheader; 01124 struct rtpPayloadType rtpPT; 01125 struct ast_rtp *bridged = NULL; 01126 01127 /* If time is up, kill it */ 01128 if (rtp->sending_digit) 01129 ast_rtp_senddigit_continuation(rtp); 01130 01131 len = sizeof(sin); 01132 01133 /* Cache where the header will go */ 01134 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01135 0, (struct sockaddr *)&sin, &len); 01136 if (option_debug > 3) 01137 ast_log(LOG_DEBUG, "socket RTP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 01138 01139 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01140 if (res < 0) { 01141 ast_assert(errno != EBADF); 01142 if (errno != EAGAIN) { 01143 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01144 ast_log(LOG_WARNING, "socket RTP read: rtp %i rtcp %i\n", rtp->s, rtp->rtcp->s); 01145 return NULL; 01146 } 01147 return &ast_null_frame; 01148 } 01149 01150 if (res < hdrlen) { 01151 ast_log(LOG_WARNING, "RTP Read too short\n"); 01152 return &ast_null_frame; 01153 } 01154 01155 /* Get fields */ 01156 seqno = ntohl(rtpheader[0]); 01157 01158 /* Check RTP version */ 01159 version = (seqno & 0xC0000000) >> 30; 01160 if (!version) { 01161 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01162 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01163 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01164 } 01165 return &ast_null_frame; 01166 } 01167 01168 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01169 /* If we don't have the other side's address, then ignore this */ 01170 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01171 return &ast_null_frame; 01172 #endif 01173 01174 /* Send to whoever send to us if NAT is turned on */ 01175 if (rtp->nat) { 01176 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01177 (rtp->them.sin_port != sin.sin_port)) { 01178 rtp->them = sin; 01179 if (rtp->rtcp) { 01180 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01181 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01182 } 01183 rtp->rxseqno = 0; 01184 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01185 if (option_debug || rtpdebug) 01186 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)); 01187 } 01188 } 01189 01190 /* If we are bridged to another RTP stream, send direct */ 01191 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01192 return &ast_null_frame; 01193 01194 if (version != 2) 01195 return &ast_null_frame; 01196 01197 payloadtype = (seqno & 0x7f0000) >> 16; 01198 padding = seqno & (1 << 29); 01199 mark = seqno & (1 << 23); 01200 ext = seqno & (1 << 28); 01201 cc = (seqno & 0xF000000) >> 24; 01202 seqno &= 0xffff; 01203 timestamp = ntohl(rtpheader[1]); 01204 ssrc = ntohl(rtpheader[2]); 01205 01206 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01207 if (option_debug || rtpdebug) 01208 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01209 mark = 1; 01210 } 01211 01212 rtp->rxssrc = ssrc; 01213 01214 if (padding) { 01215 /* Remove padding bytes */ 01216 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01217 } 01218 01219 if (cc) { 01220 /* CSRC fields present */ 01221 hdrlen += cc*4; 01222 } 01223 01224 if (ext) { 01225 /* RTP Extension present */ 01226 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01227 hdrlen += 4; 01228 } 01229 01230 if (res < hdrlen) { 01231 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01232 return &ast_null_frame; 01233 } 01234 01235 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01236 01237 if (rtp->rxcount==1) { 01238 /* This is the first RTP packet successfully received from source */ 01239 rtp->seedrxseqno = seqno; 01240 } 01241 01242 /* Do not schedule RR if RTCP isn't run */ 01243 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01244 /* Schedule transmission of Receiver Report */ 01245 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01246 } 01247 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01248 rtp->cycles += RTP_SEQ_MOD; 01249 01250 rtp->lastrxseqno = seqno; 01251 01252 if (rtp->themssrc==0) 01253 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01254 01255 if (rtp_debug_test_addr(&sin)) 01256 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01257 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01258 01259 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01260 if (!rtpPT.isAstFormat) { 01261 struct ast_frame *f = NULL; 01262 01263 /* This is special in-band data that's not one of our codecs */ 01264 if (rtpPT.code == AST_RTP_DTMF) { 01265 /* It's special -- rfc2833 process it */ 01266 if (rtp_debug_test_addr(&sin)) { 01267 unsigned char *data; 01268 unsigned int event; 01269 unsigned int event_end; 01270 unsigned int duration; 01271 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01272 event = ntohl(*((unsigned int *)(data))); 01273 event >>= 24; 01274 event_end = ntohl(*((unsigned int *)(data))); 01275 event_end <<= 8; 01276 event_end >>= 24; 01277 duration = ntohl(*((unsigned int *)(data))); 01278 duration &= 0xFFFF; 01279 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); 01280 } 01281 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01282 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01283 /* It's really special -- process it the Cisco way */ 01284 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01285 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01286 rtp->lastevent = seqno; 01287 } 01288 } else if (rtpPT.code == AST_RTP_CN) { 01289 /* Comfort Noise */ 01290 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01291 } else { 01292 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01293 } 01294 return f ? f : &ast_null_frame; 01295 } 01296 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01297 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01298 01299 rtp->rxseqno = seqno; 01300 01301 if (rtp->dtmfcount) { 01302 rtp->dtmfcount -= (timestamp - rtp->lastrxts); 01303 01304 if (rtp->dtmfcount < 0) { 01305 rtp->dtmfcount = 0; 01306 } 01307 01308 if (rtp->resp && !rtp->dtmfcount) { 01309 struct ast_frame *f; 01310 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01311 rtp->resp = 0; 01312 return f; 01313 } 01314 } 01315 01316 /* Record received timestamp as last received now */ 01317 rtp->lastrxts = timestamp; 01318 01319 rtp->f.mallocd = 0; 01320 rtp->f.datalen = res - hdrlen; 01321 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01322 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01323 rtp->f.seqno = seqno; 01324 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01325 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01326 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01327 ast_frame_byteswap_be(&rtp->f); 01328 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01329 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01330 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01331 rtp->f.ts = timestamp / 8; 01332 rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000); 01333 } else { 01334 /* Video -- samples is # of samples vs. 90000 */ 01335 if (!rtp->lastividtimestamp) 01336 rtp->lastividtimestamp = timestamp; 01337 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01338 rtp->lastividtimestamp = timestamp; 01339 rtp->f.delivery.tv_sec = 0; 01340 rtp->f.delivery.tv_usec = 0; 01341 if (mark) 01342 rtp->f.subclass |= 0x1; 01343 } 01344 rtp->f.src = "RTP"; 01345 return &rtp->f; 01346 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3820 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().
03821 { 03822 struct ast_config *cfg; 03823 const char *s; 03824 03825 rtpstart = 5000; 03826 rtpend = 31000; 03827 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03828 cfg = ast_config_load("rtp.conf"); 03829 if (cfg) { 03830 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03831 rtpstart = atoi(s); 03832 if (rtpstart < 1024) 03833 rtpstart = 1024; 03834 if (rtpstart > 65535) 03835 rtpstart = 65535; 03836 } 03837 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03838 rtpend = atoi(s); 03839 if (rtpend < 1024) 03840 rtpend = 1024; 03841 if (rtpend > 65535) 03842 rtpend = 65535; 03843 } 03844 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03845 rtcpinterval = atoi(s); 03846 if (rtcpinterval == 0) 03847 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03848 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03849 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03850 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03851 rtcpinterval = RTCP_MAX_INTERVALMS; 03852 } 03853 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03854 #ifdef SO_NO_CHECK 03855 if (ast_false(s)) 03856 nochecksums = 1; 03857 else 03858 nochecksums = 0; 03859 #else 03860 if (ast_false(s)) 03861 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03862 #endif 03863 } 03864 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03865 dtmftimeout = atoi(s); 03866 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03867 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03868 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03869 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03870 }; 03871 } 03872 ast_config_destroy(cfg); 03873 } 03874 if (rtpstart >= rtpend) { 03875 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03876 rtpstart = 5000; 03877 rtpend = 31000; 03878 } 03879 if (option_verbose > 1) 03880 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03881 return 0; 03882 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2089 of file rtp.c.
References ast_rtp::dtmfcount, 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.
02090 { 02091 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02092 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02093 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02094 rtp->lastts = 0; 02095 rtp->lastdigitts = 0; 02096 rtp->lastrxts = 0; 02097 rtp->lastividtimestamp = 0; 02098 rtp->lastovidtimestamp = 0; 02099 rtp->lasteventseqn = 0; 02100 rtp->lastevent = 0; 02101 rtp->lasttxformat = 0; 02102 rtp->lastrxformat = 0; 02103 rtp->dtmfcount = 0; 02104 rtp->seqno = 0; 02105 rtp->rxseqno = 0; 02106 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2603 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().
02604 { 02605 unsigned int *rtpheader; 02606 int hdrlen = 12; 02607 int res; 02608 int payload; 02609 char data[256]; 02610 level = 127 - (level & 0x7f); 02611 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02612 02613 /* If we have no peer, return immediately */ 02614 if (!rtp->them.sin_addr.s_addr) 02615 return 0; 02616 02617 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02618 02619 /* Get a pointer to the header */ 02620 rtpheader = (unsigned int *)data; 02621 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02622 rtpheader[1] = htonl(rtp->lastts); 02623 rtpheader[2] = htonl(rtp->ssrc); 02624 data[12] = level; 02625 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02626 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02627 if (res <0) 02628 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)); 02629 if (rtp_debug_test_addr(&rtp->them)) 02630 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02631 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02632 02633 } 02634 return 0; 02635 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2211 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().
02212 { 02213 unsigned int *rtpheader; 02214 int hdrlen = 12, res = 0, i = 0, payload = 0; 02215 char data[256]; 02216 02217 if ((digit <= '9') && (digit >= '0')) 02218 digit -= '0'; 02219 else if (digit == '*') 02220 digit = 10; 02221 else if (digit == '#') 02222 digit = 11; 02223 else if ((digit >= 'A') && (digit <= 'D')) 02224 digit = digit - 'A' + 12; 02225 else if ((digit >= 'a') && (digit <= 'd')) 02226 digit = digit - 'a' + 12; 02227 else { 02228 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02229 return 0; 02230 } 02231 02232 /* If we have no peer, return immediately */ 02233 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02234 return 0; 02235 02236 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02237 02238 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02239 rtp->send_duration = 160; 02240 rtp->lastdigitts = rtp->lastts + rtp->send_duration; 02241 02242 /* Get a pointer to the header */ 02243 rtpheader = (unsigned int *)data; 02244 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02245 rtpheader[1] = htonl(rtp->lastdigitts); 02246 rtpheader[2] = htonl(rtp->ssrc); 02247 02248 for (i = 0; i < 2; i++) { 02249 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02250 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02251 if (res < 0) 02252 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02253 ast_inet_ntoa(rtp->them.sin_addr), 02254 ntohs(rtp->them.sin_port), strerror(errno)); 02255 if (rtp_debug_test_addr(&rtp->them)) 02256 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02257 ast_inet_ntoa(rtp->them.sin_addr), 02258 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02259 /* Increment sequence number */ 02260 rtp->seqno++; 02261 /* Increment duration */ 02262 rtp->send_duration += 160; 02263 /* Clear marker bit and set seqno */ 02264 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02265 } 02266 02267 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02268 rtp->sending_digit = 1; 02269 rtp->send_digit = digit; 02270 rtp->send_payload = payload; 02271 02272 return 0; 02273 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2276 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().
02277 { 02278 unsigned int *rtpheader; 02279 int hdrlen = 12, res = 0; 02280 char data[256]; 02281 02282 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02283 return 0; 02284 02285 /* Setup packet to send */ 02286 rtpheader = (unsigned int *)data; 02287 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02288 rtpheader[1] = htonl(rtp->lastdigitts); 02289 rtpheader[2] = htonl(rtp->ssrc); 02290 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02291 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02292 02293 /* Transmit */ 02294 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02295 if (res < 0) 02296 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02297 ast_inet_ntoa(rtp->them.sin_addr), 02298 ntohs(rtp->them.sin_port), strerror(errno)); 02299 if (rtp_debug_test_addr(&rtp->them)) 02300 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02301 ast_inet_ntoa(rtp->them.sin_addr), 02302 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02303 02304 /* Increment sequence number */ 02305 rtp->seqno++; 02306 /* Increment duration */ 02307 rtp->send_duration += 160; 02308 02309 return 0; 02310 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2313 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by mgcp_senddigit_end(), oh323_digit_end(), and sip_senddigit_end().
02314 { 02315 unsigned int *rtpheader; 02316 int hdrlen = 12, res = 0, i = 0; 02317 char data[256]; 02318 02319 /* If no address, then bail out */ 02320 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02321 return 0; 02322 02323 if ((digit <= '9') && (digit >= '0')) 02324 digit -= '0'; 02325 else if (digit == '*') 02326 digit = 10; 02327 else if (digit == '#') 02328 digit = 11; 02329 else if ((digit >= 'A') && (digit <= 'D')) 02330 digit = digit - 'A' + 12; 02331 else if ((digit >= 'a') && (digit <= 'd')) 02332 digit = digit - 'a' + 12; 02333 else { 02334 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02335 return 0; 02336 } 02337 02338 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02339 02340 rtpheader = (unsigned int *)data; 02341 rtpheader[1] = htonl(rtp->lastdigitts); 02342 rtpheader[2] = htonl(rtp->ssrc); 02343 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02344 /* Set end bit */ 02345 rtpheader[3] |= htonl((1 << 23)); 02346 02347 /* Send 3 termination packets */ 02348 for (i = 0; i < 3; i++) { 02349 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02350 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02351 rtp->seqno++; 02352 if (res < 0) 02353 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02354 ast_inet_ntoa(rtp->them.sin_addr), 02355 ntohs(rtp->them.sin_port), strerror(errno)); 02356 if (rtp_debug_test_addr(&rtp->them)) 02357 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02358 ast_inet_ntoa(rtp->them.sin_addr), 02359 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02360 } 02361 rtp->lastts += rtp->send_duration; 02362 rtp->sending_digit = 0; 02363 rtp->send_digit = 0; 02364 02365 return res; 02366 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 585 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00586 { 00587 rtp->callback = callback; 00588 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 580 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00581 { 00582 rtp->data = data; 00583 }
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Activate payload type.
Definition at line 1656 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().
01657 { 01658 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01659 return; /* bogus payload type */ 01660 01661 ast_mutex_lock(&rtp->bridge_lock); 01662 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01663 ast_mutex_unlock(&rtp->bridge_lock); 01664 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2033 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().
02034 { 02035 rtp->them.sin_port = them->sin_port; 02036 rtp->them.sin_addr = them->sin_addr; 02037 if (rtp->rtcp) { 02038 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02039 rtp->rtcp->them.sin_addr = them->sin_addr; 02040 } 02041 rtp->rxseqno = 0; 02042 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 547 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00548 { 00549 rtp->rtpholdtimeout = timeout; 00550 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 553 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00554 { 00555 rtp->rtpkeepalive = period; 00556 }
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 1683 of file rtp.c.
References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, subtype, and type.
Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), process_sdp(), and set_dtmf_payload().
01686 { 01687 unsigned int i; 01688 int found = 0; 01689 01690 if (pt < 0 || pt > MAX_RTP_PT) 01691 return -1; /* bogus payload type */ 01692 01693 ast_mutex_lock(&rtp->bridge_lock); 01694 01695 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01696 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01697 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01698 found = 1; 01699 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01700 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01701 mimeTypes[i].payloadType.isAstFormat && 01702 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01703 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01704 break; 01705 } 01706 } 01707 01708 ast_mutex_unlock(&rtp->bridge_lock); 01709 01710 return (found ? 0 : -1); 01711 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 541 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00542 { 00543 rtp->rtptimeout = timeout; 00544 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 534 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00535 { 00536 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00537 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00538 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 600 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().
00601 { 00602 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00603 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 605 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().
00606 { 00607 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00608 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 590 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 610 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00611 { 00612 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00613 }
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 2016 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
02017 { 02018 int res; 02019 02020 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 02021 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 02022 return res; 02023 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2073 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().
02074 { 02075 if (rtp->rtcp) { 02076 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02077 } 02078 02079 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02080 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02081 if (rtp->rtcp) { 02082 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02083 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02084 } 02085 02086 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02087 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Definition at line 402 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().
00403 { 00404 struct stun_header *req; 00405 unsigned char reqdata[1024]; 00406 int reqlen, reqleft; 00407 struct stun_attr *attr; 00408 00409 req = (struct stun_header *)reqdata; 00410 stun_req_id(req); 00411 reqlen = 0; 00412 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00413 req->msgtype = 0; 00414 req->msglen = 0; 00415 attr = (struct stun_attr *)req->ies; 00416 if (username) 00417 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00418 req->msglen = htons(reqlen); 00419 req->msgtype = htons(STUN_BINDREQ); 00420 stun_send(rtp->s, suggestion, req); 00421 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
clear payload type
Definition at line 1668 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().
01669 { 01670 if (pt < 0 || pt > MAX_RTP_PT) 01671 return; /* bogus payload type */ 01672 01673 ast_mutex_lock(&rtp->bridge_lock); 01674 rtp->current_RTP_PT[pt].isAstFormat = 0; 01675 rtp->current_RTP_PT[pt].code = 0; 01676 ast_mutex_unlock(&rtp->bridge_lock); 01677 }
Definition at line 2802 of file rtp.c.
References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_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().
02803 { 02804 struct ast_frame *f; 02805 int codec; 02806 int hdrlen = 12; 02807 int subclass; 02808 02809 02810 /* If we have no peer, return immediately */ 02811 if (!rtp->them.sin_addr.s_addr) 02812 return 0; 02813 02814 /* If there is no data length, return immediately */ 02815 if (!_f->datalen) 02816 return 0; 02817 02818 /* Make sure we have enough space for RTP header */ 02819 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02820 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02821 return -1; 02822 } 02823 02824 subclass = _f->subclass; 02825 if (_f->frametype == AST_FRAME_VIDEO) 02826 subclass &= ~0x1; 02827 02828 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02829 if (codec < 0) { 02830 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02831 return -1; 02832 } 02833 02834 if (rtp->lasttxformat != subclass) { 02835 /* New format, reset the smoother */ 02836 if (option_debug) 02837 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02838 rtp->lasttxformat = subclass; 02839 if (rtp->smoother) 02840 ast_smoother_free(rtp->smoother); 02841 rtp->smoother = NULL; 02842 } 02843 02844 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 02845 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02846 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02847 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02848 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)); 02849 return -1; 02850 } 02851 if (fmt.flags) 02852 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02853 if (option_debug) 02854 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)); 02855 } 02856 } 02857 if (rtp->smoother) { 02858 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02859 ast_smoother_feed_be(rtp->smoother, _f); 02860 } else { 02861 ast_smoother_feed(rtp->smoother, _f); 02862 } 02863 02864 while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { 02865 if (f->subclass == AST_FORMAT_G722) { 02866 /* G.722 is silllllllllllllly */ 02867 f->samples /= 2; 02868 } 02869 02870 ast_rtp_raw_write(rtp, f, codec); 02871 } 02872 } else { 02873 /* Don't buffer outgoing frames; send them one-per-packet: */ 02874 if (_f->offset < hdrlen) { 02875 f = ast_frdup(_f); 02876 } else { 02877 f = _f; 02878 } 02879 if (f->data) { 02880 if (f->subclass == AST_FORMAT_G722) { 02881 /* G.722 is silllllllllllllly */ 02882 f->samples /= 2; 02883 } 02884 ast_rtp_raw_write(rtp, f, codec); 02885 } 02886 if (f != _f) 02887 ast_frfree(f); 02888 } 02889 02890 return 0; 02891 }
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 2921 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().
02922 { 02923 struct ast_frame *fr = NULL; 02924 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02925 int oldcodec0 = codec0, oldcodec1 = codec1; 02926 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02927 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02928 02929 /* Set it up so audio goes directly between the two endpoints */ 02930 02931 /* Test the first channel */ 02932 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02933 ast_rtp_get_peer(p1, &ac1); 02934 if (vp1) 02935 ast_rtp_get_peer(vp1, &vac1); 02936 } else 02937 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 02938 02939 /* Test the second channel */ 02940 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 02941 ast_rtp_get_peer(p0, &ac0); 02942 if (vp0) 02943 ast_rtp_get_peer(vp0, &vac0); 02944 } else 02945 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 02946 02947 /* Now we can unlock and move into our loop */ 02948 ast_channel_unlock(c0); 02949 ast_channel_unlock(c1); 02950 02951 /* Throw our channels into the structure and enter the loop */ 02952 cs[0] = c0; 02953 cs[1] = c1; 02954 cs[2] = NULL; 02955 for (;;) { 02956 /* Check if anything changed */ 02957 if ((c0->tech_pvt != pvt0) || 02958 (c1->tech_pvt != pvt1) || 02959 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 02960 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 02961 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 02962 if (c0->tech_pvt == pvt0) 02963 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02964 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02965 if (c1->tech_pvt == pvt1) 02966 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02967 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02968 return AST_BRIDGE_RETRY; 02969 } 02970 02971 /* Check if they have changed their address */ 02972 ast_rtp_get_peer(p1, &t1); 02973 if (vp1) 02974 ast_rtp_get_peer(vp1, &vt1); 02975 if (pr1->get_codec) 02976 codec1 = pr1->get_codec(c1); 02977 ast_rtp_get_peer(p0, &t0); 02978 if (vp0) 02979 ast_rtp_get_peer(vp0, &vt0); 02980 if (pr0->get_codec) 02981 codec0 = pr0->get_codec(c0); 02982 if ((inaddrcmp(&t1, &ac1)) || 02983 (vp1 && inaddrcmp(&vt1, &vac1)) || 02984 (codec1 != oldcodec1)) { 02985 if (option_debug > 1) { 02986 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02987 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 02988 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 02989 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 02990 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02991 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 02992 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02993 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 02994 } 02995 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))) 02996 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 02997 memcpy(&ac1, &t1, sizeof(ac1)); 02998 memcpy(&vac1, &vt1, sizeof(vac1)); 02999 oldcodec1 = codec1; 03000 } 03001 if ((inaddrcmp(&t0, &ac0)) || 03002 (vp0 && inaddrcmp(&vt0, &vac0))) { 03003 if (option_debug > 1) { 03004 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03005 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 03006 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 03007 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 03008 } 03009 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))) 03010 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 03011 memcpy(&ac0, &t0, sizeof(ac0)); 03012 memcpy(&vac0, &vt0, sizeof(vac0)); 03013 oldcodec0 = codec0; 03014 } 03015 03016 /* Wait for frame to come in on the channels */ 03017 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03018 if (!timeoutms) { 03019 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03020 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03021 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03022 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03023 return AST_BRIDGE_RETRY; 03024 } 03025 if (option_debug) 03026 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 03027 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03028 break; 03029 continue; 03030 } 03031 fr = ast_read(who); 03032 other = (who == c0) ? c1 : c0; 03033 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03034 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 03035 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 03036 /* Break out of bridge */ 03037 *fo = fr; 03038 *rc = who; 03039 if (option_debug) 03040 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03041 if (c0->tech_pvt == pvt0) 03042 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03043 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03044 if (c1->tech_pvt == pvt1) 03045 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03046 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03047 return AST_BRIDGE_COMPLETE; 03048 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03049 if ((fr->subclass == AST_CONTROL_HOLD) || 03050 (fr->subclass == AST_CONTROL_UNHOLD) || 03051 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03052 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03053 if (fr->subclass == AST_CONTROL_HOLD) { 03054 /* If we someone went on hold we want the other side to reinvite back to us */ 03055 if (who == c0) 03056 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 03057 else 03058 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 03059 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03060 /* If they went off hold they should go back to being direct */ 03061 if (who == c0) 03062 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 03063 else 03064 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 03065 } 03066 /* Update local address information */ 03067 ast_rtp_get_peer(p0, &t0); 03068 memcpy(&ac0, &t0, sizeof(ac0)); 03069 ast_rtp_get_peer(p1, &t1); 03070 memcpy(&ac1, &t1, sizeof(ac1)); 03071 /* Update codec information */ 03072 if (pr0->get_codec && c0->tech_pvt) 03073 oldcodec0 = codec0 = pr0->get_codec(c0); 03074 if (pr1->get_codec && c1->tech_pvt) 03075 oldcodec1 = codec1 = pr1->get_codec(c1); 03076 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03077 ast_frfree(fr); 03078 } else { 03079 *fo = fr; 03080 *rc = who; 03081 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03082 return AST_BRIDGE_COMPLETE; 03083 } 03084 } else { 03085 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03086 (fr->frametype == AST_FRAME_DTMF_END) || 03087 (fr->frametype == AST_FRAME_VOICE) || 03088 (fr->frametype == AST_FRAME_VIDEO) || 03089 (fr->frametype == AST_FRAME_IMAGE) || 03090 (fr->frametype == AST_FRAME_HTML) || 03091 (fr->frametype == AST_FRAME_MODEM) || 03092 (fr->frametype == AST_FRAME_TEXT)) { 03093 ast_write(other, fr); 03094 } 03095 ast_frfree(fr); 03096 } 03097 /* Swap priority */ 03098 cs[2] = cs[0]; 03099 cs[0] = cs[1]; 03100 cs[1] = cs[2]; 03101 } 03102 03103 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03104 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03105 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03106 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03107 03108 return AST_BRIDGE_FAILED; 03109 }
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 3207 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().
03208 { 03209 struct ast_frame *fr = NULL; 03210 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03211 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03212 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03213 int p0_callback = 0, p1_callback = 0; 03214 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03215 03216 /* Okay, setup each RTP structure to do P2P forwarding */ 03217 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03218 p2p_set_bridge(p0, p1); 03219 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03220 p2p_set_bridge(p1, p0); 03221 03222 /* Activate callback modes if possible */ 03223 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03224 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03225 03226 /* Now let go of the channel locks and be on our way */ 03227 ast_channel_unlock(c0); 03228 ast_channel_unlock(c1); 03229 03230 /* Go into a loop forwarding frames until we don't need to anymore */ 03231 cs[0] = c0; 03232 cs[1] = c1; 03233 cs[2] = NULL; 03234 for (;;) { 03235 /* If the underlying formats have changed force this bridge to break */ 03236 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 03237 ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n"); 03238 res = AST_BRIDGE_FAILED_NOWARN; 03239 break; 03240 } 03241 /* Check if anything changed */ 03242 if ((c0->tech_pvt != pvt0) || 03243 (c1->tech_pvt != pvt1) || 03244 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03245 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03246 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03247 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03248 ast_frfree(fr); 03249 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03250 ast_frfree(fr); 03251 res = AST_BRIDGE_RETRY; 03252 break; 03253 } 03254 /* Wait on a channel to feed us a frame */ 03255 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03256 if (!timeoutms) { 03257 res = AST_BRIDGE_RETRY; 03258 break; 03259 } 03260 if (option_debug) 03261 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03262 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03263 break; 03264 continue; 03265 } 03266 /* Read in frame from channel */ 03267 fr = ast_read(who); 03268 other = (who == c0) ? c1 : c0; 03269 /* Dependong on the frame we may need to break out of our bridge */ 03270 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03271 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03272 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03273 /* Record received frame and who */ 03274 *fo = fr; 03275 *rc = who; 03276 if (option_debug) 03277 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03278 res = AST_BRIDGE_COMPLETE; 03279 break; 03280 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03281 if ((fr->subclass == AST_CONTROL_HOLD) || 03282 (fr->subclass == AST_CONTROL_UNHOLD) || 03283 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03284 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03285 /* If we are going on hold, then break callback mode and P2P bridging */ 03286 if (fr->subclass == AST_CONTROL_HOLD) { 03287 if (p0_callback) 03288 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03289 if (p1_callback) 03290 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03291 p2p_set_bridge(p0, NULL); 03292 p2p_set_bridge(p1, NULL); 03293 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03294 /* If we are off hold, then go back to callback mode and P2P bridging */ 03295 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03296 p2p_set_bridge(p0, p1); 03297 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03298 p2p_set_bridge(p1, p0); 03299 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03300 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03301 } 03302 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03303 ast_frfree(fr); 03304 } else { 03305 *fo = fr; 03306 *rc = who; 03307 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03308 res = AST_BRIDGE_COMPLETE; 03309 break; 03310 } 03311 } else { 03312 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03313 (fr->frametype == AST_FRAME_DTMF_END) || 03314 (fr->frametype == AST_FRAME_VOICE) || 03315 (fr->frametype == AST_FRAME_VIDEO) || 03316 (fr->frametype == AST_FRAME_IMAGE) || 03317 (fr->frametype == AST_FRAME_HTML) || 03318 (fr->frametype == AST_FRAME_MODEM) || 03319 (fr->frametype == AST_FRAME_TEXT)) { 03320 ast_write(other, fr); 03321 } 03322 03323 ast_frfree(fr); 03324 } 03325 /* Swap priority */ 03326 cs[2] = cs[0]; 03327 cs[0] = cs[1]; 03328 cs[1] = cs[2]; 03329 } 03330 03331 /* If we are totally avoiding the core, then restore our link to it */ 03332 if (p0_callback) 03333 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03334 if (p1_callback) 03335 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03336 03337 /* Break out of the direct bridge */ 03338 p2p_set_bridge(p0, NULL); 03339 p2p_set_bridge(p1, NULL); 03340 03341 return res; 03342 }
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 1054 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().
01055 { 01056 int res = 0, payload = 0, bridged_payload = 0, mark; 01057 struct rtpPayloadType rtpPT; 01058 int reconstruct = ntohl(rtpheader[0]); 01059 01060 /* Get fields from packet */ 01061 payload = (reconstruct & 0x7f0000) >> 16; 01062 mark = (((reconstruct & 0x800000) >> 23) != 0); 01063 01064 /* Check what the payload value should be */ 01065 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01066 01067 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01068 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01069 return -1; 01070 01071 /* Otherwise adjust bridged payload to match */ 01072 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01073 01074 /* 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 */ 01075 if (!bridged->current_RTP_PT[bridged_payload].code) 01076 return -1; 01077 01078 01079 /* If the mark bit has not been sent yet... do it now */ 01080 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01081 mark = 1; 01082 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01083 } 01084 01085 /* Reconstruct part of the packet */ 01086 reconstruct &= 0xFF80FFFF; 01087 reconstruct |= (bridged_payload << 16); 01088 reconstruct |= (mark << 23); 01089 rtpheader[0] = htonl(reconstruct); 01090 01091 /* Send the packet back out */ 01092 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01093 if (res < 0) { 01094 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01095 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)); 01096 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01097 if (option_debug || rtpdebug) 01098 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)); 01099 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01100 } 01101 return 0; 01102 } else if (rtp_debug_test_addr(&bridged->them)) 01103 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); 01104 01105 return 0; 01106 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1005 of file rtp.c.
References ast_rtp::drxcore, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtp::rtcp, ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtp::rxtransit, and ast_rtp::seedrxts.
Referenced by ast_rtp_read(), and schedule_delivery().
01006 { 01007 struct timeval now; 01008 double transit; 01009 double current_time; 01010 double d; 01011 double dtv; 01012 double prog; 01013 01014 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01015 gettimeofday(&rtp->rxcore, NULL); 01016 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01017 /* map timestamp to a real time */ 01018 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01019 rtp->rxcore.tv_sec -= timestamp / 8000; 01020 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01021 /* Round to 0.1ms for nice, pretty timestamps */ 01022 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01023 if (rtp->rxcore.tv_usec < 0) { 01024 /* Adjust appropriately if necessary */ 01025 rtp->rxcore.tv_usec += 1000000; 01026 rtp->rxcore.tv_sec -= 1; 01027 } 01028 } 01029 01030 gettimeofday(&now,NULL); 01031 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01032 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01033 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01034 if (tv->tv_usec >= 1000000) { 01035 tv->tv_usec -= 1000000; 01036 tv->tv_sec += 1; 01037 } 01038 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01039 dtv = (double)rtp->drxcore + (double)(prog); 01040 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01041 transit = current_time - dtv; 01042 d = transit - rtp->rxtransit; 01043 rtp->rxtransit = transit; 01044 if (d<0) 01045 d=-d; 01046 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01047 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01048 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01049 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01050 rtp->rtcp->minrxjitter = rtp->rxjitter; 01051 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2191 of file rtp.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), t, and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02192 { 02193 struct timeval t; 02194 long ms; 02195 if (ast_tvzero(rtp->txcore)) { 02196 rtp->txcore = ast_tvnow(); 02197 /* Round to 20ms for nice, pretty timestamps */ 02198 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02199 } 02200 /* Use previous txcore if available */ 02201 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02202 ms = ast_tvdiff_ms(t, rtp->txcore); 02203 if (ms < 0) 02204 ms = 0; 02205 /* Use what we just got for next time */ 02206 rtp->txcore = t; 02207 return (unsigned int) ms; 02208 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 1480 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().
01481 { 01482 struct ast_rtp_protocol *cur = NULL; 01483 01484 AST_LIST_LOCK(&protos); 01485 AST_LIST_TRAVERSE(&protos, cur, list) { 01486 if (cur->type == chan->tech->type) 01487 break; 01488 } 01489 AST_LIST_UNLOCK(&protos); 01490 01491 return cur; 01492 }
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 3178 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.
03179 { 03180 ast_channel_lock(chan); 03181 03182 /* Remove the callback from the IO context */ 03183 ast_io_remove(rtp->io, iod[0]); 03184 03185 /* Restore file descriptors */ 03186 chan->fds[0] = fds[0]; 03187 ast_channel_unlock(chan); 03188 03189 /* Restore callback mode if previously used */ 03190 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03191 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03192 03193 return 0; 03194 }
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 3197 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03198 { 03199 ast_mutex_lock(&rtp0->bridge_lock); 03200 rtp0->bridged = rtp1; 03201 ast_mutex_unlock(&rtp0->bridge_lock); 03202 03203 return; 03204 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 668 of file rtp.c.
References AST_FRAME_DTMF_END, ast_log(), ast_rtp::dtmfcount, f, LOG_DEBUG, option_debug, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00669 { 00670 unsigned int event; 00671 char resp = 0; 00672 struct ast_frame *f = NULL; 00673 event = ntohl(*((unsigned int *)(data))); 00674 event &= 0x001F; 00675 if (option_debug > 2 || rtpdebug) 00676 ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len); 00677 if (event < 10) { 00678 resp = '0' + event; 00679 } else if (event < 11) { 00680 resp = '*'; 00681 } else if (event < 12) { 00682 resp = '#'; 00683 } else if (event < 16) { 00684 resp = 'A' + (event - 12); 00685 } else if (event < 17) { 00686 resp = 'X'; 00687 } 00688 if (rtp->resp && (rtp->resp != resp)) { 00689 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00690 } 00691 rtp->resp = resp; 00692 rtp->dtmfcount = dtmftimeout; 00693 return f; 00694 }
static struct ast_frame* process_rfc2833 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp | |||
) | [static] |
Process RTP DTMF and events according to RFC 2833.
RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
rtp | ||
data | ||
len | ||
seqno |
Definition at line 707 of file rtp.c.
References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_null_frame, ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), ast_rtp::dtmfcount, f, FLAG_DTMF_COMPENSATE, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, ast_frame::samples, and send_dtmf().
Referenced by ast_rtp_read().
00708 { 00709 unsigned int event; 00710 unsigned int event_end; 00711 unsigned int samples; 00712 char resp = 0; 00713 struct ast_frame *f = NULL; 00714 00715 /* Figure out event, event end, and samples */ 00716 event = ntohl(*((unsigned int *)(data))); 00717 event >>= 24; 00718 event_end = ntohl(*((unsigned int *)(data))); 00719 event_end <<= 8; 00720 event_end >>= 24; 00721 samples = ntohl(*((unsigned int *)(data))); 00722 samples &= 0xFFFF; 00723 00724 /* Print out debug if turned on */ 00725 if (rtpdebug || option_debug > 2) 00726 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00727 00728 /* Figure out what digit was pressed */ 00729 if (event < 10) { 00730 resp = '0' + event; 00731 } else if (event < 11) { 00732 resp = '*'; 00733 } else if (event < 12) { 00734 resp = '#'; 00735 } else if (event < 16) { 00736 resp = 'A' + (event - 12); 00737 } else if (event < 17) { /* Event 16: Hook flash */ 00738 resp = 'X'; 00739 } else { 00740 /* Not a supported event */ 00741 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 00742 return &ast_null_frame; 00743 } 00744 00745 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00746 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 00747 rtp->resp = resp; 00748 rtp->dtmfcount = 0; 00749 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00750 f->len = 0; 00751 rtp->lastevent = timestamp; 00752 } 00753 } else { 00754 if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) { 00755 rtp->resp = resp; 00756 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00757 rtp->dtmfcount = dtmftimeout; 00758 } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) { 00759 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00760 f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */ 00761 rtp->resp = 0; 00762 rtp->dtmfcount = 0; 00763 rtp->lastevent = seqno; 00764 } 00765 } 00766 00767 return f; 00768 }
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 776 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().
00777 { 00778 struct ast_frame *f = NULL; 00779 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00780 totally help us out becuase we don't have an engine to keep it going and we are not 00781 guaranteed to have it every 20ms or anything */ 00782 if (rtpdebug) 00783 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00784 00785 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00786 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00787 ast_inet_ntoa(rtp->them.sin_addr)); 00788 ast_set_flag(rtp, FLAG_3389_WARNING); 00789 } 00790 00791 /* Must have at least one byte */ 00792 if (!len) 00793 return NULL; 00794 if (len < 24) { 00795 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00796 rtp->f.datalen = len - 1; 00797 rtp->f.offset = AST_FRIENDLY_OFFSET; 00798 memcpy(rtp->f.data, data + 1, len - 1); 00799 } else { 00800 rtp->f.data = NULL; 00801 rtp->f.offset = 0; 00802 rtp->f.datalen = 0; 00803 } 00804 rtp->f.frametype = AST_FRAME_CNG; 00805 rtp->f.subclass = data[0] & 0x7f; 00806 rtp->f.datalen = len - 1; 00807 rtp->f.samples = 0; 00808 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00809 f = &rtp->f; 00810 return f; 00811 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 654 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00655 { 00656 if (rtcpdebug == 0) 00657 return 0; 00658 if (rtcpdebugaddr.sin_addr.s_addr) { 00659 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00660 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00661 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00662 return 0; 00663 } 00664 return 1; 00665 }
static int rtcp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3617 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip().
03617 { 03618 if (argc != 2) { 03619 if (argc != 4) 03620 return RESULT_SHOWUSAGE; 03621 return rtcp_do_debug_ip(fd, argc, argv); 03622 } 03623 rtcpdebug = 1; 03624 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03625 ast_cli(fd, "RTCP Debugging Enabled\n"); 03626 return RESULT_SUCCESS; 03627 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3605 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip_deprecated().
03605 { 03606 if (argc != 3) { 03607 if (argc != 5) 03608 return RESULT_SHOWUSAGE; 03609 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03610 } 03611 rtcpdebug = 1; 03612 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03613 ast_cli(fd, "RTCP Debugging Enabled\n"); 03614 return RESULT_SUCCESS; 03615 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3562 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtcp_do_debug().
03563 { 03564 struct hostent *hp; 03565 struct ast_hostent ahp; 03566 int port = 0; 03567 char *p, *arg; 03568 if (argc != 4) 03569 return RESULT_SHOWUSAGE; 03570 03571 arg = argv[3]; 03572 p = strstr(arg, ":"); 03573 if (p) { 03574 *p = '\0'; 03575 p++; 03576 port = atoi(p); 03577 } 03578 hp = ast_gethostbyname(arg, &ahp); 03579 if (hp == NULL) 03580 return RESULT_SHOWUSAGE; 03581 rtcpdebugaddr.sin_family = AF_INET; 03582 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03583 rtcpdebugaddr.sin_port = htons(port); 03584 if (port == 0) 03585 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03586 else 03587 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03588 rtcpdebug = 1; 03589 return RESULT_SUCCESS; 03590 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3532 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().
03533 { 03534 struct hostent *hp; 03535 struct ast_hostent ahp; 03536 int port = 0; 03537 char *p, *arg; 03538 if (argc != 5) 03539 return RESULT_SHOWUSAGE; 03540 03541 arg = argv[4]; 03542 p = strstr(arg, ":"); 03543 if (p) { 03544 *p = '\0'; 03545 p++; 03546 port = atoi(p); 03547 } 03548 hp = ast_gethostbyname(arg, &ahp); 03549 if (hp == NULL) 03550 return RESULT_SHOWUSAGE; 03551 rtcpdebugaddr.sin_family = AF_INET; 03552 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03553 rtcpdebugaddr.sin_port = htons(port); 03554 if (port == 0) 03555 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03556 else 03557 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03558 rtcpdebug = 1; 03559 return RESULT_SUCCESS; 03560 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3638 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03638 { 03639 if (argc != 2) { 03640 return RESULT_SHOWUSAGE; 03641 } 03642 rtcpstats = 1; 03643 ast_cli(fd, "RTCP Stats Enabled\n"); 03644 return RESULT_SUCCESS; 03645 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3629 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03629 { 03630 if (argc != 3) { 03631 return RESULT_SHOWUSAGE; 03632 } 03633 rtcpstats = 1; 03634 ast_cli(fd, "RTCP Stats Enabled\n"); 03635 return RESULT_SUCCESS; 03636 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3665 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03666 { 03667 if (argc != 3) 03668 return RESULT_SHOWUSAGE; 03669 rtcpdebug = 0; 03670 ast_cli(fd,"RTCP Debugging Disabled\n"); 03671 return RESULT_SUCCESS; 03672 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3656 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03657 { 03658 if (argc != 4) 03659 return RESULT_SHOWUSAGE; 03660 rtcpdebug = 0; 03661 ast_cli(fd,"RTCP Debugging Disabled\n"); 03662 return RESULT_SUCCESS; 03663 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3683 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03684 { 03685 if (argc != 3) 03686 return RESULT_SHOWUSAGE; 03687 rtcpstats = 0; 03688 ast_cli(fd,"RTCP Stats Disabled\n"); 03689 return RESULT_SUCCESS; 03690 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3674 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03675 { 03676 if (argc != 4) 03677 return RESULT_SHOWUSAGE; 03678 rtcpstats = 0; 03679 ast_cli(fd,"RTCP Stats Disabled\n"); 03680 return RESULT_SUCCESS; 03681 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 641 of file rtp.c.
Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_senddigit_continuation(), ast_rtp_senddigit_end(), and bridge_p2p_rtp_write().
00642 { 00643 if (rtpdebug == 0) 00644 return 0; 00645 if (rtpdebugaddr.sin_addr.s_addr) { 00646 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00647 && (rtpdebugaddr.sin_port != addr->sin_port)) 00648 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00649 return 0; 00650 } 00651 return 1; 00652 }
static int rtp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3592 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtp_do_debug_ip().
03593 { 03594 if (argc != 2) { 03595 if (argc != 4) 03596 return RESULT_SHOWUSAGE; 03597 return rtp_do_debug_ip(fd, argc, argv); 03598 } 03599 rtpdebug = 1; 03600 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03601 ast_cli(fd, "RTP Debugging Enabled\n"); 03602 return RESULT_SUCCESS; 03603 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3502 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtp_do_debug().
03503 { 03504 struct hostent *hp; 03505 struct ast_hostent ahp; 03506 int port = 0; 03507 char *p, *arg; 03508 03509 if (argc != 4) 03510 return RESULT_SHOWUSAGE; 03511 arg = argv[3]; 03512 p = strstr(arg, ":"); 03513 if (p) { 03514 *p = '\0'; 03515 p++; 03516 port = atoi(p); 03517 } 03518 hp = ast_gethostbyname(arg, &ahp); 03519 if (hp == NULL) 03520 return RESULT_SHOWUSAGE; 03521 rtpdebugaddr.sin_family = AF_INET; 03522 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03523 rtpdebugaddr.sin_port = htons(port); 03524 if (port == 0) 03525 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03526 else 03527 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03528 rtpdebug = 1; 03529 return RESULT_SUCCESS; 03530 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3647 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03648 { 03649 if (argc != 3) 03650 return RESULT_SHOWUSAGE; 03651 rtpdebug = 0; 03652 ast_cli(fd,"RTP Debugging Disabled\n"); 03653 return RESULT_SUCCESS; 03654 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1855 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01856 { 01857 int s; 01858 long flags; 01859 s = socket(AF_INET, SOCK_DGRAM, 0); 01860 if (s > -1) { 01861 flags = fcntl(s, F_GETFL); 01862 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01863 #ifdef SO_NO_CHECK 01864 if (nochecksums) 01865 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01866 #endif 01867 } 01868 return s; 01869 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 813 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and f.
Referenced by p2p_callback_disable().
00814 { 00815 struct ast_rtp *rtp = cbdata; 00816 struct ast_frame *f; 00817 f = ast_rtp_read(rtp); 00818 if (f) { 00819 if (rtp->callback) 00820 rtp->callback(rtp, f, rtp->data); 00821 } 00822 return 1; 00823 }
static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static] |
Definition at line 615 of file rtp.c.
References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_test_flag, ast_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::f, FLAG_DTMF_COMPENSATE, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, option_debug, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read(), process_cisco_dtmf(), and process_rfc2833().
00616 { 00617 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00618 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00619 if (option_debug) 00620 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00621 rtp->resp = 0; 00622 return &ast_null_frame; 00623 } 00624 if (option_debug) 00625 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00626 if (rtp->resp == 'X') { 00627 rtp->f.frametype = AST_FRAME_CONTROL; 00628 rtp->f.subclass = AST_CONTROL_FLASH; 00629 } else { 00630 rtp->f.frametype = type; 00631 rtp->f.subclass = rtp->resp; 00632 } 00633 rtp->f.datalen = 0; 00634 rtp->f.samples = 0; 00635 rtp->f.mallocd = 0; 00636 rtp->f.src = "RTP"; 00637 return &rtp->f; 00638 00639 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
Definition at line 299 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().
00300 { 00301 switch(msg) { 00302 case STUN_MAPPED_ADDRESS: 00303 return "Mapped Address"; 00304 case STUN_RESPONSE_ADDRESS: 00305 return "Response Address"; 00306 case STUN_CHANGE_REQUEST: 00307 return "Change Request"; 00308 case STUN_SOURCE_ADDRESS: 00309 return "Source Address"; 00310 case STUN_CHANGED_ADDRESS: 00311 return "Changed Address"; 00312 case STUN_USERNAME: 00313 return "Username"; 00314 case STUN_PASSWORD: 00315 return "Password"; 00316 case STUN_MESSAGE_INTEGRITY: 00317 return "Message Integrity"; 00318 case STUN_ERROR_CODE: 00319 return "Error Code"; 00320 case STUN_UNKNOWN_ATTRIBUTES: 00321 return "Unknown Attributes"; 00322 case STUN_REFLECTED_FROM: 00323 return "Reflected From"; 00324 } 00325 return "Non-RFC3489 Attribute"; 00326 }
static int stun_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3692 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03693 { 03694 if (argc != 2) { 03695 return RESULT_SHOWUSAGE; 03696 } 03697 stundebug = 1; 03698 ast_cli(fd, "STUN Debugging Enabled\n"); 03699 return RESULT_SUCCESS; 03700 }
static int stun_handle_packet | ( | int | s, | |
struct sockaddr_in * | src, | |||
unsigned char * | data, | |||
size_t | len | |||
) | [static] |
Definition at line 423 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().
00424 { 00425 struct stun_header *resp, *hdr = (struct stun_header *)data; 00426 struct stun_attr *attr; 00427 struct stun_state st; 00428 int ret = STUN_IGNORE; 00429 unsigned char respdata[1024]; 00430 int resplen, respleft; 00431 00432 if (len < sizeof(struct stun_header)) { 00433 if (option_debug) 00434 ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header)); 00435 return -1; 00436 } 00437 if (stundebug) 00438 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen)); 00439 if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) { 00440 if (option_debug) 00441 ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header)); 00442 } else 00443 len = ntohs(hdr->msglen); 00444 data += sizeof(struct stun_header); 00445 memset(&st, 0, sizeof(st)); 00446 while(len) { 00447 if (len < sizeof(struct stun_attr)) { 00448 if (option_debug) 00449 ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr)); 00450 break; 00451 } 00452 attr = (struct stun_attr *)data; 00453 if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) { 00454 if (option_debug) 00455 ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len); 00456 break; 00457 } 00458 if (stun_process_attr(&st, attr)) { 00459 if (option_debug) 00460 ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00461 break; 00462 } 00463 /* Clear attribute in case previous entry was a string */ 00464 attr->attr = 0; 00465 data += ntohs(attr->len) + sizeof(struct stun_attr); 00466 len -= ntohs(attr->len) + sizeof(struct stun_attr); 00467 } 00468 /* Null terminate any string */ 00469 *data = '\0'; 00470 resp = (struct stun_header *)respdata; 00471 resplen = 0; 00472 respleft = sizeof(respdata) - sizeof(struct stun_header); 00473 resp->id = hdr->id; 00474 resp->msgtype = 0; 00475 resp->msglen = 0; 00476 attr = (struct stun_attr *)resp->ies; 00477 if (!len) { 00478 switch(ntohs(hdr->msgtype)) { 00479 case STUN_BINDREQ: 00480 if (stundebug) 00481 ast_verbose("STUN Bind Request, username: %s\n", 00482 st.username ? st.username : "<none>"); 00483 if (st.username) 00484 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00485 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00486 resp->msglen = htons(resplen); 00487 resp->msgtype = htons(STUN_BINDRESP); 00488 stun_send(s, src, resp); 00489 ret = STUN_ACCEPT; 00490 break; 00491 default: 00492 if (stundebug) 00493 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00494 } 00495 } 00496 return ret; 00497 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
Definition at line 280 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00281 { 00282 switch(msg) { 00283 case STUN_BINDREQ: 00284 return "Binding Request"; 00285 case STUN_BINDRESP: 00286 return "Binding Response"; 00287 case STUN_BINDERR: 00288 return "Binding Error Response"; 00289 case STUN_SECREQ: 00290 return "Shared Secret Request"; 00291 case STUN_SECRESP: 00292 return "Shared Secret Response"; 00293 case STUN_SECERR: 00294 return "Shared Secret Error Response"; 00295 } 00296 return "Non-RFC3489 Message"; 00297 }
static int stun_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3702 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03703 { 03704 if (argc != 3) 03705 return RESULT_SHOWUSAGE; 03706 stundebug = 0; 03707 ast_cli(fd, "STUN Debugging Disabled\n"); 03708 return RESULT_SUCCESS; 03709 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 333 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().
00334 { 00335 if (stundebug) 00336 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00337 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00338 switch(ntohs(attr->attr)) { 00339 case STUN_USERNAME: 00340 state->username = (const char *) (attr->value); 00341 break; 00342 case STUN_PASSWORD: 00343 state->password = (const char *) (attr->value); 00344 break; 00345 default: 00346 if (stundebug) 00347 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00348 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00349 } 00350 return 0; 00351 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
Definition at line 390 of file rtp.c.
References ast_random(), stun_trans_id::id, and stun_header::id.
Referenced by ast_rtp_stun_request().
00391 { 00392 int x; 00393 for (x=0;x<4;x++) 00394 req->id.id[x] = ast_random(); 00395 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
Definition at line 384 of file rtp.c.
References stun_header::msglen.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00385 { 00386 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00387 (struct sockaddr *)dst, sizeof(*dst)); 00388 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 502 of file rtp.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00503 { 00504 unsigned int sec, usec, frac; 00505 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00506 usec = tv.tv_usec; 00507 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00508 *msw = sec; 00509 *lsw = frac; 00510 }
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 1351 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 1386 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 1352 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), find_subscription_type(), g723_len(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), parse_information(), parse_setup(), sla_load_config(), subscription_type2str(), and yyparse().