#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"
Include dependency graph for rtp.c:
Go to the source code of this file.
Data Structures | |
struct | __attribute__ |
struct | ast_rtcp |
Structure defining an RTCP session. More... | |
struct | ast_rtp |
RTP session description. 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 |
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 | AST_LIST_HEAD_STATIC (protos, ast_rtp_protocol) |
List of current sessions. | |
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 (void *data) |
Write and RTCP packet to the far end. | |
static int | ast_rtcp_write_rr (void *data) |
Send RTCP recipient's report. | |
static int | ast_rtcp_write_sr (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. | |
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) |
Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line). | |
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 | |
void | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options) |
Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line. | |
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) |
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 [] |
stun_addr | packed |
stun_attr | packed |
stun_header | packed |
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) |
Definition at line 193 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 194 of file rtp.c.
Referenced by ast_rtp_bridge(), ast_rtp_setdtmfcompensate(), process_rfc2833(), and send_dtmf().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 190 of file rtp.c.
Referenced by ast_rtp_bridge(), ast_rtp_new_init(), and ast_rtp_setdtmf().
#define FLAG_HAS_STUN (1 << 8) |
#define FLAG_NAT_ACTIVE (3 << 1) |
Definition at line 187 of file rtp.c.
Referenced by ast_rtp_early_bridge(), ast_rtp_getnat(), ast_rtp_make_compatible(), ast_rtp_raw_write(), ast_rtp_read(), bridge_native_loop(), and bridge_p2p_rtp_write().
#define FLAG_NAT_INACTIVE (0 << 1) |
Definition at line 188 of file rtp.c.
Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().
#define FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
Definition at line 189 of file rtp.c.
Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().
#define FLAG_P2P_NEED_DTMF (1 << 5) |
#define FLAG_P2P_SENT_MARK (1 << 4) |
Definition at line 191 of file rtp.c.
Referenced by ast_rtp_stop(), bridge_p2p_loop(), and bridge_p2p_rtp_write().
#define MAX_TIMESTAMP_SKEW 640 |
Definition at line 60 of file rtp.c.
Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp().
#define RTCP_DEFAULT_INTERVALMS 5000 |
#define RTCP_MAX_INTERVALMS 60000 |
Max milli-seconds between RTCP reports we send
Definition at line 65 of file rtp.c.
Referenced by ast_rtp_reload().
#define RTCP_MIN_INTERVALMS 500 |
Min milli-seconds between RTCP reports we send
Definition at line 64 of file rtp.c.
Referenced by ast_rtp_reload().
#define RTCP_PT_BYE 203 |
#define RTCP_PT_FUR 192 |
Definition at line 67 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr().
#define RTCP_PT_RR 201 |
#define RTCP_PT_SDES 202 |
Definition at line 70 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr().
#define RTCP_PT_SR 200 |
#define RTP_SEQ_MOD (1<<16) |
A sequence number can't be more than 16 bits
Definition at line 62 of file rtp.c.
Referenced by ast_rtp_read().
#define STUN_ACCEPT (1) |
#define STUN_BINDERR 0x0111 |
#define STUN_BINDREQ 0x0001 |
Definition at line 261 of file rtp.c.
Referenced by ast_rtp_stun_request(), stun_handle_packet(), and stun_msg2str().
#define STUN_BINDRESP 0x0101 |
#define STUN_CHANGE_REQUEST 0x0003 |
#define STUN_CHANGED_ADDRESS 0x0005 |
#define STUN_ERROR_CODE 0x0009 |
#define STUN_IGNORE (0) |
#define STUN_MAPPED_ADDRESS 0x0001 |
#define STUN_MESSAGE_INTEGRITY 0x0008 |
#define STUN_PASSWORD 0x0007 |
#define STUN_REFLECTED_FROM 0x000b |
#define STUN_RESPONSE_ADDRESS 0x0002 |
#define STUN_SECERR 0x0112 |
#define STUN_SECREQ 0x0002 |
#define STUN_SECRESP 0x0102 |
#define STUN_SOURCE_ADDRESS 0x0004 |
#define STUN_UNKNOWN_ATTRIBUTES 0x000a |
#define STUN_USERNAME 0x0006 |
Definition at line 273 of file rtp.c.
Referenced by ast_rtp_stun_request(), stun_attr2str(), stun_handle_packet(), and stun_process_attr().
static void append_attr_address | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
struct sockaddr_in * | sin, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 366 of file rtp.c.
References stun_addr::addr.
Referenced by stun_handle_packet().
00367 { 00368 int size = sizeof(**attr) + 8; 00369 struct stun_addr *addr; 00370 if (*left > size) { 00371 (*attr)->attr = htons(attrval); 00372 (*attr)->len = htons(8); 00373 addr = (struct stun_addr *)((*attr)->value); 00374 addr->unused = 0; 00375 addr->family = 0x01; 00376 addr->port = sin->sin_port; 00377 addr->addr = sin->sin_addr.s_addr; 00378 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00379 *len += size; 00380 *left -= size; 00381 } 00382 }
static void append_attr_string | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
const char * | s, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 353 of file rtp.c.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00354 { 00355 int size = sizeof(**attr) + strlen(s); 00356 if (*left > size) { 00357 (*attr)->attr = htons(attrval); 00358 (*attr)->len = htons(strlen(s)); 00359 memcpy((*attr)->value, s, strlen(s)); 00360 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00361 *len += size; 00362 *left -= size; 00363 } 00364 }
static AST_LIST_HEAD_STATIC | ( | protos | , | |
ast_rtp_protocol | ||||
) | [static] |
List of current sessions.
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 524 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00525 { 00526 unsigned int interval; 00527 /*! \todo XXX Do a more reasonable calculation on this one 00528 * Look in RFC 3550 Section A.7 for an example*/ 00529 interval = rtcpinterval; 00530 return interval; 00531 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 517 of file rtp.c.
References ast_rtp::rtcp, and ast_rtcp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), sip_new(), and start_rtp().
static struct ast_rtcp* ast_rtcp_new | ( | void | ) | [static] |
Initialize a new RTCP session.
Definition at line 1849 of file rtp.c.
References ast_calloc, ast_log(), free, LOG_WARNING, rtp_socket(), and ast_rtcp::s.
Referenced by ast_rtp_new_with_bindaddr().
01850 { 01851 struct ast_rtcp *rtcp; 01852 01853 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01854 return NULL; 01855 rtcp->s = rtp_socket(); 01856 rtcp->us.sin_family = AF_INET; 01857 rtcp->them.sin_family = AF_INET; 01858 01859 if (rtcp->s < 0) { 01860 free(rtcp); 01861 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01862 return NULL; 01863 } 01864 01865 return rtcp; 01866 }
Definition at line 822 of file rtp.c.
References ast_rtcp::accumulated_transit, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), CRASH, ast_frame::datalen, 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_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().
00823 { 00824 socklen_t len; 00825 int position, i, packetwords; 00826 int res; 00827 struct sockaddr_in sin; 00828 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00829 unsigned int *rtcpheader; 00830 int pt; 00831 struct timeval now; 00832 unsigned int length; 00833 int rc; 00834 double rttsec; 00835 uint64_t rtt = 0; 00836 unsigned int dlsr; 00837 unsigned int lsr; 00838 unsigned int msw; 00839 unsigned int lsw; 00840 unsigned int comp; 00841 struct ast_frame *f = &ast_null_frame; 00842 00843 if (!rtp || !rtp->rtcp) 00844 return &ast_null_frame; 00845 00846 len = sizeof(sin); 00847 00848 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00849 0, (struct sockaddr *)&sin, &len); 00850 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00851 00852 if (res < 0) { 00853 if (errno == EBADF) 00854 CRASH; 00855 if (errno != EAGAIN) { 00856 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00857 return NULL; 00858 } 00859 return &ast_null_frame; 00860 } 00861 00862 packetwords = res / 4; 00863 00864 if (rtp->nat) { 00865 /* Send to whoever sent to us */ 00866 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00867 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00868 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00869 if (option_debug || rtpdebug) 00870 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)); 00871 } 00872 } 00873 00874 if (option_debug) 00875 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00876 00877 /* Process a compound packet */ 00878 position = 0; 00879 while (position < packetwords) { 00880 i = position; 00881 length = ntohl(rtcpheader[i]); 00882 pt = (length & 0xff0000) >> 16; 00883 rc = (length & 0x1f000000) >> 24; 00884 length &= 0xffff; 00885 00886 if ((i + length) > packetwords) { 00887 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00888 return &ast_null_frame; 00889 } 00890 00891 if (rtcp_debug_test_addr(&sin)) { 00892 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00893 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00894 ast_verbose("Reception reports: %d\n", rc); 00895 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00896 } 00897 00898 i += 2; /* Advance past header and ssrc */ 00899 00900 switch (pt) { 00901 case RTCP_PT_SR: 00902 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00903 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00904 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00905 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00906 00907 if (rtcp_debug_test_addr(&sin)) { 00908 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00909 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00910 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00911 } 00912 i += 5; 00913 if (rc < 1) 00914 break; 00915 /* Intentional fall through */ 00916 case RTCP_PT_RR: 00917 /* Don't handle multiple reception reports (rc > 1) yet */ 00918 /* Calculate RTT per RFC */ 00919 gettimeofday(&now, NULL); 00920 timeval2ntp(now, &msw, &lsw); 00921 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00922 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00923 lsr = ntohl(rtcpheader[i + 4]); 00924 dlsr = ntohl(rtcpheader[i + 5]); 00925 rtt = comp - lsr - dlsr; 00926 00927 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00928 sess->ee_delay = (eedelay * 1000) / 65536; */ 00929 if (rtt < 4294) { 00930 rtt = (rtt * 1000000) >> 16; 00931 } else { 00932 rtt = (rtt * 1000) >> 16; 00933 rtt *= 1000; 00934 } 00935 rtt = rtt / 1000.; 00936 rttsec = rtt / 1000.; 00937 00938 if (comp - dlsr >= lsr) { 00939 rtp->rtcp->accumulated_transit += rttsec; 00940 rtp->rtcp->rtt = rttsec; 00941 if (rtp->rtcp->maxrtt<rttsec) 00942 rtp->rtcp->maxrtt = rttsec; 00943 if (rtp->rtcp->minrtt>rttsec) 00944 rtp->rtcp->minrtt = rttsec; 00945 } else if (rtcp_debug_test_addr(&sin)) { 00946 ast_verbose("Internal RTCP NTP clock skew detected: " 00947 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 00948 "diff=%d\n", 00949 lsr, comp, dlsr, dlsr / 65536, 00950 (dlsr % 65536) * 1000 / 65536, 00951 dlsr - (comp - lsr)); 00952 } 00953 } 00954 00955 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00956 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00957 if (rtcp_debug_test_addr(&sin)) { 00958 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00959 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00960 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00961 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00962 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00963 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00964 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00965 if (rtt) 00966 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 00967 } 00968 break; 00969 case RTCP_PT_FUR: 00970 if (rtcp_debug_test_addr(&sin)) 00971 ast_verbose("Received an RTCP Fast Update Request\n"); 00972 rtp->f.frametype = AST_FRAME_CONTROL; 00973 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00974 rtp->f.datalen = 0; 00975 rtp->f.samples = 0; 00976 rtp->f.mallocd = 0; 00977 rtp->f.src = "RTP"; 00978 f = &rtp->f; 00979 break; 00980 case RTCP_PT_SDES: 00981 if (rtcp_debug_test_addr(&sin)) 00982 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00983 break; 00984 case RTCP_PT_BYE: 00985 if (rtcp_debug_test_addr(&sin)) 00986 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00987 break; 00988 default: 00989 if (option_debug) 00990 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)); 00991 break; 00992 } 00993 position += (length + 1); 00994 } 00995 00996 return f; 00997 }
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 2314 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02315 { 02316 struct ast_rtp *rtp = data; 02317 int res; 02318 02319 rtp->rtcp->sendfur = 1; 02320 res = ast_rtcp_write(data); 02321 02322 return res; 02323 }
static int ast_rtcp_write | ( | void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2539 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().
02540 { 02541 struct ast_rtp *rtp = data; 02542 int res; 02543 02544 if (!rtp || !rtp->rtcp) 02545 return 0; 02546 02547 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02548 res = ast_rtcp_write_sr(data); 02549 else 02550 res = ast_rtcp_write_rr(data); 02551 02552 return res; 02553 }
static int ast_rtcp_write_rr | ( | void * | data | ) | [static] |
Send RTCP recipient's report.
Definition at line 2440 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, 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().
02441 { 02442 struct ast_rtp *rtp = data; 02443 int res; 02444 int len = 32; 02445 unsigned int lost; 02446 unsigned int extended; 02447 unsigned int expected; 02448 unsigned int expected_interval; 02449 unsigned int received_interval; 02450 int lost_interval; 02451 struct timeval now; 02452 unsigned int *rtcpheader; 02453 char bdata[1024]; 02454 struct timeval dlsr; 02455 int fraction; 02456 02457 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02458 return 0; 02459 02460 if (!rtp->rtcp->them.sin_addr.s_addr) { 02461 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02462 if (rtp->rtcp->schedid > 0) 02463 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02464 rtp->rtcp->schedid = -1; 02465 return 0; 02466 } 02467 02468 extended = rtp->cycles + rtp->lastrxseqno; 02469 expected = extended - rtp->seedrxseqno + 1; 02470 lost = expected - rtp->rxcount; 02471 expected_interval = expected - rtp->rtcp->expected_prior; 02472 rtp->rtcp->expected_prior = expected; 02473 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02474 rtp->rtcp->received_prior = rtp->rxcount; 02475 lost_interval = expected_interval - received_interval; 02476 if (expected_interval == 0 || lost_interval <= 0) 02477 fraction = 0; 02478 else 02479 fraction = (lost_interval << 8) / expected_interval; 02480 gettimeofday(&now, NULL); 02481 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02482 rtcpheader = (unsigned int *)bdata; 02483 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02484 rtcpheader[1] = htonl(rtp->ssrc); 02485 rtcpheader[2] = htonl(rtp->themssrc); 02486 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02487 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02488 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02489 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02490 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02491 02492 if (rtp->rtcp->sendfur) { 02493 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02494 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02495 len += 8; 02496 rtp->rtcp->sendfur = 0; 02497 } 02498 02499 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02500 it can change mid call, and SDES can't) */ 02501 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02502 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02503 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02504 len += 12; 02505 02506 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02507 02508 if (res < 0) { 02509 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02510 /* Remove the scheduler */ 02511 if (rtp->rtcp->schedid > 0) 02512 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02513 rtp->rtcp->schedid = -1; 02514 return 0; 02515 } 02516 02517 rtp->rtcp->rr_count++; 02518 02519 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02520 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02521 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02522 " IA jitter: %.4f\n" 02523 " Their last SR: %u\n" 02524 " DLSR: %4.4f (sec)\n\n", 02525 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02526 ntohs(rtp->rtcp->them.sin_port), 02527 rtp->ssrc, rtp->themssrc, fraction, lost, 02528 rtp->rxjitter, 02529 rtp->rtcp->themrxlsr, 02530 (double)(ntohl(rtcpheader[7])/65536.0)); 02531 } 02532 02533 return res; 02534 }
static int ast_rtcp_write_sr | ( | void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2326 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, 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().
02327 { 02328 struct ast_rtp *rtp = data; 02329 int res; 02330 int len = 0; 02331 struct timeval now; 02332 unsigned int now_lsw; 02333 unsigned int now_msw; 02334 unsigned int *rtcpheader; 02335 unsigned int lost; 02336 unsigned int extended; 02337 unsigned int expected; 02338 unsigned int expected_interval; 02339 unsigned int received_interval; 02340 int lost_interval; 02341 int fraction; 02342 struct timeval dlsr; 02343 char bdata[512]; 02344 02345 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02346 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02347 return 0; 02348 02349 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02350 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02351 if (rtp->rtcp->schedid > 0) 02352 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02353 rtp->rtcp->schedid = -1; 02354 return 0; 02355 } 02356 02357 gettimeofday(&now, NULL); 02358 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02359 rtcpheader = (unsigned int *)bdata; 02360 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02361 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02362 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02363 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02364 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02365 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02366 len += 28; 02367 02368 extended = rtp->cycles + rtp->lastrxseqno; 02369 expected = extended - rtp->seedrxseqno + 1; 02370 if (rtp->rxcount > expected) 02371 expected += rtp->rxcount - expected; 02372 lost = expected - rtp->rxcount; 02373 expected_interval = expected - rtp->rtcp->expected_prior; 02374 rtp->rtcp->expected_prior = expected; 02375 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02376 rtp->rtcp->received_prior = rtp->rxcount; 02377 lost_interval = expected_interval - received_interval; 02378 if (expected_interval == 0 || lost_interval <= 0) 02379 fraction = 0; 02380 else 02381 fraction = (lost_interval << 8) / expected_interval; 02382 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02383 rtcpheader[7] = htonl(rtp->themssrc); 02384 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02385 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02386 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02387 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02388 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02389 len += 24; 02390 02391 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02392 02393 if (rtp->rtcp->sendfur) { 02394 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02395 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02396 len += 8; 02397 rtp->rtcp->sendfur = 0; 02398 } 02399 02400 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02401 /* it can change mid call, and SDES can't) */ 02402 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02403 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02404 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02405 len += 12; 02406 02407 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02408 if (res < 0) { 02409 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)); 02410 if (rtp->rtcp->schedid > 0) 02411 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02412 rtp->rtcp->schedid = -1; 02413 return 0; 02414 } 02415 02416 /* FIXME Don't need to get a new one */ 02417 gettimeofday(&rtp->rtcp->txlsr, NULL); 02418 rtp->rtcp->sr_count++; 02419 02420 rtp->rtcp->lastsrtxcount = rtp->txcount; 02421 02422 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02423 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02424 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02425 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02426 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02427 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02428 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02429 ast_verbose(" Report block:\n"); 02430 ast_verbose(" Fraction lost: %u\n", fraction); 02431 ast_verbose(" Cumulative loss: %u\n", lost); 02432 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02433 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02434 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02435 } 02436 return res; 02437 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 397 of file rtp.c.
Referenced by process_sdp().
00398 { 00399 return sizeof(struct ast_rtp); 00400 }
enum ast_bridge_result ast_rtp_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
int | timeoutms | |||
) |
Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
Definition at line 3222 of file rtp.c.
References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, 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_DTMF_COMPENSATE, 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, 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.
03223 { 03224 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03225 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03226 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03227 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03228 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03229 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03230 int codec0 = 0, codec1 = 0; 03231 void *pvt0 = NULL, *pvt1 = NULL; 03232 03233 /* Lock channels */ 03234 ast_channel_lock(c0); 03235 while(ast_channel_trylock(c1)) { 03236 ast_channel_unlock(c0); 03237 usleep(1); 03238 ast_channel_lock(c0); 03239 } 03240 03241 /* Find channel driver interfaces */ 03242 if (!(pr0 = get_proto(c0))) { 03243 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03244 ast_channel_unlock(c0); 03245 ast_channel_unlock(c1); 03246 return AST_BRIDGE_FAILED; 03247 } 03248 if (!(pr1 = get_proto(c1))) { 03249 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03250 ast_channel_unlock(c0); 03251 ast_channel_unlock(c1); 03252 return AST_BRIDGE_FAILED; 03253 } 03254 03255 /* Get channel specific interface structures */ 03256 pvt0 = c0->tech_pvt; 03257 pvt1 = c1->tech_pvt; 03258 03259 /* Get audio and video interface (if native bridge is possible) */ 03260 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03261 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03262 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03263 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03264 03265 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03266 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03267 audio_p0_res = AST_RTP_GET_FAILED; 03268 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03269 audio_p1_res = AST_RTP_GET_FAILED; 03270 03271 /* Check if a bridge is possible (partial/native) */ 03272 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03273 /* Somebody doesn't want to play... */ 03274 ast_channel_unlock(c0); 03275 ast_channel_unlock(c1); 03276 return AST_BRIDGE_FAILED_NOWARN; 03277 } 03278 03279 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03280 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03281 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03282 audio_p0_res = AST_RTP_TRY_PARTIAL; 03283 } 03284 03285 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03286 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03287 audio_p1_res = AST_RTP_TRY_PARTIAL; 03288 } 03289 03290 /* If both sides are not using the same method of DTMF transmission 03291 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03292 * -------------------------------------------------- 03293 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03294 * |-----------|------------|-----------------------| 03295 * | Inband | False | True | 03296 * | RFC2833 | True | True | 03297 * | SIP INFO | False | False | 03298 * -------------------------------------------------- 03299 * However, if DTMF from both channels is being monitored by the core, then 03300 * we can still do packet-to-packet bridging, because passing through the 03301 * core will handle DTMF mode translation. 03302 */ 03303 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03304 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03305 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03306 ast_channel_unlock(c0); 03307 ast_channel_unlock(c1); 03308 return AST_BRIDGE_FAILED_NOWARN; 03309 } 03310 audio_p0_res = AST_RTP_TRY_PARTIAL; 03311 audio_p1_res = AST_RTP_TRY_PARTIAL; 03312 } 03313 03314 /* If the core will need to compensate and the P2P bridge will need to feed up DTMF frames then we can not reliably do so yet, so do not P2P bridge */ 03315 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF) && ast_test_flag(p0, FLAG_DTMF_COMPENSATE)) || 03316 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF) && ast_test_flag(p1, FLAG_DTMF_COMPENSATE))) { 03317 ast_channel_unlock(c0); 03318 ast_channel_unlock(c1); 03319 return AST_BRIDGE_FAILED_NOWARN; 03320 } 03321 03322 /* Get codecs from both sides */ 03323 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03324 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03325 if (codec0 && codec1 && !(codec0 & codec1)) { 03326 /* Hey, we can't do native bridging if both parties speak different codecs */ 03327 if (option_debug) 03328 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03329 ast_channel_unlock(c0); 03330 ast_channel_unlock(c1); 03331 return AST_BRIDGE_FAILED_NOWARN; 03332 } 03333 03334 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03335 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03336 struct ast_format_list fmt0, fmt1; 03337 03338 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03339 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03340 if (option_debug) 03341 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03342 ast_channel_unlock(c0); 03343 ast_channel_unlock(c1); 03344 return AST_BRIDGE_FAILED_NOWARN; 03345 } 03346 /* They must also be using the same packetization */ 03347 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03348 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03349 if (fmt0.cur_ms != fmt1.cur_ms) { 03350 if (option_debug) 03351 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03352 ast_channel_unlock(c0); 03353 ast_channel_unlock(c1); 03354 return AST_BRIDGE_FAILED_NOWARN; 03355 } 03356 03357 if (option_verbose > 2) 03358 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03359 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03360 } else { 03361 if (option_verbose > 2) 03362 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03363 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03364 } 03365 03366 return res; 03367 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2697 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp().
02698 { 02699 if (pt < 0 || pt > MAX_RTP_PT) 02700 return 0; /* bogus payload type */ 02701 02702 if (static_RTP_PT[pt].isAstFormat) 02703 return static_RTP_PT[pt].code; 02704 else 02705 return 0; 02706 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Definition at line 2692 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
02693 { 02694 return &rtp->pref; 02695 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2679 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(), start_rtp(), and transmit_response_with_sdp().
02680 { 02681 int x; 02682 for (x = 0; x < 32; x++) { /* Ugly way */ 02683 rtp->pref.order[x] = prefs->order[x]; 02684 rtp->pref.framing[x] = prefs->framing[x]; 02685 } 02686 if (rtp->smoother) 02687 ast_smoother_free(rtp->smoother); 02688 rtp->smoother = NULL; 02689 return 0; 02690 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2096 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().
02097 { 02098 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02099 /*Print some info on the call here */ 02100 ast_verbose(" RTP-stats\n"); 02101 ast_verbose("* Our Receiver:\n"); 02102 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02103 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02104 ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02105 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02106 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02107 ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count); 02108 ast_verbose("* Our Sender:\n"); 02109 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02110 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02111 ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost); 02112 ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter); 02113 ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count); 02114 ast_verbose(" RTT: %f\n", rtp->rtcp->rtt); 02115 } 02116 02117 if (rtp->smoother) 02118 ast_smoother_free(rtp->smoother); 02119 if (rtp->ioid) 02120 ast_io_remove(rtp->io, rtp->ioid); 02121 if (rtp->s > -1) 02122 close(rtp->s); 02123 if (rtp->rtcp) { 02124 if (rtp->rtcp->schedid > 0) 02125 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02126 close(rtp->rtcp->s); 02127 free(rtp->rtcp); 02128 rtp->rtcp=NULL; 02129 } 02130 02131 ast_mutex_destroy(&rtp->bridge_lock); 02132 02133 free(rtp); 02134 }
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 1482 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, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01483 { 01484 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01485 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01486 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01487 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01488 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01489 int srccodec, destcodec, nat_active = 0; 01490 01491 /* Lock channels */ 01492 ast_channel_lock(dest); 01493 if (src) { 01494 while(ast_channel_trylock(src)) { 01495 ast_channel_unlock(dest); 01496 usleep(1); 01497 ast_channel_lock(dest); 01498 } 01499 } 01500 01501 /* Find channel driver interfaces */ 01502 destpr = get_proto(dest); 01503 if (src) 01504 srcpr = get_proto(src); 01505 if (!destpr) { 01506 if (option_debug) 01507 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01508 ast_channel_unlock(dest); 01509 if (src) 01510 ast_channel_unlock(src); 01511 return 0; 01512 } 01513 if (!srcpr) { 01514 if (option_debug) 01515 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01516 ast_channel_unlock(dest); 01517 if (src) 01518 ast_channel_unlock(src); 01519 return 0; 01520 } 01521 01522 /* Get audio and video interface (if native bridge is possible) */ 01523 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01524 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01525 if (srcpr) { 01526 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01527 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01528 } 01529 01530 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01531 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01532 /* Somebody doesn't want to play... */ 01533 ast_channel_unlock(dest); 01534 if (src) 01535 ast_channel_unlock(src); 01536 return 0; 01537 } 01538 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01539 srccodec = srcpr->get_codec(src); 01540 else 01541 srccodec = 0; 01542 if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec) 01543 destcodec = destpr->get_codec(dest); 01544 else 01545 destcodec = 0; 01546 /* Ensure we have at least one matching codec */ 01547 if (!(srccodec & destcodec)) { 01548 ast_channel_unlock(dest); 01549 if (src) 01550 ast_channel_unlock(src); 01551 return 0; 01552 } 01553 /* Consider empty media as non-existant */ 01554 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01555 srcp = NULL; 01556 /* If the client has NAT stuff turned on then just safe NAT is active */ 01557 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01558 nat_active = 1; 01559 /* Bridge media early */ 01560 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01561 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01562 ast_channel_unlock(dest); 01563 if (src) 01564 ast_channel_unlock(src); 01565 if (option_debug) 01566 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01567 return 1; 01568 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 512 of file rtp.c.
References ast_rtp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().
00513 { 00514 return rtp->s; 00515 }
Definition at line 2018 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by ast_rtp_read(), and do_monitor().
02019 { 02020 struct ast_rtp *bridged = NULL; 02021 02022 ast_mutex_lock(&rtp->bridge_lock); 02023 bridged = rtp->bridged; 02024 ast_mutex_unlock(&rtp->bridge_lock); 02025 02026 return bridged; 02027 }
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 1688 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 process_sdp().
01690 { 01691 int pt; 01692 01693 ast_mutex_lock(&rtp->bridge_lock); 01694 01695 *astFormats = *nonAstFormats = 0; 01696 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01697 if (rtp->current_RTP_PT[pt].isAstFormat) { 01698 *astFormats |= rtp->current_RTP_PT[pt].code; 01699 } else { 01700 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01701 } 01702 } 01703 01704 ast_mutex_unlock(&rtp->bridge_lock); 01705 01706 return; 01707 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2000 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), bridge_native_loop(), do_monitor(), gtalk_update_stun(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
02001 { 02002 if ((them->sin_family != AF_INET) || 02003 (them->sin_port != rtp->them.sin_port) || 02004 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02005 them->sin_family = AF_INET; 02006 them->sin_port = rtp->them.sin_port; 02007 them->sin_addr = rtp->them.sin_addr; 02008 return 1; 02009 } 02010 return 0; 02011 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2066 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().
02067 { 02068 /* 02069 *ssrc our ssrc 02070 *themssrc their ssrc 02071 *lp lost packets 02072 *rxjitter our calculated jitter(rx) 02073 *rxcount no. received packets 02074 *txjitter reported jitter of the other end 02075 *txcount transmitted packets 02076 *rlp remote lost packets 02077 *rtt round trip time 02078 */ 02079 02080 if (qual) { 02081 qual->local_ssrc = rtp->ssrc; 02082 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02083 qual->local_jitter = rtp->rxjitter; 02084 qual->local_count = rtp->rxcount; 02085 qual->remote_ssrc = rtp->themssrc; 02086 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02087 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02088 qual->remote_count = rtp->txcount; 02089 qual->rtt = rtp->rtcp->rtt; 02090 } 02091 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt); 02092 02093 return rtp->rtcp->quality; 02094 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 567 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by do_monitor().
00568 { 00569 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00570 return 0; 00571 return rtp->rtpholdtimeout; 00572 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 575 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by do_monitor().
00576 { 00577 return rtp->rtpkeepalive; 00578 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 559 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by do_monitor().
00560 { 00561 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00562 return 0; 00563 return rtp->rtptimeout; 00564 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2013 of file rtp.c.
References ast_rtp::us.
Referenced by add_sdp(), external_rtp_create(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), and oh323_set_rtp_peer().
int ast_rtp_getnat | ( | struct ast_rtp * | rtp | ) |
Definition at line 595 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00596 { 00597 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00598 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 3752 of file rtp.c.
References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp.
Referenced by main().
03753 { 03754 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03755 ast_rtp_reload(); 03756 }
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 1731 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().
01732 { 01733 int pt = 0; 01734 01735 ast_mutex_lock(&rtp->bridge_lock); 01736 01737 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01738 code == rtp->rtp_lookup_code_cache_code) { 01739 /* Use our cached mapping, to avoid the overhead of the loop below */ 01740 pt = rtp->rtp_lookup_code_cache_result; 01741 ast_mutex_unlock(&rtp->bridge_lock); 01742 return pt; 01743 } 01744 01745 /* Check the dynamic list first */ 01746 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01747 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01748 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01749 rtp->rtp_lookup_code_cache_code = code; 01750 rtp->rtp_lookup_code_cache_result = pt; 01751 ast_mutex_unlock(&rtp->bridge_lock); 01752 return pt; 01753 } 01754 } 01755 01756 /* Then the static list */ 01757 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01758 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01759 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01760 rtp->rtp_lookup_code_cache_code = code; 01761 rtp->rtp_lookup_code_cache_result = pt; 01762 ast_mutex_unlock(&rtp->bridge_lock); 01763 return pt; 01764 } 01765 } 01766 01767 ast_mutex_unlock(&rtp->bridge_lock); 01768 01769 return -1; 01770 }
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 1791 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len, and name.
Referenced by process_sdp().
01793 { 01794 int format; 01795 unsigned len; 01796 char *end = buf; 01797 char *start = buf; 01798 01799 if (!buf || !size) 01800 return NULL; 01801 01802 snprintf(end, size, "0x%x (", capability); 01803 01804 len = strlen(end); 01805 end += len; 01806 size -= len; 01807 start = end; 01808 01809 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01810 if (capability & format) { 01811 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01812 01813 snprintf(end, size, "%s|", name); 01814 len = strlen(end); 01815 end += len; 01816 size -= len; 01817 } 01818 } 01819 01820 if (start == end) 01821 snprintf(start, size, "nothing)"); 01822 else if (size > 1) 01823 *(end -1) = ')'; 01824 01825 return buf; 01826 }
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 1772 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().
01774 { 01775 unsigned int i; 01776 01777 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01778 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01779 if (isAstFormat && 01780 (code == AST_FORMAT_G726_AAL2) && 01781 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01782 return "G726-32"; 01783 else 01784 return mimeTypes[i].subtype; 01785 } 01786 } 01787 01788 return ""; 01789 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1709 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), MAX_RTP_PT, result, and static_RTP_PT.
Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().
01710 { 01711 struct rtpPayloadType result; 01712 01713 result.isAstFormat = result.code = 0; 01714 01715 if (pt < 0 || pt > MAX_RTP_PT) 01716 return result; /* bogus payload type */ 01717 01718 /* Start with negotiated codecs */ 01719 ast_mutex_lock(&rtp->bridge_lock); 01720 result = rtp->current_RTP_PT[pt]; 01721 ast_mutex_unlock(&rtp->bridge_lock); 01722 01723 /* If it doesn't exist, check our static RTP type list, just in case */ 01724 if (!result.code) 01725 result = static_RTP_PT[pt]; 01726 01727 return result; 01728 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1570 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, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01571 { 01572 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01573 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01574 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01575 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01576 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01577 int srccodec, destcodec; 01578 01579 /* Lock channels */ 01580 ast_channel_lock(dest); 01581 while(ast_channel_trylock(src)) { 01582 ast_channel_unlock(dest); 01583 usleep(1); 01584 ast_channel_lock(dest); 01585 } 01586 01587 /* Find channel driver interfaces */ 01588 if (!(destpr = get_proto(dest))) { 01589 if (option_debug) 01590 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01591 ast_channel_unlock(dest); 01592 ast_channel_unlock(src); 01593 return 0; 01594 } 01595 if (!(srcpr = get_proto(src))) { 01596 if (option_debug) 01597 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01598 ast_channel_unlock(dest); 01599 ast_channel_unlock(src); 01600 return 0; 01601 } 01602 01603 /* Get audio and video interface (if native bridge is possible) */ 01604 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01605 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01606 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01607 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01608 01609 /* Ensure we have at least one matching codec */ 01610 if (srcpr->get_codec) 01611 srccodec = srcpr->get_codec(src); 01612 else 01613 srccodec = 0; 01614 if (destpr->get_codec) 01615 destcodec = destpr->get_codec(dest); 01616 else 01617 destcodec = 0; 01618 01619 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01620 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) { 01621 /* Somebody doesn't want to play... */ 01622 ast_channel_unlock(dest); 01623 ast_channel_unlock(src); 01624 return 0; 01625 } 01626 ast_rtp_pt_copy(destp, srcp); 01627 if (vdestp && vsrcp) 01628 ast_rtp_pt_copy(vdestp, vsrcp); 01629 if (media) { 01630 /* Bridge early */ 01631 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01632 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01633 } 01634 ast_channel_unlock(dest); 01635 ast_channel_unlock(src); 01636 if (option_debug) 01637 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01638 return 1; 01639 }
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 1972 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
01973 { 01974 struct in_addr ia; 01975 01976 memset(&ia, 0, sizeof(ia)); 01977 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 01978 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1872 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().
01873 { 01874 ast_mutex_init(&rtp->bridge_lock); 01875 01876 rtp->them.sin_family = AF_INET; 01877 rtp->us.sin_family = AF_INET; 01878 rtp->ssrc = ast_random(); 01879 rtp->seqno = ast_random() & 0xffff; 01880 ast_set_flag(rtp, FLAG_HAS_DTMF); 01881 01882 return; 01883 }
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 1885 of file rtp.c.
References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, FLAG_CALLBACK_MODE, free, io, LOG_ERROR, rtp_socket(), rtpread(), and sched.
Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), sip_alloc(), and start_rtp().
01886 { 01887 struct ast_rtp *rtp; 01888 int x; 01889 int first; 01890 int startplace; 01891 01892 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01893 return NULL; 01894 01895 ast_rtp_new_init(rtp); 01896 01897 rtp->s = rtp_socket(); 01898 if (rtp->s < 0) { 01899 free(rtp); 01900 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01901 return NULL; 01902 } 01903 if (sched && rtcpenable) { 01904 rtp->sched = sched; 01905 rtp->rtcp = ast_rtcp_new(); 01906 } 01907 01908 /* Select a random port number in the range of possible RTP */ 01909 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01910 x = x & ~1; 01911 /* Save it for future references. */ 01912 startplace = x; 01913 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01914 for (;;) { 01915 /* Must be an even port number by RTP spec */ 01916 rtp->us.sin_port = htons(x); 01917 rtp->us.sin_addr = addr; 01918 /* If there's rtcp, initialize it as well. */ 01919 if (rtp->rtcp) { 01920 rtp->rtcp->us.sin_port = htons(x + 1); 01921 rtp->rtcp->us.sin_addr = addr; 01922 } 01923 /* Try to bind it/them. */ 01924 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01925 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01926 break; 01927 if (!first) { 01928 /* Primary bind succeeded! Gotta recreate it */ 01929 close(rtp->s); 01930 rtp->s = rtp_socket(); 01931 } 01932 if (errno != EADDRINUSE) { 01933 /* We got an error that wasn't expected, abort! */ 01934 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01935 close(rtp->s); 01936 if (rtp->rtcp) { 01937 close(rtp->rtcp->s); 01938 free(rtp->rtcp); 01939 } 01940 free(rtp); 01941 return NULL; 01942 } 01943 /* The port was used, increment it (by two). */ 01944 x += 2; 01945 /* Did we go over the limit ? */ 01946 if (x > rtpend) 01947 /* then, start from the begingig. */ 01948 x = (rtpstart + 1) & ~1; 01949 /* Check if we reached the place were we started. */ 01950 if (x == startplace) { 01951 /* If so, there's no ports available. */ 01952 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01953 close(rtp->s); 01954 if (rtp->rtcp) { 01955 close(rtp->rtcp->s); 01956 free(rtp->rtcp); 01957 } 01958 free(rtp); 01959 return NULL; 01960 } 01961 } 01962 rtp->sched = sched; 01963 rtp->io = io; 01964 if (callbackmode) { 01965 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01966 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01967 } 01968 ast_rtp_pt_default(rtp); 01969 return rtp; 01970 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2797 of file rtp.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, protos, and ast_rtp_protocol::type.
Referenced by load_module().
02798 { 02799 struct ast_rtp_protocol *cur; 02800 02801 AST_LIST_LOCK(&protos); 02802 AST_LIST_TRAVERSE(&protos, cur, list) { 02803 if (!strcmp(cur->type, proto->type)) { 02804 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02805 AST_LIST_UNLOCK(&protos); 02806 return -1; 02807 } 02808 } 02809 AST_LIST_INSERT_HEAD(&protos, proto, list); 02810 AST_LIST_UNLOCK(&protos); 02811 02812 return 0; 02813 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2789 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.
Referenced by load_module(), and unload_module().
02790 { 02791 AST_LIST_LOCK(&protos); 02792 AST_LIST_REMOVE(&protos, proto, list); 02793 AST_LIST_UNLOCK(&protos); 02794 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1406 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 process_sdp().
01407 { 01408 int i; 01409 01410 if (!rtp) 01411 return; 01412 01413 ast_mutex_lock(&rtp->bridge_lock); 01414 01415 for (i = 0; i < MAX_RTP_PT; ++i) { 01416 rtp->current_RTP_PT[i].isAstFormat = 0; 01417 rtp->current_RTP_PT[i].code = 0; 01418 } 01419 01420 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01421 rtp->rtp_lookup_code_cache_code = 0; 01422 rtp->rtp_lookup_code_cache_result = 0; 01423 01424 ast_mutex_unlock(&rtp->bridge_lock); 01425 }
Copy payload types between RTP structures.
Definition at line 1446 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().
01447 { 01448 unsigned int i; 01449 01450 ast_mutex_lock(&dest->bridge_lock); 01451 ast_mutex_lock(&src->bridge_lock); 01452 01453 for (i=0; i < MAX_RTP_PT; ++i) { 01454 dest->current_RTP_PT[i].isAstFormat = 01455 src->current_RTP_PT[i].isAstFormat; 01456 dest->current_RTP_PT[i].code = 01457 src->current_RTP_PT[i].code; 01458 } 01459 dest->rtp_lookup_code_cache_isAstFormat = 0; 01460 dest->rtp_lookup_code_cache_code = 0; 01461 dest->rtp_lookup_code_cache_result = 0; 01462 01463 ast_mutex_unlock(&src->bridge_lock); 01464 ast_mutex_unlock(&dest->bridge_lock); 01465 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1427 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.
Referenced by ast_rtp_new_with_bindaddr().
01428 { 01429 int i; 01430 01431 ast_mutex_lock(&rtp->bridge_lock); 01432 01433 /* Initialize to default payload types */ 01434 for (i = 0; i < MAX_RTP_PT; ++i) { 01435 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01436 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01437 } 01438 01439 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01440 rtp->rtp_lookup_code_cache_code = 0; 01441 rtp->rtp_lookup_code_cache_result = 0; 01442 01443 ast_mutex_unlock(&rtp->bridge_lock); 01444 }
Definition at line 2590 of file rtp.c.
References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), 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::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
02591 { 02592 unsigned char *rtpheader; 02593 int hdrlen = 12; 02594 int res; 02595 unsigned int ms; 02596 int pred; 02597 int mark = 0; 02598 02599 ms = calc_txstamp(rtp, &f->delivery); 02600 /* Default prediction */ 02601 if (f->subclass < AST_FORMAT_MAX_AUDIO) { 02602 pred = rtp->lastts + f->samples; 02603 02604 /* Re-calculate last TS */ 02605 rtp->lastts = rtp->lastts + ms * 8; 02606 if (ast_tvzero(f->delivery)) { 02607 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02608 and if so, go with our prediction */ 02609 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02610 rtp->lastts = pred; 02611 else { 02612 if (option_debug > 2) 02613 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02614 mark = 1; 02615 } 02616 } 02617 } else { 02618 mark = f->subclass & 0x1; 02619 pred = rtp->lastovidtimestamp + f->samples; 02620 /* Re-calculate last TS */ 02621 rtp->lastts = rtp->lastts + ms * 90; 02622 /* If it's close to our prediction, go for it */ 02623 if (ast_tvzero(f->delivery)) { 02624 if (abs(rtp->lastts - pred) < 7200) { 02625 rtp->lastts = pred; 02626 rtp->lastovidtimestamp += f->samples; 02627 } else { 02628 if (option_debug > 2) 02629 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); 02630 rtp->lastovidtimestamp = rtp->lastts; 02631 } 02632 } 02633 } 02634 /* If the timestamp for non-digit packets has moved beyond the timestamp 02635 for digits, update the digit timestamp. 02636 */ 02637 if (rtp->lastts > rtp->lastdigitts) 02638 rtp->lastdigitts = rtp->lastts; 02639 02640 if (f->has_timing_info) 02641 rtp->lastts = f->ts * 8; 02642 02643 /* Get a pointer to the header */ 02644 rtpheader = (unsigned char *)(f->data - hdrlen); 02645 02646 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02647 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02648 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02649 02650 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02651 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02652 if (res <0) { 02653 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02654 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)); 02655 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02656 /* Only give this error message once if we are not RTP debugging */ 02657 if (option_debug || rtpdebug) 02658 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)); 02659 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02660 } 02661 } else { 02662 rtp->txcount++; 02663 rtp->txoctetcount +=(res - hdrlen); 02664 02665 if (rtp->rtcp && rtp->rtcp->schedid < 1) 02666 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02667 } 02668 02669 if (rtp_debug_test_addr(&rtp->them)) 02670 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02671 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02672 } 02673 02674 rtp->seqno++; 02675 02676 return 0; 02677 }
Definition at line 1097 of file rtp.c.
References ast_backtrace(), ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, 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, CRASH, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, event, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_frame::has_timing_info, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len, ast_frame::len, LOG_DEBUG, LOG_ERROR, 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_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().
01098 { 01099 int res; 01100 struct sockaddr_in sin; 01101 socklen_t len; 01102 unsigned int seqno; 01103 int version; 01104 int payloadtype; 01105 int hdrlen = 12; 01106 int padding; 01107 int mark; 01108 int ext; 01109 int cc; 01110 unsigned int ssrc; 01111 unsigned int timestamp; 01112 unsigned int *rtpheader; 01113 struct rtpPayloadType rtpPT; 01114 struct ast_rtp *bridged = NULL; 01115 01116 if( !rtp ) { 01117 ast_log(LOG_ERROR, "ast_rtp_read(): called with rtp == NULL\n"); 01118 ast_backtrace(); 01119 return &ast_null_frame; 01120 } 01121 01122 /* If time is up, kill it */ 01123 if (rtp->sending_digit) 01124 ast_rtp_senddigit_continuation(rtp); 01125 01126 len = sizeof(sin); 01127 01128 /* Cache where the header will go */ 01129 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01130 0, (struct sockaddr *)&sin, &len); 01131 01132 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01133 if (res < 0) { 01134 if (errno == EBADF) 01135 CRASH; 01136 if (errno != EAGAIN) { 01137 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01138 return NULL; 01139 } 01140 return &ast_null_frame; 01141 } 01142 01143 if (res < hdrlen) { 01144 ast_log(LOG_WARNING, "RTP Read too short\n"); 01145 return &ast_null_frame; 01146 } 01147 01148 /* Get fields */ 01149 seqno = ntohl(rtpheader[0]); 01150 01151 /* Check RTP version */ 01152 version = (seqno & 0xC0000000) >> 30; 01153 if (!version) { 01154 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01155 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01156 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01157 } 01158 return &ast_null_frame; 01159 } 01160 01161 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01162 /* If we don't have the other side's address, then ignore this */ 01163 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01164 return &ast_null_frame; 01165 #endif 01166 01167 /* Send to whoever send to us if NAT is turned on */ 01168 if (rtp->nat) { 01169 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01170 (rtp->them.sin_port != sin.sin_port)) { 01171 rtp->them = sin; 01172 if (rtp->rtcp) { 01173 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01174 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01175 } 01176 rtp->rxseqno = 0; 01177 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01178 if (option_debug || rtpdebug) 01179 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)); 01180 } 01181 } 01182 01183 /* If we are bridged to another RTP stream, send direct */ 01184 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01185 return &ast_null_frame; 01186 01187 if (version != 2) 01188 return &ast_null_frame; 01189 01190 payloadtype = (seqno & 0x7f0000) >> 16; 01191 padding = seqno & (1 << 29); 01192 mark = seqno & (1 << 23); 01193 ext = seqno & (1 << 28); 01194 cc = (seqno & 0xF000000) >> 24; 01195 seqno &= 0xffff; 01196 timestamp = ntohl(rtpheader[1]); 01197 ssrc = ntohl(rtpheader[2]); 01198 01199 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01200 if (option_debug || rtpdebug) 01201 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01202 mark = 1; 01203 } 01204 01205 rtp->rxssrc = ssrc; 01206 01207 if (padding) { 01208 /* Remove padding bytes */ 01209 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01210 } 01211 01212 if (cc) { 01213 /* CSRC fields present */ 01214 hdrlen += cc*4; 01215 } 01216 01217 if (ext) { 01218 /* RTP Extension present */ 01219 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01220 hdrlen += 4; 01221 if (option_debug) { 01222 int profile; 01223 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01224 if (profile == 0x505a) 01225 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01226 else 01227 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile); 01228 } 01229 } 01230 01231 if (res < hdrlen) { 01232 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01233 return &ast_null_frame; 01234 } 01235 01236 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01237 01238 if (rtp->rxcount==1) { 01239 /* This is the first RTP packet successfully received from source */ 01240 rtp->seedrxseqno = seqno; 01241 } 01242 01243 /* Do not schedule RR if RTCP isn't run */ 01244 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01245 /* Schedule transmission of Receiver Report */ 01246 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01247 } 01248 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01249 rtp->cycles += RTP_SEQ_MOD; 01250 01251 rtp->lastrxseqno = seqno; 01252 01253 if (rtp->themssrc==0) 01254 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01255 01256 if (rtp_debug_test_addr(&sin)) 01257 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01258 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01259 01260 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01261 if (!rtpPT.isAstFormat) { 01262 struct ast_frame *f = NULL; 01263 01264 /* This is special in-band data that's not one of our codecs */ 01265 if (rtpPT.code == AST_RTP_DTMF) { 01266 /* It's special -- rfc2833 process it */ 01267 if (rtp_debug_test_addr(&sin)) { 01268 unsigned char *data; 01269 unsigned int event; 01270 unsigned int event_end; 01271 unsigned int duration; 01272 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01273 event = ntohl(*((unsigned int *)(data))); 01274 event >>= 24; 01275 event_end = ntohl(*((unsigned int *)(data))); 01276 event_end <<= 8; 01277 event_end >>= 24; 01278 duration = ntohl(*((unsigned int *)(data))); 01279 duration &= 0xFFFF; 01280 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); 01281 } 01282 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01283 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01284 /* It's really special -- process it the Cisco way */ 01285 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01286 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01287 rtp->lastevent = seqno; 01288 } 01289 } else if (rtpPT.code == AST_RTP_CN) { 01290 /* Comfort Noise */ 01291 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01292 } else { 01293 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01294 } 01295 return f ? f : &ast_null_frame; 01296 } 01297 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01298 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01299 01300 if (!rtp->lastrxts) 01301 rtp->lastrxts = timestamp; 01302 01303 rtp->rxseqno = seqno; 01304 01305 /* Record received timestamp as last received now */ 01306 rtp->lastrxts = timestamp; 01307 01308 rtp->f.mallocd = 0; 01309 rtp->f.datalen = res - hdrlen; 01310 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01311 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01312 rtp->f.seqno = seqno; 01313 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01314 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01315 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01316 ast_frame_byteswap_be(&rtp->f); 01317 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01318 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01319 rtp->f.has_timing_info = 1; 01320 rtp->f.ts = timestamp / 8; 01321 rtp->f.len = rtp->f.samples / 8; 01322 } else { 01323 /* Video -- samples is # of samples vs. 90000 */ 01324 if (!rtp->lastividtimestamp) 01325 rtp->lastividtimestamp = timestamp; 01326 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01327 rtp->lastividtimestamp = timestamp; 01328 rtp->f.delivery.tv_sec = 0; 01329 rtp->f.delivery.tv_usec = 0; 01330 if (mark) 01331 rtp->f.subclass |= 0x1; 01332 01333 } 01334 rtp->f.src = "RTP"; 01335 return &rtp->f; 01336 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3687 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().
03688 { 03689 struct ast_config *cfg; 03690 const char *s; 03691 03692 rtpstart = 5000; 03693 rtpend = 31000; 03694 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03695 cfg = ast_config_load("rtp.conf"); 03696 if (cfg) { 03697 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03698 rtpstart = atoi(s); 03699 if (rtpstart < 1024) 03700 rtpstart = 1024; 03701 if (rtpstart > 65535) 03702 rtpstart = 65535; 03703 } 03704 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03705 rtpend = atoi(s); 03706 if (rtpend < 1024) 03707 rtpend = 1024; 03708 if (rtpend > 65535) 03709 rtpend = 65535; 03710 } 03711 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03712 rtcpinterval = atoi(s); 03713 if (rtcpinterval == 0) 03714 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03715 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03716 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03717 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03718 rtcpinterval = RTCP_MAX_INTERVALMS; 03719 } 03720 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03721 #ifdef SO_NO_CHECK 03722 if (ast_false(s)) 03723 nochecksums = 1; 03724 else 03725 nochecksums = 0; 03726 #else 03727 if (ast_false(s)) 03728 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03729 #endif 03730 } 03731 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03732 dtmftimeout = atoi(s); 03733 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03734 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03735 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03736 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03737 }; 03738 } 03739 ast_config_destroy(cfg); 03740 } 03741 if (rtpstart >= rtpend) { 03742 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03743 rtpstart = 5000; 03744 rtpend = 31000; 03745 } 03746 if (option_verbose > 1) 03747 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03748 return 0; 03749 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2046 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.
02047 { 02048 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02049 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02050 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02051 rtp->lastts = 0; 02052 rtp->lastdigitts = 0; 02053 rtp->lastrxts = 0; 02054 rtp->lastividtimestamp = 0; 02055 rtp->lastovidtimestamp = 0; 02056 rtp->lasteventseqn = 0; 02057 rtp->lastevent = 0; 02058 rtp->lasttxformat = 0; 02059 rtp->lastrxformat = 0; 02060 rtp->dtmfcount = 0; 02061 rtp->dtmfsamples = 0; 02062 rtp->seqno = 0; 02063 rtp->rxseqno = 0; 02064 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2556 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::data, ast_rtp::dtmfmute, 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().
02557 { 02558 unsigned int *rtpheader; 02559 int hdrlen = 12; 02560 int res; 02561 int payload; 02562 char data[256]; 02563 level = 127 - (level & 0x7f); 02564 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02565 02566 /* If we have no peer, return immediately */ 02567 if (!rtp->them.sin_addr.s_addr) 02568 return 0; 02569 02570 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02571 02572 /* Get a pointer to the header */ 02573 rtpheader = (unsigned int *)data; 02574 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02575 rtpheader[1] = htonl(rtp->lastts); 02576 rtpheader[2] = htonl(rtp->ssrc); 02577 data[12] = level; 02578 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02579 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02580 if (res <0) 02581 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)); 02582 if (rtp_debug_test_addr(&rtp->them)) 02583 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02584 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02585 02586 } 02587 return 0; 02588 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2156 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, 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 oh323_digit_begin(), and sip_senddigit_begin().
02157 { 02158 unsigned int *rtpheader; 02159 int hdrlen = 12, res = 0, i = 0, payload = 0; 02160 char data[256]; 02161 02162 if ((digit <= '9') && (digit >= '0')) 02163 digit -= '0'; 02164 else if (digit == '*') 02165 digit = 10; 02166 else if (digit == '#') 02167 digit = 11; 02168 else if ((digit >= 'A') && (digit <= 'D')) 02169 digit = digit - 'A' + 12; 02170 else if ((digit >= 'a') && (digit <= 'd')) 02171 digit = digit - 'a' + 12; 02172 else { 02173 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02174 return 0; 02175 } 02176 02177 /* If we have no peer, return immediately */ 02178 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02179 return 0; 02180 02181 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02182 02183 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02184 rtp->send_duration = 160; 02185 02186 /* Get a pointer to the header */ 02187 rtpheader = (unsigned int *)data; 02188 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02189 rtpheader[1] = htonl(rtp->lastdigitts); 02190 rtpheader[2] = htonl(rtp->ssrc); 02191 02192 for (i = 0; i < 2; i++) { 02193 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02194 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02195 if (res < 0) 02196 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02197 ast_inet_ntoa(rtp->them.sin_addr), 02198 ntohs(rtp->them.sin_port), strerror(errno)); 02199 if (rtp_debug_test_addr(&rtp->them)) 02200 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02201 ast_inet_ntoa(rtp->them.sin_addr), 02202 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02203 /* Increment sequence number */ 02204 rtp->seqno++; 02205 /* Increment duration */ 02206 rtp->send_duration += 160; 02207 /* Clear marker bit and set seqno */ 02208 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02209 } 02210 02211 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02212 rtp->sending_digit = 1; 02213 rtp->send_digit = digit; 02214 rtp->send_payload = payload; 02215 02216 return 0; 02217 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2220 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_verbose(), 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().
02221 { 02222 unsigned int *rtpheader; 02223 int hdrlen = 12, res = 0; 02224 char data[256]; 02225 02226 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02227 return 0; 02228 02229 /* Setup packet to send */ 02230 rtpheader = (unsigned int *)data; 02231 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02232 rtpheader[1] = htonl(rtp->lastdigitts); 02233 rtpheader[2] = htonl(rtp->ssrc); 02234 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02235 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02236 02237 /* Transmit */ 02238 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02239 if (res < 0) 02240 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02241 ast_inet_ntoa(rtp->them.sin_addr), 02242 ntohs(rtp->them.sin_port), strerror(errno)); 02243 if (rtp_debug_test_addr(&rtp->them)) 02244 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02245 ast_inet_ntoa(rtp->them.sin_addr), 02246 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02247 02248 /* Increment sequence number */ 02249 rtp->seqno++; 02250 /* Increment duration */ 02251 rtp->send_duration += 160; 02252 02253 return 0; 02254 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2257 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, 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 oh323_digit_end(), and sip_senddigit_end().
02258 { 02259 unsigned int *rtpheader; 02260 int hdrlen = 12, res = 0, i = 0; 02261 char data[256]; 02262 02263 /* If no address, then bail out */ 02264 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02265 return 0; 02266 02267 if ((digit <= '9') && (digit >= '0')) 02268 digit -= '0'; 02269 else if (digit == '*') 02270 digit = 10; 02271 else if (digit == '#') 02272 digit = 11; 02273 else if ((digit >= 'A') && (digit <= 'D')) 02274 digit = digit - 'A' + 12; 02275 else if ((digit >= 'a') && (digit <= 'd')) 02276 digit = digit - 'a' + 12; 02277 else { 02278 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02279 return 0; 02280 } 02281 02282 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02283 02284 rtpheader = (unsigned int *)data; 02285 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02286 rtpheader[1] = htonl(rtp->lastdigitts); 02287 rtpheader[2] = htonl(rtp->ssrc); 02288 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02289 /* Set end bit */ 02290 rtpheader[3] |= htonl((1 << 23)); 02291 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02292 /* Send 3 termination packets */ 02293 for (i = 0; i < 3; i++) { 02294 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02295 if (res < 0) 02296 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02297 ast_inet_ntoa(rtp->them.sin_addr), 02298 ntohs(rtp->them.sin_port), strerror(errno)); 02299 if (rtp_debug_test_addr(&rtp->them)) 02300 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02301 ast_inet_ntoa(rtp->them.sin_addr), 02302 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02303 } 02304 rtp->sending_digit = 0; 02305 rtp->send_digit = 0; 02306 /* Increment lastdigitts */ 02307 rtp->lastdigitts += 960; 02308 rtp->seqno++; 02309 02310 return res; 02311 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 585 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00586 { 00587 rtp->callback = callback; 00588 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 580 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00581 { 00582 rtp->data = data; 00583 }
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
Definition at line 1645 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_newcall(), and process_sdp().
01646 { 01647 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01648 return; /* bogus payload type */ 01649 01650 ast_mutex_lock(&rtp->bridge_lock); 01651 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01652 ast_mutex_unlock(&rtp->bridge_lock); 01653 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 1989 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().
01990 { 01991 rtp->them.sin_port = them->sin_port; 01992 rtp->them.sin_addr = them->sin_addr; 01993 if (rtp->rtcp) { 01994 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 01995 rtp->rtcp->them.sin_addr = them->sin_addr; 01996 } 01997 rtp->rxseqno = 0; 01998 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 547 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00548 { 00549 rtp->rtpholdtimeout = timeout; 00550 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 553 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00554 { 00555 rtp->rtpkeepalive = period; 00556 }
void ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
int | pt, | |||
char * | mimeType, | |||
char * | mimeSubtype, | |||
enum ast_rtp_options | options | |||
) |
Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
Definition at line 1658 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_newcall(), process_sdp(), and set_dtmf_payload().
01661 { 01662 unsigned int i; 01663 01664 if (pt < 0 || pt > MAX_RTP_PT) 01665 return; /* bogus payload type */ 01666 01667 ast_mutex_lock(&rtp->bridge_lock); 01668 01669 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01670 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01671 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01672 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01673 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01674 mimeTypes[i].payloadType.isAstFormat && 01675 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01676 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01677 break; 01678 } 01679 } 01680 01681 ast_mutex_unlock(&rtp->bridge_lock); 01682 01683 return; 01684 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 541 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00542 { 00543 rtp->rtptimeout = timeout; 00544 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 534 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00535 { 00536 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00537 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00538 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 600 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_DTMF.
Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), sip_alloc(), and sip_dtmfmode().
00601 { 00602 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00603 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 605 of file rtp.c.
References ast_set2_flag, and FLAG_DTMF_COMPENSATE.
Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), and sip_alloc().
00606 { 00607 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00608 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 590 of file rtp.c.
References ast_rtp::nat.
Referenced by __oh323_rtp_create(), do_setnat(), oh323_rtp_read(), and start_rtp().
void ast_rtp_setstun | ( | struct ast_rtp * | rtp, | |
int | stun_enable | |||
) |
Enable STUN capability.
Definition at line 610 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00611 { 00612 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00613 }
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 1980 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
01981 { 01982 int res; 01983 01984 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 01985 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 01986 return res; 01987 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2029 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().
02030 { 02031 if (rtp->rtcp && rtp->rtcp->schedid > 0) { 02032 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02033 rtp->rtcp->schedid = -1; 02034 } 02035 02036 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02037 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02038 if (rtp->rtcp) { 02039 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02040 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02041 } 02042 02043 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02044 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Definition at line 402 of file rtp.c.
References append_attr_string(), stun_attr::attr, ast_rtp::s, STUN_BINDREQ, stun_req_id(), stun_send(), and STUN_USERNAME.
Referenced by gtalk_update_stun().
00403 { 00404 struct stun_header *req; 00405 unsigned char reqdata[1024]; 00406 int reqlen, reqleft; 00407 struct stun_attr *attr; 00408 00409 req = (struct stun_header *)reqdata; 00410 stun_req_id(req); 00411 reqlen = 0; 00412 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00413 req->msgtype = 0; 00414 req->msglen = 0; 00415 attr = (struct stun_attr *)req->ies; 00416 if (username) 00417 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00418 req->msglen = htons(reqlen); 00419 req->msgtype = htons(STUN_BINDREQ); 00420 stun_send(rtp->s, suggestion, req); 00421 }
Definition at line 2708 of file rtp.c.
References ast_codec_pref_getsize(), 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_frame::datalen, f, fmt, ast_frame::frametype, 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().
02709 { 02710 struct ast_frame *f; 02711 int codec; 02712 int hdrlen = 12; 02713 int subclass; 02714 02715 02716 /* If we have no peer, return immediately */ 02717 if (!rtp->them.sin_addr.s_addr) 02718 return 0; 02719 02720 /* If there is no data length, return immediately */ 02721 if (!_f->datalen) 02722 return 0; 02723 02724 /* Make sure we have enough space for RTP header */ 02725 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02726 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02727 return -1; 02728 } 02729 02730 subclass = _f->subclass; 02731 if (_f->frametype == AST_FRAME_VIDEO) 02732 subclass &= ~0x1; 02733 02734 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02735 if (codec < 0) { 02736 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02737 return -1; 02738 } 02739 02740 if (rtp->lasttxformat != subclass) { 02741 /* New format, reset the smoother */ 02742 if (option_debug) 02743 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02744 rtp->lasttxformat = subclass; 02745 if (rtp->smoother) 02746 ast_smoother_free(rtp->smoother); 02747 rtp->smoother = NULL; 02748 } 02749 02750 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX) { 02751 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02752 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02753 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02754 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)); 02755 return -1; 02756 } 02757 if (fmt.flags) 02758 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02759 if (option_debug) 02760 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)); 02761 } 02762 } 02763 if (rtp->smoother) { 02764 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02765 ast_smoother_feed_be(rtp->smoother, _f); 02766 } else { 02767 ast_smoother_feed(rtp->smoother, _f); 02768 } 02769 02770 while((f = ast_smoother_read(rtp->smoother)) && (f->data)) 02771 ast_rtp_raw_write(rtp, f, codec); 02772 } else { 02773 /* Don't buffer outgoing frames; send them one-per-packet: */ 02774 if (_f->offset < hdrlen) { 02775 f = ast_frdup(_f); 02776 } else { 02777 f = _f; 02778 } 02779 if (f->data) 02780 ast_rtp_raw_write(rtp, f, codec); 02781 if (f != _f) 02782 ast_frfree(f); 02783 } 02784 02785 return 0; 02786 }
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 2816 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_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, 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_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, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
02817 { 02818 struct ast_frame *fr = NULL; 02819 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02820 int oldcodec0 = codec0, oldcodec1 = codec1; 02821 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02822 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02823 02824 /* Set it up so audio goes directly between the two endpoints */ 02825 02826 /* Test the first channel */ 02827 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02828 ast_rtp_get_peer(p1, &ac1); 02829 if (vp1) 02830 ast_rtp_get_peer(vp1, &vac1); 02831 } else 02832 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 02833 02834 /* Test the second channel */ 02835 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 02836 ast_rtp_get_peer(p0, &ac0); 02837 if (vp0) 02838 ast_rtp_get_peer(vp0, &vac0); 02839 } else 02840 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 02841 02842 /* Now we can unlock and move into our loop */ 02843 ast_channel_unlock(c0); 02844 ast_channel_unlock(c1); 02845 02846 /* Throw our channels into the structure and enter the loop */ 02847 cs[0] = c0; 02848 cs[1] = c1; 02849 cs[2] = NULL; 02850 for (;;) { 02851 /* Check if anything changed */ 02852 if ((c0->tech_pvt != pvt0) || 02853 (c1->tech_pvt != pvt1) || 02854 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 02855 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 02856 if (c0->tech_pvt == pvt0) 02857 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02858 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02859 if (c1->tech_pvt == pvt1) 02860 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02861 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02862 return AST_BRIDGE_RETRY; 02863 } 02864 02865 /* Check if they have changed their address */ 02866 ast_rtp_get_peer(p1, &t1); 02867 if (vp1) 02868 ast_rtp_get_peer(vp1, &vt1); 02869 if (pr1->get_codec) 02870 codec1 = pr1->get_codec(c1); 02871 ast_rtp_get_peer(p0, &t0); 02872 if (vp0) 02873 ast_rtp_get_peer(vp0, &vt0); 02874 if (pr0->get_codec) 02875 codec0 = pr0->get_codec(c0); 02876 if ((inaddrcmp(&t1, &ac1)) || 02877 (vp1 && inaddrcmp(&vt1, &vac1)) || 02878 (codec1 != oldcodec1)) { 02879 if (option_debug > 1) { 02880 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02881 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 02882 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 02883 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 02884 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02885 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 02886 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02887 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 02888 } 02889 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))) 02890 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 02891 memcpy(&ac1, &t1, sizeof(ac1)); 02892 memcpy(&vac1, &vt1, sizeof(vac1)); 02893 oldcodec1 = codec1; 02894 } 02895 if ((inaddrcmp(&t0, &ac0)) || 02896 (vp0 && inaddrcmp(&vt0, &vac0))) { 02897 if (option_debug > 1) { 02898 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02899 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 02900 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02901 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 02902 } 02903 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))) 02904 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 02905 memcpy(&ac0, &t0, sizeof(ac0)); 02906 memcpy(&vac0, &vt0, sizeof(vac0)); 02907 oldcodec0 = codec0; 02908 } 02909 02910 /* Wait for frame to come in on the channels */ 02911 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 02912 if (!timeoutms) { 02913 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02914 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02915 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02916 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02917 return AST_BRIDGE_RETRY; 02918 } 02919 if (option_debug) 02920 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 02921 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 02922 break; 02923 continue; 02924 } 02925 fr = ast_read(who); 02926 other = (who == c0) ? c1 : c0; 02927 if (!fr || ((fr->frametype == AST_FRAME_DTMF) && 02928 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 02929 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 02930 /* Break out of bridge */ 02931 *fo = fr; 02932 *rc = who; 02933 if (option_debug) 02934 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 02935 if (c0->tech_pvt == pvt0) 02936 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02937 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02938 if (c1->tech_pvt == pvt1) 02939 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02940 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02941 return AST_BRIDGE_COMPLETE; 02942 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02943 if ((fr->subclass == AST_CONTROL_HOLD) || 02944 (fr->subclass == AST_CONTROL_UNHOLD) || 02945 (fr->subclass == AST_CONTROL_VIDUPDATE)) { 02946 if (fr->subclass == AST_CONTROL_HOLD) { 02947 /* If we someone went on hold we want the other side to reinvite back to us */ 02948 if (who == c0) 02949 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 02950 else 02951 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 02952 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 02953 /* If they went off hold they should go back to being direct */ 02954 if (who == c0) 02955 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 02956 else 02957 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 02958 } 02959 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 02960 ast_frfree(fr); 02961 } else { 02962 *fo = fr; 02963 *rc = who; 02964 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 02965 return AST_BRIDGE_COMPLETE; 02966 } 02967 } else { 02968 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 02969 (fr->frametype == AST_FRAME_DTMF) || 02970 (fr->frametype == AST_FRAME_VOICE) || 02971 (fr->frametype == AST_FRAME_VIDEO) || 02972 (fr->frametype == AST_FRAME_IMAGE) || 02973 (fr->frametype == AST_FRAME_HTML) || 02974 (fr->frametype == AST_FRAME_MODEM) || 02975 (fr->frametype == AST_FRAME_TEXT)) { 02976 ast_write(other, fr); 02977 } 02978 ast_frfree(fr); 02979 } 02980 /* Swap priority */ 02981 cs[2] = cs[0]; 02982 cs[0] = cs[1]; 02983 cs[1] = cs[2]; 02984 } 02985 02986 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02987 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02988 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02989 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02990 02991 return AST_BRIDGE_FAILED; 02992 }
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 3090 of file rtp.c.
References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate_data(), ast_log(), ast_read(), ast_waitfor_n(), ast_write(), ast_frame::data, ast_frame::datalen, FLAG_P2P_SENT_MARK, ast_frame::frametype, LOG_NOTICE, ast_channel::masq, ast_channel::masqr, option_debug, p2p_callback_disable(), p2p_callback_enable(), p2p_set_bridge(), ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
03091 { 03092 struct ast_frame *fr = NULL; 03093 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03094 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03095 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03096 int p0_callback = 0, p1_callback = 0; 03097 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03098 03099 /* Okay, setup each RTP structure to do P2P forwarding */ 03100 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03101 p2p_set_bridge(p0, p1); 03102 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03103 p2p_set_bridge(p1, p0); 03104 03105 /* Activate callback modes if possible */ 03106 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03107 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03108 03109 /* Now let go of the channel locks and be on our way */ 03110 ast_channel_unlock(c0); 03111 ast_channel_unlock(c1); 03112 03113 /* Go into a loop forwarding frames until we don't need to anymore */ 03114 cs[0] = c0; 03115 cs[1] = c1; 03116 cs[2] = NULL; 03117 for (;;) { 03118 /* Check if anything changed */ 03119 if ((c0->tech_pvt != pvt0) || 03120 (c1->tech_pvt != pvt1) || 03121 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 03122 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03123 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03124 ast_frfree(fr); 03125 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03126 ast_frfree(fr); 03127 res = AST_BRIDGE_RETRY; 03128 break; 03129 } 03130 /* Wait on a channel to feed us a frame */ 03131 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03132 if (!timeoutms) { 03133 res = AST_BRIDGE_RETRY; 03134 break; 03135 } 03136 if (option_debug) 03137 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03138 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03139 break; 03140 continue; 03141 } 03142 /* Read in frame from channel */ 03143 fr = ast_read(who); 03144 other = (who == c0) ? c1 : c0; 03145 /* Dependong on the frame we may need to break out of our bridge */ 03146 if (!fr || ((fr->frametype == AST_FRAME_DTMF) && 03147 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03148 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03149 /* Record received frame and who */ 03150 *fo = fr; 03151 *rc = who; 03152 if (option_debug) 03153 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03154 res = AST_BRIDGE_COMPLETE; 03155 break; 03156 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03157 if ((fr->subclass == AST_CONTROL_HOLD) || 03158 (fr->subclass == AST_CONTROL_UNHOLD) || 03159 (fr->subclass == AST_CONTROL_VIDUPDATE)) { 03160 /* If we are going on hold, then break callback mode and P2P bridging */ 03161 if (fr->subclass == AST_CONTROL_HOLD) { 03162 if (p0_callback) 03163 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03164 if (p1_callback) 03165 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03166 p2p_set_bridge(p0, NULL); 03167 p2p_set_bridge(p1, NULL); 03168 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03169 /* If we are off hold, then go back to callback mode and P2P bridging */ 03170 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03171 p2p_set_bridge(p0, p1); 03172 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03173 p2p_set_bridge(p1, p0); 03174 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03175 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03176 } 03177 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03178 ast_frfree(fr); 03179 } else { 03180 *fo = fr; 03181 *rc = who; 03182 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03183 res = AST_BRIDGE_COMPLETE; 03184 break; 03185 } 03186 } else { 03187 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03188 (fr->frametype == AST_FRAME_DTMF) || 03189 (fr->frametype == AST_FRAME_VOICE) || 03190 (fr->frametype == AST_FRAME_VIDEO) || 03191 (fr->frametype == AST_FRAME_IMAGE) || 03192 (fr->frametype == AST_FRAME_HTML) || 03193 (fr->frametype == AST_FRAME_MODEM) || 03194 (fr->frametype == AST_FRAME_TEXT)) { 03195 ast_write(other, fr); 03196 } 03197 03198 ast_frfree(fr); 03199 } 03200 /* Swap priority */ 03201 cs[2] = cs[0]; 03202 cs[0] = cs[1]; 03203 cs[1] = cs[2]; 03204 } 03205 03206 /* If we are totally avoiding the core, then restore our link to it */ 03207 if (p0_callback) 03208 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03209 if (p1_callback) 03210 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03211 03212 /* Break out of the direct bridge */ 03213 p2p_set_bridge(p0, NULL); 03214 p2p_set_bridge(p1, NULL); 03215 03216 return res; 03217 }
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 1048 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, 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().
01049 { 01050 int res = 0, payload = 0, bridged_payload = 0, mark; 01051 struct rtpPayloadType rtpPT; 01052 int reconstruct = ntohl(rtpheader[0]); 01053 01054 /* Get fields from packet */ 01055 payload = (reconstruct & 0x7f0000) >> 16; 01056 mark = (((reconstruct & 0x800000) >> 23) != 0); 01057 01058 /* Check what the payload value should be */ 01059 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01060 01061 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01062 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01063 return -1; 01064 01065 /* Otherwise adjust bridged payload to match */ 01066 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01067 01068 /* If the mark bit has not been sent yet... do it now */ 01069 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01070 mark = 1; 01071 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01072 } 01073 01074 /* Reconstruct part of the packet */ 01075 reconstruct &= 0xFF80FFFF; 01076 reconstruct |= (bridged_payload << 16); 01077 reconstruct |= (mark << 23); 01078 rtpheader[0] = htonl(reconstruct); 01079 01080 /* Send the packet back out */ 01081 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01082 if (res < 0) { 01083 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01084 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)); 01085 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01086 if (option_debug || rtpdebug) 01087 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)); 01088 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01089 } 01090 return 0; 01091 } else if (rtp_debug_test_addr(&bridged->them)) 01092 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); 01093 01094 return 0; 01095 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 999 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().
01000 { 01001 struct timeval now; 01002 double transit; 01003 double current_time; 01004 double d; 01005 double dtv; 01006 double prog; 01007 01008 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01009 gettimeofday(&rtp->rxcore, NULL); 01010 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01011 /* map timestamp to a real time */ 01012 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01013 rtp->rxcore.tv_sec -= timestamp / 8000; 01014 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01015 /* Round to 0.1ms for nice, pretty timestamps */ 01016 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01017 if (rtp->rxcore.tv_usec < 0) { 01018 /* Adjust appropriately if necessary */ 01019 rtp->rxcore.tv_usec += 1000000; 01020 rtp->rxcore.tv_sec -= 1; 01021 } 01022 } 01023 01024 gettimeofday(&now,NULL); 01025 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01026 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01027 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01028 if (tv->tv_usec >= 1000000) { 01029 tv->tv_usec -= 1000000; 01030 tv->tv_sec += 1; 01031 } 01032 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01033 dtv = (double)rtp->drxcore + (double)(prog); 01034 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01035 transit = current_time - dtv; 01036 d = transit - rtp->rxtransit; 01037 rtp->rxtransit = transit; 01038 if (d<0) 01039 d=-d; 01040 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01041 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01042 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01043 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01044 rtp->rtcp->minrxjitter = rtp->rxjitter; 01045 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2136 of file rtp.c.
References t, and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02137 { 02138 struct timeval t; 02139 long ms; 02140 if (ast_tvzero(rtp->txcore)) { 02141 rtp->txcore = ast_tvnow(); 02142 /* Round to 20ms for nice, pretty timestamps */ 02143 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02144 } 02145 /* Use previous txcore if available */ 02146 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02147 ms = ast_tvdiff_ms(t, rtp->txcore); 02148 if (ms < 0) 02149 ms = 0; 02150 /* Use what we just got for next time */ 02151 rtp->txcore = t; 02152 return (unsigned int) ms; 02153 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 1468 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, protos, 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().
01469 { 01470 struct ast_rtp_protocol *cur = NULL; 01471 01472 AST_LIST_LOCK(&protos); 01473 AST_LIST_TRAVERSE(&protos, cur, list) { 01474 if (cur->type == chan->tech->type) 01475 break; 01476 } 01477 AST_LIST_UNLOCK(&protos); 01478 01479 return cur; 01480 }
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 3061 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.
Referenced by bridge_p2p_loop().
03062 { 03063 ast_channel_lock(chan); 03064 03065 /* Remove the callback from the IO context */ 03066 ast_io_remove(rtp->io, iod[0]); 03067 03068 /* Restore file descriptors */ 03069 chan->fds[0] = fds[0]; 03070 ast_channel_unlock(chan); 03071 03072 /* Restore callback mode if previously used */ 03073 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03074 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03075 03076 return 0; 03077 }
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 3080 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03081 { 03082 ast_mutex_lock(&rtp0->bridge_lock); 03083 rtp0->bridged = rtp1; 03084 ast_mutex_unlock(&rtp0->bridge_lock); 03085 03086 return; 03087 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 669 of file rtp.c.
References AST_FRAME_DTMF_END, ast_log(), ast_rtp::dtmfcount, event, f, LOG_DEBUG, option_debug, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00670 { 00671 unsigned int event; 00672 char resp = 0; 00673 struct ast_frame *f = NULL; 00674 event = ntohl(*((unsigned int *)(data))); 00675 event &= 0x001F; 00676 if (option_debug > 2 || rtpdebug) 00677 ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len); 00678 if (event < 10) { 00679 resp = '0' + event; 00680 } else if (event < 11) { 00681 resp = '*'; 00682 } else if (event < 12) { 00683 resp = '#'; 00684 } else if (event < 16) { 00685 resp = 'A' + (event - 12); 00686 } else if (event < 17) { 00687 resp = 'X'; 00688 } 00689 if (rtp->resp && (rtp->resp != resp)) { 00690 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00691 } 00692 rtp->resp = resp; 00693 rtp->dtmfcount = dtmftimeout; 00694 return f; 00695 }
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 708 of file rtp.c.
References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_test_flag, ast_rtp::dtmfcount, ast_rtp::dtmfsamples, event, 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().
00709 { 00710 unsigned int event; 00711 unsigned int event_end; 00712 unsigned int samples; 00713 char resp = 0; 00714 struct ast_frame *f = NULL; 00715 00716 /* Figure out event, event end, and samples */ 00717 event = ntohl(*((unsigned int *)(data))); 00718 event >>= 24; 00719 event_end = ntohl(*((unsigned int *)(data))); 00720 event_end <<= 8; 00721 event_end >>= 24; 00722 samples = ntohl(*((unsigned int *)(data))); 00723 samples &= 0xFFFF; 00724 00725 /* Print out debug if turned on */ 00726 if (rtpdebug || option_debug > 2) 00727 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00728 00729 /* Figure out what digit was pressed */ 00730 if (event < 10) { 00731 resp = '0' + event; 00732 } else if (event < 11) { 00733 resp = '*'; 00734 } else if (event < 12) { 00735 resp = '#'; 00736 } else if (event < 16) { 00737 resp = 'A' + (event - 12); 00738 } else if (event < 17) { /* Event 16: Hook flash */ 00739 resp = 'X'; 00740 } 00741 00742 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00743 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 00744 rtp->resp = resp; 00745 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00746 f->len = 0; 00747 rtp->lastevent = timestamp; 00748 } 00749 } else { 00750 if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) { 00751 rtp->resp = resp; 00752 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00753 } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) { 00754 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00755 f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */ 00756 rtp->resp = 0; 00757 rtp->lastevent = seqno; 00758 } 00759 } 00760 00761 rtp->dtmfcount = dtmftimeout; 00762 rtp->dtmfsamples = samples; 00763 00764 return f; 00765 }
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 773 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().
00774 { 00775 struct ast_frame *f = NULL; 00776 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00777 totally help us out becuase we don't have an engine to keep it going and we are not 00778 guaranteed to have it every 20ms or anything */ 00779 if (rtpdebug) 00780 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00781 00782 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00783 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00784 ast_inet_ntoa(rtp->them.sin_addr)); 00785 ast_set_flag(rtp, FLAG_3389_WARNING); 00786 } 00787 00788 /* Must have at least one byte */ 00789 if (!len) 00790 return NULL; 00791 if (len < 24) { 00792 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00793 rtp->f.datalen = len - 1; 00794 rtp->f.offset = AST_FRIENDLY_OFFSET; 00795 memcpy(rtp->f.data, data + 1, len - 1); 00796 } else { 00797 rtp->f.data = NULL; 00798 rtp->f.offset = 0; 00799 rtp->f.datalen = 0; 00800 } 00801 rtp->f.frametype = AST_FRAME_CNG; 00802 rtp->f.subclass = data[0] & 0x7f; 00803 rtp->f.datalen = len - 1; 00804 rtp->f.samples = 0; 00805 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00806 f = &rtp->f; 00807 return f; 00808 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 655 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00656 { 00657 if (rtcpdebug == 0) 00658 return 0; 00659 if (rtcpdebugaddr.sin_addr.s_addr) { 00660 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00661 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00662 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00663 return 0; 00664 } 00665 return 1; 00666 }
static int rtcp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3484 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip().
03484 { 03485 if (argc != 2) { 03486 if (argc != 4) 03487 return RESULT_SHOWUSAGE; 03488 return rtcp_do_debug_ip(fd, argc, argv); 03489 } 03490 rtcpdebug = 1; 03491 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03492 ast_cli(fd, "RTCP Debugging Enabled\n"); 03493 return RESULT_SUCCESS; 03494 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3472 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip_deprecated().
03472 { 03473 if (argc != 3) { 03474 if (argc != 5) 03475 return RESULT_SHOWUSAGE; 03476 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03477 } 03478 rtcpdebug = 1; 03479 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03480 ast_cli(fd, "RTCP Debugging Enabled\n"); 03481 return RESULT_SUCCESS; 03482 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3429 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtcp_do_debug().
03430 { 03431 struct hostent *hp; 03432 struct ast_hostent ahp; 03433 int port = 0; 03434 char *p, *arg; 03435 if (argc != 4) 03436 return RESULT_SHOWUSAGE; 03437 03438 arg = argv[3]; 03439 p = strstr(arg, ":"); 03440 if (p) { 03441 *p = '\0'; 03442 p++; 03443 port = atoi(p); 03444 } 03445 hp = ast_gethostbyname(arg, &ahp); 03446 if (hp == NULL) 03447 return RESULT_SHOWUSAGE; 03448 rtcpdebugaddr.sin_family = AF_INET; 03449 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03450 rtcpdebugaddr.sin_port = htons(port); 03451 if (port == 0) 03452 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03453 else 03454 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03455 rtcpdebug = 1; 03456 return RESULT_SUCCESS; 03457 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3399 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().
03400 { 03401 struct hostent *hp; 03402 struct ast_hostent ahp; 03403 int port = 0; 03404 char *p, *arg; 03405 if (argc != 5) 03406 return RESULT_SHOWUSAGE; 03407 03408 arg = argv[4]; 03409 p = strstr(arg, ":"); 03410 if (p) { 03411 *p = '\0'; 03412 p++; 03413 port = atoi(p); 03414 } 03415 hp = ast_gethostbyname(arg, &ahp); 03416 if (hp == NULL) 03417 return RESULT_SHOWUSAGE; 03418 rtcpdebugaddr.sin_family = AF_INET; 03419 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03420 rtcpdebugaddr.sin_port = htons(port); 03421 if (port == 0) 03422 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03423 else 03424 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03425 rtcpdebug = 1; 03426 return RESULT_SUCCESS; 03427 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3505 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03505 { 03506 if (argc != 2) { 03507 return RESULT_SHOWUSAGE; 03508 } 03509 rtcpstats = 1; 03510 ast_cli(fd, "RTCP Stats Enabled\n"); 03511 return RESULT_SUCCESS; 03512 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3496 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03496 { 03497 if (argc != 3) { 03498 return RESULT_SHOWUSAGE; 03499 } 03500 rtcpstats = 1; 03501 ast_cli(fd, "RTCP Stats Enabled\n"); 03502 return RESULT_SUCCESS; 03503 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3532 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03533 { 03534 if (argc != 3) 03535 return RESULT_SHOWUSAGE; 03536 rtcpdebug = 0; 03537 ast_cli(fd,"RTCP Debugging Disabled\n"); 03538 return RESULT_SUCCESS; 03539 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3523 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03524 { 03525 if (argc != 4) 03526 return RESULT_SHOWUSAGE; 03527 rtcpdebug = 0; 03528 ast_cli(fd,"RTCP Debugging Disabled\n"); 03529 return RESULT_SUCCESS; 03530 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3550 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03551 { 03552 if (argc != 3) 03553 return RESULT_SHOWUSAGE; 03554 rtcpstats = 0; 03555 ast_cli(fd,"RTCP Stats Disabled\n"); 03556 return RESULT_SUCCESS; 03557 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3541 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03542 { 03543 if (argc != 4) 03544 return RESULT_SHOWUSAGE; 03545 rtcpstats = 0; 03546 ast_cli(fd,"RTCP Stats Disabled\n"); 03547 return RESULT_SUCCESS; 03548 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 642 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().
00643 { 00644 if (rtpdebug == 0) 00645 return 0; 00646 if (rtpdebugaddr.sin_addr.s_addr) { 00647 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00648 && (rtpdebugaddr.sin_port != addr->sin_port)) 00649 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00650 return 0; 00651 } 00652 return 1; 00653 }
static int rtp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3459 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtp_do_debug_ip().
03460 { 03461 if (argc != 2) { 03462 if (argc != 4) 03463 return RESULT_SHOWUSAGE; 03464 return rtp_do_debug_ip(fd, argc, argv); 03465 } 03466 rtpdebug = 1; 03467 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03468 ast_cli(fd, "RTP Debugging Enabled\n"); 03469 return RESULT_SUCCESS; 03470 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3369 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtp_do_debug().
03370 { 03371 struct hostent *hp; 03372 struct ast_hostent ahp; 03373 int port = 0; 03374 char *p, *arg; 03375 03376 if (argc != 4) 03377 return RESULT_SHOWUSAGE; 03378 arg = argv[3]; 03379 p = strstr(arg, ":"); 03380 if (p) { 03381 *p = '\0'; 03382 p++; 03383 port = atoi(p); 03384 } 03385 hp = ast_gethostbyname(arg, &ahp); 03386 if (hp == NULL) 03387 return RESULT_SHOWUSAGE; 03388 rtpdebugaddr.sin_family = AF_INET; 03389 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03390 rtpdebugaddr.sin_port = htons(port); 03391 if (port == 0) 03392 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03393 else 03394 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03395 rtpdebug = 1; 03396 return RESULT_SUCCESS; 03397 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3514 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03515 { 03516 if (argc != 3) 03517 return RESULT_SHOWUSAGE; 03518 rtpdebug = 0; 03519 ast_cli(fd,"RTP Debugging Disabled\n"); 03520 return RESULT_SUCCESS; 03521 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1828 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01829 { 01830 int s; 01831 long flags; 01832 s = socket(AF_INET, SOCK_DGRAM, 0); 01833 if (s > -1) { 01834 flags = fcntl(s, F_GETFL); 01835 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01836 #ifdef SO_NO_CHECK 01837 if (nochecksums) 01838 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01839 #endif 01840 } 01841 return s; 01842 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 810 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and f.
Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().
00811 { 00812 struct ast_rtp *rtp = cbdata; 00813 struct ast_frame *f; 00814 f = ast_rtp_read(rtp); 00815 if (f) { 00816 if (rtp->callback) 00817 rtp->callback(rtp, f, rtp->data); 00818 } 00819 return 1; 00820 }
static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static] |
Definition at line 615 of file rtp.c.
References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_test_flag, ast_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().
00616 { 00617 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00618 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00619 if (option_debug) 00620 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00621 rtp->resp = 0; 00622 rtp->dtmfsamples = 0; 00623 return &ast_null_frame; 00624 } 00625 if (option_debug) 00626 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00627 if (rtp->resp == 'X') { 00628 rtp->f.frametype = AST_FRAME_CONTROL; 00629 rtp->f.subclass = AST_CONTROL_FLASH; 00630 } else { 00631 rtp->f.frametype = type; 00632 rtp->f.subclass = rtp->resp; 00633 } 00634 rtp->f.datalen = 0; 00635 rtp->f.samples = 0; 00636 rtp->f.mallocd = 0; 00637 rtp->f.src = "RTP"; 00638 return &rtp->f; 00639 00640 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
Definition at line 299 of file rtp.c.
References STUN_CHANGE_REQUEST, STUN_CHANGED_ADDRESS, STUN_ERROR_CODE, STUN_MAPPED_ADDRESS, STUN_MESSAGE_INTEGRITY, STUN_PASSWORD, STUN_REFLECTED_FROM, STUN_RESPONSE_ADDRESS, STUN_SOURCE_ADDRESS, STUN_UNKNOWN_ATTRIBUTES, and STUN_USERNAME.
Referenced by stun_handle_packet(), and stun_process_attr().
00300 { 00301 switch(msg) { 00302 case STUN_MAPPED_ADDRESS: 00303 return "Mapped Address"; 00304 case STUN_RESPONSE_ADDRESS: 00305 return "Response Address"; 00306 case STUN_CHANGE_REQUEST: 00307 return "Change Request"; 00308 case STUN_SOURCE_ADDRESS: 00309 return "Source Address"; 00310 case STUN_CHANGED_ADDRESS: 00311 return "Changed Address"; 00312 case STUN_USERNAME: 00313 return "Username"; 00314 case STUN_PASSWORD: 00315 return "Password"; 00316 case STUN_MESSAGE_INTEGRITY: 00317 return "Message Integrity"; 00318 case STUN_ERROR_CODE: 00319 return "Error Code"; 00320 case STUN_UNKNOWN_ATTRIBUTES: 00321 return "Unknown Attributes"; 00322 case STUN_REFLECTED_FROM: 00323 return "Reflected From"; 00324 } 00325 return "Non-RFC3489 Attribute"; 00326 }
static int stun_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3559 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03560 { 03561 if (argc != 2) { 03562 return RESULT_SHOWUSAGE; 03563 } 03564 stundebug = 1; 03565 ast_cli(fd, "STUN Debugging Enabled\n"); 03566 return RESULT_SUCCESS; 03567 }
static int stun_handle_packet | ( | int | s, | |
struct sockaddr_in * | src, | |||
unsigned char * | data, | |||
size_t | len | |||
) | [static] |
Definition at line 423 of file rtp.c.
References append_attr_address(), append_attr_string(), ast_log(), ast_verbose(), stun_attr::attr, stun_header::id, stun_header::ies, LOG_DEBUG, stun_header::msglen, stun_header::msgtype, option_debug, STUN_ACCEPT, stun_attr2str(), STUN_BINDREQ, STUN_BINDRESP, STUN_IGNORE, STUN_MAPPED_ADDRESS, stun_msg2str(), stun_process_attr(), stun_send(), and STUN_USERNAME.
Referenced by ast_rtp_read().
00424 { 00425 struct stun_header *resp, *hdr = (struct stun_header *)data; 00426 struct stun_attr *attr; 00427 struct stun_state st; 00428 int ret = STUN_IGNORE; 00429 unsigned char respdata[1024]; 00430 int resplen, respleft; 00431 00432 if (len < sizeof(struct stun_header)) { 00433 if (option_debug) 00434 ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header)); 00435 return -1; 00436 } 00437 if (stundebug) 00438 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen)); 00439 if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) { 00440 if (option_debug) 00441 ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header)); 00442 } else 00443 len = ntohs(hdr->msglen); 00444 data += sizeof(struct stun_header); 00445 memset(&st, 0, sizeof(st)); 00446 while(len) { 00447 if (len < sizeof(struct stun_attr)) { 00448 if (option_debug) 00449 ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr)); 00450 break; 00451 } 00452 attr = (struct stun_attr *)data; 00453 if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) { 00454 if (option_debug) 00455 ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len); 00456 break; 00457 } 00458 if (stun_process_attr(&st, attr)) { 00459 if (option_debug) 00460 ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00461 break; 00462 } 00463 /* Clear attribute in case previous entry was a string */ 00464 attr->attr = 0; 00465 data += ntohs(attr->len) + sizeof(struct stun_attr); 00466 len -= ntohs(attr->len) + sizeof(struct stun_attr); 00467 } 00468 /* Null terminate any string */ 00469 *data = '\0'; 00470 resp = (struct stun_header *)respdata; 00471 resplen = 0; 00472 respleft = sizeof(respdata) - sizeof(struct stun_header); 00473 resp->id = hdr->id; 00474 resp->msgtype = 0; 00475 resp->msglen = 0; 00476 attr = (struct stun_attr *)resp->ies; 00477 if (!len) { 00478 switch(ntohs(hdr->msgtype)) { 00479 case STUN_BINDREQ: 00480 if (stundebug) 00481 ast_verbose("STUN Bind Request, username: %s\n", 00482 st.username ? st.username : "<none>"); 00483 if (st.username) 00484 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00485 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00486 resp->msglen = htons(resplen); 00487 resp->msgtype = htons(STUN_BINDRESP); 00488 stun_send(s, src, resp); 00489 ret = STUN_ACCEPT; 00490 break; 00491 default: 00492 if (stundebug) 00493 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00494 } 00495 } 00496 return ret; 00497 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
Definition at line 280 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00281 { 00282 switch(msg) { 00283 case STUN_BINDREQ: 00284 return "Binding Request"; 00285 case STUN_BINDRESP: 00286 return "Binding Response"; 00287 case STUN_BINDERR: 00288 return "Binding Error Response"; 00289 case STUN_SECREQ: 00290 return "Shared Secret Request"; 00291 case STUN_SECRESP: 00292 return "Shared Secret Response"; 00293 case STUN_SECERR: 00294 return "Shared Secret Error Response"; 00295 } 00296 return "Non-RFC3489 Message"; 00297 }
static int stun_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3569 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03570 { 03571 if (argc != 3) 03572 return RESULT_SHOWUSAGE; 03573 stundebug = 0; 03574 ast_cli(fd, "STUN Debugging Disabled\n"); 03575 return RESULT_SUCCESS; 03576 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 333 of file rtp.c.
References ast_verbose(), stun_attr::attr, stun_attr::len, stun_state::password, stun_attr2str(), STUN_PASSWORD, STUN_USERNAME, stun_state::username, and stun_attr::value.
Referenced by stun_handle_packet().
00334 { 00335 if (stundebug) 00336 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00337 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00338 switch(ntohs(attr->attr)) { 00339 case STUN_USERNAME: 00340 state->username = (const char *) (attr->value); 00341 break; 00342 case STUN_PASSWORD: 00343 state->password = (const char *) (attr->value); 00344 break; 00345 default: 00346 if (stundebug) 00347 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00348 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00349 } 00350 return 0; 00351 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
Definition at line 390 of file rtp.c.
References ast_random(), and stun_header::id.
Referenced by ast_rtp_stun_request().
00391 { 00392 int x; 00393 for (x=0;x<4;x++) 00394 req->id.id[x] = ast_random(); 00395 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
Definition at line 384 of file rtp.c.
References stun_header::msglen.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00385 { 00386 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00387 (struct sockaddr *)dst, sizeof(*dst)); 00388 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 502 of file rtp.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00503 { 00504 unsigned int sec, usec, frac; 00505 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00506 usec = tv.tv_usec; 00507 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00508 *msw = sec; 00509 *lsw = frac; 00510 }
struct ast_cli_entry cli_rtp[] [static] |
struct ast_cli_entry cli_rtp_no_debug_deprecated [static] |
Initial value:
{ { "rtp", "no", "debug", NULL }, rtp_no_debug, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_debug_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "debug", NULL }, rtcp_do_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "debug", "ip", NULL }, rtcp_do_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "no", "debug", NULL }, rtcp_no_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "no", "stats", NULL }, rtcp_no_stats_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_stats_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "stats", NULL }, rtcp_do_stats_deprecated, NULL, NULL }
struct ast_cli_entry cli_stun_no_debug_deprecated [static] |
Initial value:
{ { "stun", "no", "debug", NULL }, stun_no_debug, NULL, NULL }
char debug_usage[] [static] |
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
struct { ... } mimeTypes[] [static] |
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
char no_debug_usage[] [static] |
struct stun_header packed |
Referenced by get_unaligned_uint16(), get_unaligned_uint32(), put_unaligned_uint16(), and put_unaligned_uint32().
struct rtpPayloadType payloadType |
Definition at line 1341 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 1373 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 1342 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(), iax2_show_threads(), misdn_cfg_get(), misdn_cfg_get_config_string(), parse_information(), parse_setup(), schedule_delivery(), sla_load_config(), subscription_type2str(), and yyparse().