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