#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 1826 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().
01827 { 01828 struct ast_rtcp *rtcp; 01829 01830 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01831 return NULL; 01832 rtcp->s = rtp_socket(); 01833 rtcp->us.sin_family = AF_INET; 01834 rtcp->them.sin_family = AF_INET; 01835 01836 if (rtcp->s < 0) { 01837 free(rtcp); 01838 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01839 return NULL; 01840 } 01841 01842 return rtcp; 01843 }
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 rtt = 0; 00835 double a; 00836 double dlsr; 00837 double 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 /* This is the place to calculate RTT */ 00918 /* Don't handle multiple reception reports (rc > 1) yet */ 00919 gettimeofday(&now, NULL); 00920 timeval2ntp(now, &msw, &lsw); 00921 /* Use the one we sent them in our SR instead, rtcp->txlsr could have been rewritten if the dlsr is large */ 00922 if (ntohl(rtcpheader[i + 4])) { /* We must have the LSR */ 00923 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00924 a = (double)((comp & 0xffff0000) >> 16) + (double)((double)(comp & 0xffff)/1000000.); 00925 lsr = (double)((ntohl(rtcpheader[i + 4]) & 0xffff0000) >> 16) + (double)((double)(ntohl(rtcpheader[i + 4]) & 0xffff) / 1000000.); 00926 dlsr = (double)(ntohl(rtcpheader[i + 5])/65536.); 00927 rtt = a - dlsr - lsr; 00928 if (rtt >= 0) { 00929 rtp->rtcp->accumulated_transit += rtt; 00930 rtp->rtcp->rtt = rtt; 00931 if (rtp->rtcp->maxrtt < rtt) 00932 rtp->rtcp->maxrtt = rtt; 00933 if (rtp->rtcp->minrtt > rtt) 00934 rtp->rtcp->minrtt = rtt; 00935 } 00936 } 00937 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00938 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00939 if (rtcp_debug_test_addr(&sin)) { 00940 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00941 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00942 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00943 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00944 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00945 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00946 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00947 if (rtt) 00948 ast_verbose(" RTT: %f(sec)\n", rtt); 00949 } 00950 break; 00951 case RTCP_PT_FUR: 00952 if (rtcp_debug_test_addr(&sin)) 00953 ast_verbose("Received an RTCP Fast Update Request\n"); 00954 rtp->f.frametype = AST_FRAME_CONTROL; 00955 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00956 rtp->f.datalen = 0; 00957 rtp->f.samples = 0; 00958 rtp->f.mallocd = 0; 00959 rtp->f.src = "RTP"; 00960 f = &rtp->f; 00961 break; 00962 case RTCP_PT_SDES: 00963 if (rtcp_debug_test_addr(&sin)) 00964 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00965 break; 00966 case RTCP_PT_BYE: 00967 if (rtcp_debug_test_addr(&sin)) 00968 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00969 break; 00970 default: 00971 if (option_debug) 00972 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)); 00973 break; 00974 } 00975 position += (length + 1); 00976 } 00977 00978 return f; 00979 }
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 2291 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02292 { 02293 struct ast_rtp *rtp = data; 02294 int res; 02295 02296 rtp->rtcp->sendfur = 1; 02297 res = ast_rtcp_write(data); 02298 02299 return res; 02300 }
static int ast_rtcp_write | ( | void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2516 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().
02517 { 02518 struct ast_rtp *rtp = data; 02519 int res; 02520 02521 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02522 res = ast_rtcp_write_sr(data); 02523 else 02524 res = ast_rtcp_write_rr(data); 02525 02526 return res; 02527 }
static int ast_rtcp_write_rr | ( | void * | data | ) | [static] |
Send RTCP recipient's report.
Definition at line 2417 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().
02418 { 02419 struct ast_rtp *rtp = data; 02420 int res; 02421 int len = 32; 02422 unsigned int lost; 02423 unsigned int extended; 02424 unsigned int expected; 02425 unsigned int expected_interval; 02426 unsigned int received_interval; 02427 int lost_interval; 02428 struct timeval now; 02429 unsigned int *rtcpheader; 02430 char bdata[1024]; 02431 struct timeval dlsr; 02432 int fraction; 02433 02434 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02435 return 0; 02436 02437 if (!rtp->rtcp->them.sin_addr.s_addr) { 02438 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02439 if (rtp->rtcp->schedid > 0) 02440 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02441 rtp->rtcp->schedid = -1; 02442 return 0; 02443 } 02444 02445 extended = rtp->cycles + rtp->lastrxseqno; 02446 expected = extended - rtp->seedrxseqno + 1; 02447 lost = expected - rtp->rxcount; 02448 expected_interval = expected - rtp->rtcp->expected_prior; 02449 rtp->rtcp->expected_prior = expected; 02450 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02451 rtp->rtcp->received_prior = rtp->rxcount; 02452 lost_interval = expected_interval - received_interval; 02453 if (expected_interval == 0 || lost_interval <= 0) 02454 fraction = 0; 02455 else 02456 fraction = (lost_interval << 8) / expected_interval; 02457 gettimeofday(&now, NULL); 02458 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02459 rtcpheader = (unsigned int *)bdata; 02460 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02461 rtcpheader[1] = htonl(rtp->ssrc); 02462 rtcpheader[2] = htonl(rtp->themssrc); 02463 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02464 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02465 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02466 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02467 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02468 02469 if (rtp->rtcp->sendfur) { 02470 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02471 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02472 len += 8; 02473 rtp->rtcp->sendfur = 0; 02474 } 02475 02476 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02477 it can change mid call, and SDES can't) */ 02478 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02479 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02480 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02481 len += 12; 02482 02483 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02484 02485 if (res < 0) { 02486 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02487 /* Remove the scheduler */ 02488 if (rtp->rtcp->schedid > 0) 02489 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02490 rtp->rtcp->schedid = -1; 02491 return 0; 02492 } 02493 02494 rtp->rtcp->rr_count++; 02495 02496 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02497 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02498 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02499 " IA jitter: %.4f\n" 02500 " Their last SR: %u\n" 02501 " DLSR: %4.4f (sec)\n\n", 02502 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02503 ntohs(rtp->rtcp->them.sin_port), 02504 rtp->ssrc, rtp->themssrc, fraction, lost, 02505 rtp->rxjitter, 02506 rtp->rtcp->themrxlsr, 02507 (double)(ntohl(rtcpheader[7])/65536.0)); 02508 } 02509 02510 return res; 02511 }
static int ast_rtcp_write_sr | ( | void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2303 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().
02304 { 02305 struct ast_rtp *rtp = data; 02306 int res; 02307 int len = 0; 02308 struct timeval now; 02309 unsigned int now_lsw; 02310 unsigned int now_msw; 02311 unsigned int *rtcpheader; 02312 unsigned int lost; 02313 unsigned int extended; 02314 unsigned int expected; 02315 unsigned int expected_interval; 02316 unsigned int received_interval; 02317 int lost_interval; 02318 int fraction; 02319 struct timeval dlsr; 02320 char bdata[512]; 02321 02322 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02323 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02324 return 0; 02325 02326 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02327 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02328 if (rtp->rtcp->schedid > 0) 02329 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02330 rtp->rtcp->schedid = -1; 02331 return 0; 02332 } 02333 02334 gettimeofday(&now, NULL); 02335 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02336 rtcpheader = (unsigned int *)bdata; 02337 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02338 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02339 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02340 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02341 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02342 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02343 len += 28; 02344 02345 extended = rtp->cycles + rtp->lastrxseqno; 02346 expected = extended - rtp->seedrxseqno + 1; 02347 if (rtp->rxcount > expected) 02348 expected += rtp->rxcount - expected; 02349 lost = expected - rtp->rxcount; 02350 expected_interval = expected - rtp->rtcp->expected_prior; 02351 rtp->rtcp->expected_prior = expected; 02352 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02353 rtp->rtcp->received_prior = rtp->rxcount; 02354 lost_interval = expected_interval - received_interval; 02355 if (expected_interval == 0 || lost_interval <= 0) 02356 fraction = 0; 02357 else 02358 fraction = (lost_interval << 8) / expected_interval; 02359 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02360 rtcpheader[7] = htonl(rtp->themssrc); 02361 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02362 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02363 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02364 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02365 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02366 len += 24; 02367 02368 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02369 02370 if (rtp->rtcp->sendfur) { 02371 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02372 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02373 len += 8; 02374 rtp->rtcp->sendfur = 0; 02375 } 02376 02377 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02378 /* it can change mid call, and SDES can't) */ 02379 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02380 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02381 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02382 len += 12; 02383 02384 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02385 if (res < 0) { 02386 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)); 02387 if (rtp->rtcp->schedid > 0) 02388 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02389 rtp->rtcp->schedid = -1; 02390 return 0; 02391 } 02392 02393 /* FIXME Don't need to get a new one */ 02394 gettimeofday(&rtp->rtcp->txlsr, NULL); 02395 rtp->rtcp->sr_count++; 02396 02397 rtp->rtcp->lastsrtxcount = rtp->txcount; 02398 02399 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02400 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02401 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02402 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02403 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02404 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02405 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02406 ast_verbose(" Report block:\n"); 02407 ast_verbose(" Fraction lost: %u\n", fraction); 02408 ast_verbose(" Cumulative loss: %u\n", lost); 02409 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02410 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02411 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02412 } 02413 return res; 02414 }
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 3185 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_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(), 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_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
03186 { 03187 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03188 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03189 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03190 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03191 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03192 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03193 int codec0 = 0, codec1 = 0; 03194 void *pvt0 = NULL, *pvt1 = NULL; 03195 03196 /* Lock channels */ 03197 ast_channel_lock(c0); 03198 while(ast_channel_trylock(c1)) { 03199 ast_channel_unlock(c0); 03200 usleep(1); 03201 ast_channel_lock(c0); 03202 } 03203 03204 /* Find channel driver interfaces */ 03205 if (!(pr0 = get_proto(c0))) { 03206 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03207 ast_channel_unlock(c0); 03208 ast_channel_unlock(c1); 03209 return AST_BRIDGE_FAILED; 03210 } 03211 if (!(pr1 = get_proto(c1))) { 03212 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03213 ast_channel_unlock(c0); 03214 ast_channel_unlock(c1); 03215 return AST_BRIDGE_FAILED; 03216 } 03217 03218 /* Get channel specific interface structures */ 03219 pvt0 = c0->tech_pvt; 03220 pvt1 = c1->tech_pvt; 03221 03222 /* Get audio and video interface (if native bridge is possible) */ 03223 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03224 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03225 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03226 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03227 03228 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03229 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03230 audio_p0_res = AST_RTP_GET_FAILED; 03231 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03232 audio_p1_res = AST_RTP_GET_FAILED; 03233 03234 /* Check if a bridge is possible (partial/native) */ 03235 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03236 /* Somebody doesn't want to play... */ 03237 ast_channel_unlock(c0); 03238 ast_channel_unlock(c1); 03239 return AST_BRIDGE_FAILED_NOWARN; 03240 } 03241 03242 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03243 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03244 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03245 audio_p0_res = AST_RTP_TRY_PARTIAL; 03246 } 03247 03248 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03249 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03250 audio_p1_res = AST_RTP_TRY_PARTIAL; 03251 } 03252 03253 /* If both sides are not using the same method of DTMF transmission 03254 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03255 * -------------------------------------------------- 03256 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03257 * |-----------|------------|-----------------------| 03258 * | Inband | False | True | 03259 * | RFC2833 | True | True | 03260 * | SIP INFO | False | False | 03261 * -------------------------------------------------- 03262 * However, if DTMF from both channels is being monitored by the core, then 03263 * we can still do packet-to-packet bridging, because passing through the 03264 * core will handle DTMF mode translation. 03265 */ 03266 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03267 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03268 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03269 ast_channel_unlock(c0); 03270 ast_channel_unlock(c1); 03271 return AST_BRIDGE_FAILED_NOWARN; 03272 } 03273 audio_p0_res = AST_RTP_TRY_PARTIAL; 03274 audio_p1_res = AST_RTP_TRY_PARTIAL; 03275 } 03276 03277 /* 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 */ 03278 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF) && ast_test_flag(p0, FLAG_DTMF_COMPENSATE)) || 03279 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF) && ast_test_flag(p1, FLAG_DTMF_COMPENSATE))) { 03280 ast_channel_unlock(c0); 03281 ast_channel_unlock(c1); 03282 return AST_BRIDGE_FAILED_NOWARN; 03283 } 03284 03285 /* Get codecs from both sides */ 03286 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03287 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03288 if (codec0 && codec1 && !(codec0 & codec1)) { 03289 /* Hey, we can't do native bridging if both parties speak different codecs */ 03290 if (option_debug) 03291 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03292 ast_channel_unlock(c0); 03293 ast_channel_unlock(c1); 03294 return AST_BRIDGE_FAILED_NOWARN; 03295 } 03296 03297 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03298 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03299 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03300 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03301 if (option_debug) 03302 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03303 ast_channel_unlock(c0); 03304 ast_channel_unlock(c1); 03305 return AST_BRIDGE_FAILED_NOWARN; 03306 } 03307 if (option_verbose > 2) 03308 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03309 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03310 } else { 03311 if (option_verbose > 2) 03312 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03313 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03314 } 03315 03316 return res; 03317 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2671 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp().
02672 { 02673 if (pt < 0 || pt > MAX_RTP_PT) 02674 return 0; /* bogus payload type */ 02675 02676 if (static_RTP_PT[pt].isAstFormat) 02677 return static_RTP_PT[pt].code; 02678 else 02679 return 0; 02680 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Definition at line 2666 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
02667 { 02668 return &rtp->pref; 02669 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2653 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().
02654 { 02655 int x; 02656 for (x = 0; x < 32; x++) { /* Ugly way */ 02657 rtp->pref.order[x] = prefs->order[x]; 02658 rtp->pref.framing[x] = prefs->framing[x]; 02659 } 02660 if (rtp->smoother) 02661 ast_smoother_free(rtp->smoother); 02662 rtp->smoother = NULL; 02663 return 0; 02664 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2073 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().
02074 { 02075 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02076 /*Print some info on the call here */ 02077 ast_verbose(" RTP-stats\n"); 02078 ast_verbose("* Our Receiver:\n"); 02079 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02080 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02081 ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02082 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02083 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02084 ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count); 02085 ast_verbose("* Our Sender:\n"); 02086 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02087 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02088 ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost); 02089 ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter); 02090 ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count); 02091 ast_verbose(" RTT: %f\n", rtp->rtcp->rtt); 02092 } 02093 02094 if (rtp->smoother) 02095 ast_smoother_free(rtp->smoother); 02096 if (rtp->ioid) 02097 ast_io_remove(rtp->io, rtp->ioid); 02098 if (rtp->s > -1) 02099 close(rtp->s); 02100 if (rtp->rtcp) { 02101 if (rtp->rtcp->schedid > 0) 02102 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02103 close(rtp->rtcp->s); 02104 free(rtp->rtcp); 02105 rtp->rtcp=NULL; 02106 } 02107 02108 ast_mutex_destroy(&rtp->bridge_lock); 02109 02110 free(rtp); 02111 }
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 1459 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().
01460 { 01461 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01462 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01463 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01464 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01465 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01466 int srccodec, destcodec, nat_active = 0; 01467 01468 /* Lock channels */ 01469 ast_channel_lock(dest); 01470 if (src) { 01471 while(ast_channel_trylock(src)) { 01472 ast_channel_unlock(dest); 01473 usleep(1); 01474 ast_channel_lock(dest); 01475 } 01476 } 01477 01478 /* Find channel driver interfaces */ 01479 destpr = get_proto(dest); 01480 if (src) 01481 srcpr = get_proto(src); 01482 if (!destpr) { 01483 if (option_debug) 01484 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01485 ast_channel_unlock(dest); 01486 if (src) 01487 ast_channel_unlock(src); 01488 return 0; 01489 } 01490 if (!srcpr) { 01491 if (option_debug) 01492 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01493 ast_channel_unlock(dest); 01494 if (src) 01495 ast_channel_unlock(src); 01496 return 0; 01497 } 01498 01499 /* Get audio and video interface (if native bridge is possible) */ 01500 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01501 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01502 if (srcpr) { 01503 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01504 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01505 } 01506 01507 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01508 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01509 /* Somebody doesn't want to play... */ 01510 ast_channel_unlock(dest); 01511 if (src) 01512 ast_channel_unlock(src); 01513 return 0; 01514 } 01515 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01516 srccodec = srcpr->get_codec(src); 01517 else 01518 srccodec = 0; 01519 if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec) 01520 destcodec = destpr->get_codec(dest); 01521 else 01522 destcodec = 0; 01523 /* Ensure we have at least one matching codec */ 01524 if (!(srccodec & destcodec)) { 01525 ast_channel_unlock(dest); 01526 if (src) 01527 ast_channel_unlock(src); 01528 return 0; 01529 } 01530 /* Consider empty media as non-existant */ 01531 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01532 srcp = NULL; 01533 /* If the client has NAT stuff turned on then just safe NAT is active */ 01534 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01535 nat_active = 1; 01536 /* Bridge media early */ 01537 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01538 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01539 ast_channel_unlock(dest); 01540 if (src) 01541 ast_channel_unlock(src); 01542 if (option_debug) 01543 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01544 return 1; 01545 }
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 1995 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().
01996 { 01997 struct ast_rtp *bridged = NULL; 01998 01999 ast_mutex_lock(&rtp->bridge_lock); 02000 bridged = rtp->bridged; 02001 ast_mutex_unlock(&rtp->bridge_lock); 02002 02003 return bridged; 02004 }
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 1665 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().
01667 { 01668 int pt; 01669 01670 ast_mutex_lock(&rtp->bridge_lock); 01671 01672 *astFormats = *nonAstFormats = 0; 01673 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01674 if (rtp->current_RTP_PT[pt].isAstFormat) { 01675 *astFormats |= rtp->current_RTP_PT[pt].code; 01676 } else { 01677 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01678 } 01679 } 01680 01681 ast_mutex_unlock(&rtp->bridge_lock); 01682 01683 return; 01684 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 1977 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), bridge_native_loop(), do_monitor(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
01978 { 01979 if ((them->sin_family != AF_INET) || 01980 (them->sin_port != rtp->them.sin_port) || 01981 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 01982 them->sin_family = AF_INET; 01983 them->sin_port = rtp->them.sin_port; 01984 them->sin_addr = rtp->them.sin_addr; 01985 return 1; 01986 } 01987 return 0; 01988 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2043 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().
02044 { 02045 /* 02046 *ssrc our ssrc 02047 *themssrc their ssrc 02048 *lp lost packets 02049 *rxjitter our calculated jitter(rx) 02050 *rxcount no. received packets 02051 *txjitter reported jitter of the other end 02052 *txcount transmitted packets 02053 *rlp remote lost packets 02054 *rtt round trip time 02055 */ 02056 02057 if (qual) { 02058 qual->local_ssrc = rtp->ssrc; 02059 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02060 qual->local_jitter = rtp->rxjitter; 02061 qual->local_count = rtp->rxcount; 02062 qual->remote_ssrc = rtp->themssrc; 02063 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02064 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02065 qual->remote_count = rtp->txcount; 02066 qual->rtt = rtp->rtcp->rtt; 02067 } 02068 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); 02069 02070 return rtp->rtcp->quality; 02071 }
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 1990 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 3702 of file rtp.c.
References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp.
Referenced by main().
03703 { 03704 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03705 ast_rtp_reload(); 03706 }
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 1708 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().
01709 { 01710 int pt = 0; 01711 01712 ast_mutex_lock(&rtp->bridge_lock); 01713 01714 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01715 code == rtp->rtp_lookup_code_cache_code) { 01716 /* Use our cached mapping, to avoid the overhead of the loop below */ 01717 pt = rtp->rtp_lookup_code_cache_result; 01718 ast_mutex_unlock(&rtp->bridge_lock); 01719 return pt; 01720 } 01721 01722 /* Check the dynamic list first */ 01723 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01724 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01725 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01726 rtp->rtp_lookup_code_cache_code = code; 01727 rtp->rtp_lookup_code_cache_result = pt; 01728 ast_mutex_unlock(&rtp->bridge_lock); 01729 return pt; 01730 } 01731 } 01732 01733 /* Then the static list */ 01734 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01735 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01736 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01737 rtp->rtp_lookup_code_cache_code = code; 01738 rtp->rtp_lookup_code_cache_result = pt; 01739 ast_mutex_unlock(&rtp->bridge_lock); 01740 return pt; 01741 } 01742 } 01743 01744 ast_mutex_unlock(&rtp->bridge_lock); 01745 01746 return -1; 01747 }
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 1768 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len, and name.
Referenced by process_sdp().
01770 { 01771 int format; 01772 unsigned len; 01773 char *end = buf; 01774 char *start = buf; 01775 01776 if (!buf || !size) 01777 return NULL; 01778 01779 snprintf(end, size, "0x%x (", capability); 01780 01781 len = strlen(end); 01782 end += len; 01783 size -= len; 01784 start = end; 01785 01786 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01787 if (capability & format) { 01788 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01789 01790 snprintf(end, size, "%s|", name); 01791 len = strlen(end); 01792 end += len; 01793 size -= len; 01794 } 01795 } 01796 01797 if (start == end) 01798 snprintf(start, size, "nothing)"); 01799 else if (size > 1) 01800 *(end -1) = ')'; 01801 01802 return buf; 01803 }
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 1749 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().
01751 { 01752 unsigned int i; 01753 01754 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01755 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01756 if (isAstFormat && 01757 (code == AST_FORMAT_G726_AAL2) && 01758 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01759 return "G726-32"; 01760 else 01761 return mimeTypes[i].subtype; 01762 } 01763 } 01764 01765 return ""; 01766 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1686 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().
01687 { 01688 struct rtpPayloadType result; 01689 01690 result.isAstFormat = result.code = 0; 01691 01692 if (pt < 0 || pt > MAX_RTP_PT) 01693 return result; /* bogus payload type */ 01694 01695 /* Start with negotiated codecs */ 01696 ast_mutex_lock(&rtp->bridge_lock); 01697 result = rtp->current_RTP_PT[pt]; 01698 ast_mutex_unlock(&rtp->bridge_lock); 01699 01700 /* If it doesn't exist, check our static RTP type list, just in case */ 01701 if (!result.code) 01702 result = static_RTP_PT[pt]; 01703 01704 return result; 01705 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1547 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().
01548 { 01549 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01550 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01551 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01552 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01553 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01554 int srccodec, destcodec; 01555 01556 /* Lock channels */ 01557 ast_channel_lock(dest); 01558 while(ast_channel_trylock(src)) { 01559 ast_channel_unlock(dest); 01560 usleep(1); 01561 ast_channel_lock(dest); 01562 } 01563 01564 /* Find channel driver interfaces */ 01565 if (!(destpr = get_proto(dest))) { 01566 if (option_debug) 01567 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01568 ast_channel_unlock(dest); 01569 ast_channel_unlock(src); 01570 return 0; 01571 } 01572 if (!(srcpr = get_proto(src))) { 01573 if (option_debug) 01574 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01575 ast_channel_unlock(dest); 01576 ast_channel_unlock(src); 01577 return 0; 01578 } 01579 01580 /* Get audio and video interface (if native bridge is possible) */ 01581 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01582 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01583 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01584 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01585 01586 /* Ensure we have at least one matching codec */ 01587 if (srcpr->get_codec) 01588 srccodec = srcpr->get_codec(src); 01589 else 01590 srccodec = 0; 01591 if (destpr->get_codec) 01592 destcodec = destpr->get_codec(dest); 01593 else 01594 destcodec = 0; 01595 01596 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01597 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) { 01598 /* Somebody doesn't want to play... */ 01599 ast_channel_unlock(dest); 01600 ast_channel_unlock(src); 01601 return 0; 01602 } 01603 ast_rtp_pt_copy(destp, srcp); 01604 if (vdestp && vsrcp) 01605 ast_rtp_pt_copy(vdestp, vsrcp); 01606 if (media) { 01607 /* Bridge early */ 01608 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01609 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01610 } 01611 ast_channel_unlock(dest); 01612 ast_channel_unlock(src); 01613 if (option_debug) 01614 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01615 return 1; 01616 }
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 1949 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
01950 { 01951 struct in_addr ia; 01952 01953 memset(&ia, 0, sizeof(ia)); 01954 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 01955 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1849 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().
01850 { 01851 ast_mutex_init(&rtp->bridge_lock); 01852 01853 rtp->them.sin_family = AF_INET; 01854 rtp->us.sin_family = AF_INET; 01855 rtp->ssrc = ast_random(); 01856 rtp->seqno = ast_random() & 0xffff; 01857 ast_set_flag(rtp, FLAG_HAS_DTMF); 01858 01859 return; 01860 }
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 1862 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().
01863 { 01864 struct ast_rtp *rtp; 01865 int x; 01866 int first; 01867 int startplace; 01868 01869 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01870 return NULL; 01871 01872 ast_rtp_new_init(rtp); 01873 01874 rtp->s = rtp_socket(); 01875 if (rtp->s < 0) { 01876 free(rtp); 01877 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01878 return NULL; 01879 } 01880 if (sched && rtcpenable) { 01881 rtp->sched = sched; 01882 rtp->rtcp = ast_rtcp_new(); 01883 } 01884 01885 /* Select a random port number in the range of possible RTP */ 01886 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01887 x = x & ~1; 01888 /* Save it for future references. */ 01889 startplace = x; 01890 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01891 for (;;) { 01892 /* Must be an even port number by RTP spec */ 01893 rtp->us.sin_port = htons(x); 01894 rtp->us.sin_addr = addr; 01895 /* If there's rtcp, initialize it as well. */ 01896 if (rtp->rtcp) { 01897 rtp->rtcp->us.sin_port = htons(x + 1); 01898 rtp->rtcp->us.sin_addr = addr; 01899 } 01900 /* Try to bind it/them. */ 01901 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01902 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01903 break; 01904 if (!first) { 01905 /* Primary bind succeeded! Gotta recreate it */ 01906 close(rtp->s); 01907 rtp->s = rtp_socket(); 01908 } 01909 if (errno != EADDRINUSE) { 01910 /* We got an error that wasn't expected, abort! */ 01911 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01912 close(rtp->s); 01913 if (rtp->rtcp) { 01914 close(rtp->rtcp->s); 01915 free(rtp->rtcp); 01916 } 01917 free(rtp); 01918 return NULL; 01919 } 01920 /* The port was used, increment it (by two). */ 01921 x += 2; 01922 /* Did we go over the limit ? */ 01923 if (x > rtpend) 01924 /* then, start from the begingig. */ 01925 x = (rtpstart + 1) & ~1; 01926 /* Check if we reached the place were we started. */ 01927 if (x == startplace) { 01928 /* If so, there's no ports available. */ 01929 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01930 close(rtp->s); 01931 if (rtp->rtcp) { 01932 close(rtp->rtcp->s); 01933 free(rtp->rtcp); 01934 } 01935 free(rtp); 01936 return NULL; 01937 } 01938 } 01939 rtp->sched = sched; 01940 rtp->io = io; 01941 if (callbackmode) { 01942 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01943 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01944 } 01945 ast_rtp_pt_default(rtp); 01946 return rtp; 01947 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2770 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().
02771 { 02772 struct ast_rtp_protocol *cur; 02773 02774 AST_LIST_LOCK(&protos); 02775 AST_LIST_TRAVERSE(&protos, cur, list) { 02776 if (!strcmp(cur->type, proto->type)) { 02777 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02778 AST_LIST_UNLOCK(&protos); 02779 return -1; 02780 } 02781 } 02782 AST_LIST_INSERT_HEAD(&protos, proto, list); 02783 AST_LIST_UNLOCK(&protos); 02784 02785 return 0; 02786 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2762 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.
Referenced by load_module(), and unload_module().
02763 { 02764 AST_LIST_LOCK(&protos); 02765 AST_LIST_REMOVE(&protos, proto, list); 02766 AST_LIST_UNLOCK(&protos); 02767 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1383 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().
01384 { 01385 int i; 01386 01387 if (!rtp) 01388 return; 01389 01390 ast_mutex_lock(&rtp->bridge_lock); 01391 01392 for (i = 0; i < MAX_RTP_PT; ++i) { 01393 rtp->current_RTP_PT[i].isAstFormat = 0; 01394 rtp->current_RTP_PT[i].code = 0; 01395 } 01396 01397 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01398 rtp->rtp_lookup_code_cache_code = 0; 01399 rtp->rtp_lookup_code_cache_result = 0; 01400 01401 ast_mutex_unlock(&rtp->bridge_lock); 01402 }
Copy payload types between RTP structures.
Definition at line 1423 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().
01424 { 01425 unsigned int i; 01426 01427 ast_mutex_lock(&dest->bridge_lock); 01428 ast_mutex_lock(&src->bridge_lock); 01429 01430 for (i=0; i < MAX_RTP_PT; ++i) { 01431 dest->current_RTP_PT[i].isAstFormat = 01432 src->current_RTP_PT[i].isAstFormat; 01433 dest->current_RTP_PT[i].code = 01434 src->current_RTP_PT[i].code; 01435 } 01436 dest->rtp_lookup_code_cache_isAstFormat = 0; 01437 dest->rtp_lookup_code_cache_code = 0; 01438 dest->rtp_lookup_code_cache_result = 0; 01439 01440 ast_mutex_unlock(&src->bridge_lock); 01441 ast_mutex_unlock(&dest->bridge_lock); 01442 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1404 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().
01405 { 01406 int i; 01407 01408 ast_mutex_lock(&rtp->bridge_lock); 01409 01410 /* Initialize to default payload types */ 01411 for (i = 0; i < MAX_RTP_PT; ++i) { 01412 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01413 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01414 } 01415 01416 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01417 rtp->rtp_lookup_code_cache_code = 0; 01418 rtp->rtp_lookup_code_cache_result = 0; 01419 01420 ast_mutex_unlock(&rtp->bridge_lock); 01421 }
Definition at line 2564 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().
02565 { 02566 unsigned char *rtpheader; 02567 int hdrlen = 12; 02568 int res; 02569 unsigned int ms; 02570 int pred; 02571 int mark = 0; 02572 02573 ms = calc_txstamp(rtp, &f->delivery); 02574 /* Default prediction */ 02575 if (f->subclass < AST_FORMAT_MAX_AUDIO) { 02576 pred = rtp->lastts + f->samples; 02577 02578 /* Re-calculate last TS */ 02579 rtp->lastts = rtp->lastts + ms * 8; 02580 if (ast_tvzero(f->delivery)) { 02581 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02582 and if so, go with our prediction */ 02583 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02584 rtp->lastts = pred; 02585 else { 02586 if (option_debug > 2) 02587 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02588 mark = 1; 02589 } 02590 } 02591 } else { 02592 mark = f->subclass & 0x1; 02593 pred = rtp->lastovidtimestamp + f->samples; 02594 /* Re-calculate last TS */ 02595 rtp->lastts = rtp->lastts + ms * 90; 02596 /* If it's close to our prediction, go for it */ 02597 if (ast_tvzero(f->delivery)) { 02598 if (abs(rtp->lastts - pred) < 7200) { 02599 rtp->lastts = pred; 02600 rtp->lastovidtimestamp += f->samples; 02601 } else { 02602 if (option_debug > 2) 02603 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); 02604 rtp->lastovidtimestamp = rtp->lastts; 02605 } 02606 } 02607 } 02608 /* If the timestamp for non-digit packets has moved beyond the timestamp 02609 for digits, update the digit timestamp. 02610 */ 02611 if (rtp->lastts > rtp->lastdigitts) 02612 rtp->lastdigitts = rtp->lastts; 02613 02614 if (f->has_timing_info) 02615 rtp->lastts = f->ts * 8; 02616 02617 /* Get a pointer to the header */ 02618 rtpheader = (unsigned char *)(f->data - hdrlen); 02619 02620 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02621 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02622 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02623 02624 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02625 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02626 if (res <0) { 02627 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02628 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)); 02629 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02630 /* Only give this error message once if we are not RTP debugging */ 02631 if (option_debug || rtpdebug) 02632 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)); 02633 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02634 } 02635 } else { 02636 rtp->txcount++; 02637 rtp->txoctetcount +=(res - hdrlen); 02638 02639 if (rtp->rtcp && rtp->rtcp->schedid < 1) 02640 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02641 } 02642 02643 if (rtp_debug_test_addr(&rtp->them)) 02644 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02645 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02646 } 02647 02648 rtp->seqno++; 02649 02650 return 0; 02651 }
Definition at line 1081 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().
01082 { 01083 int res; 01084 struct sockaddr_in sin; 01085 socklen_t len; 01086 unsigned int seqno; 01087 int version; 01088 int payloadtype; 01089 int hdrlen = 12; 01090 int padding; 01091 int mark; 01092 int ext; 01093 unsigned int ssrc; 01094 unsigned int timestamp; 01095 unsigned int *rtpheader; 01096 struct rtpPayloadType rtpPT; 01097 struct ast_rtp *bridged = NULL; 01098 01099 if( !rtp ) { 01100 ast_log(LOG_ERROR, "ast_rtp_read(): called with rtp == NULL\n"); 01101 ast_backtrace(); 01102 return &ast_null_frame; 01103 } 01104 01105 /* If time is up, kill it */ 01106 if (rtp->sending_digit) 01107 ast_rtp_senddigit_continuation(rtp); 01108 01109 len = sizeof(sin); 01110 01111 /* Cache where the header will go */ 01112 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01113 0, (struct sockaddr *)&sin, &len); 01114 01115 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01116 if (res < 0) { 01117 if (errno == EBADF) 01118 CRASH; 01119 if (errno != EAGAIN) { 01120 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01121 return NULL; 01122 } 01123 return &ast_null_frame; 01124 } 01125 01126 if (res < hdrlen) { 01127 ast_log(LOG_WARNING, "RTP Read too short\n"); 01128 return &ast_null_frame; 01129 } 01130 01131 /* Get fields */ 01132 seqno = ntohl(rtpheader[0]); 01133 01134 /* Check RTP version */ 01135 version = (seqno & 0xC0000000) >> 30; 01136 if (!version) { 01137 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01138 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01139 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01140 } 01141 return &ast_null_frame; 01142 } 01143 01144 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01145 /* If we don't have the other side's address, then ignore this */ 01146 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01147 return &ast_null_frame; 01148 #endif 01149 01150 /* Send to whoever send to us if NAT is turned on */ 01151 if (rtp->nat) { 01152 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01153 (rtp->them.sin_port != sin.sin_port)) { 01154 rtp->them = sin; 01155 if (rtp->rtcp) { 01156 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01157 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01158 } 01159 rtp->rxseqno = 0; 01160 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01161 if (option_debug || rtpdebug) 01162 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)); 01163 } 01164 } 01165 01166 /* If we are bridged to another RTP stream, send direct */ 01167 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01168 return &ast_null_frame; 01169 01170 if (version != 2) 01171 return &ast_null_frame; 01172 01173 payloadtype = (seqno & 0x7f0000) >> 16; 01174 padding = seqno & (1 << 29); 01175 mark = seqno & (1 << 23); 01176 ext = seqno & (1 << 28); 01177 seqno &= 0xffff; 01178 timestamp = ntohl(rtpheader[1]); 01179 ssrc = ntohl(rtpheader[2]); 01180 01181 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01182 if (option_debug || rtpdebug) 01183 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01184 mark = 1; 01185 } 01186 01187 rtp->rxssrc = ssrc; 01188 01189 if (padding) { 01190 /* Remove padding bytes */ 01191 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01192 } 01193 01194 if (ext) { 01195 /* RTP Extension present */ 01196 hdrlen += 4; 01197 hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2; 01198 if (option_debug) { 01199 int profile; 01200 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01201 if (profile == 0x505a) 01202 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01203 else 01204 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile); 01205 } 01206 } 01207 01208 if (res < hdrlen) { 01209 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01210 return &ast_null_frame; 01211 } 01212 01213 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01214 01215 if (rtp->rxcount==1) { 01216 /* This is the first RTP packet successfully received from source */ 01217 rtp->seedrxseqno = seqno; 01218 } 01219 01220 /* Do not schedule RR if RTCP isn't run */ 01221 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01222 /* Schedule transmission of Receiver Report */ 01223 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01224 } 01225 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01226 rtp->cycles += RTP_SEQ_MOD; 01227 01228 rtp->lastrxseqno = seqno; 01229 01230 if (rtp->themssrc==0) 01231 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01232 01233 if (rtp_debug_test_addr(&sin)) 01234 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01235 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01236 01237 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01238 if (!rtpPT.isAstFormat) { 01239 struct ast_frame *f = NULL; 01240 01241 /* This is special in-band data that's not one of our codecs */ 01242 if (rtpPT.code == AST_RTP_DTMF) { 01243 /* It's special -- rfc2833 process it */ 01244 if (rtp_debug_test_addr(&sin)) { 01245 unsigned char *data; 01246 unsigned int event; 01247 unsigned int event_end; 01248 unsigned int duration; 01249 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01250 event = ntohl(*((unsigned int *)(data))); 01251 event >>= 24; 01252 event_end = ntohl(*((unsigned int *)(data))); 01253 event_end <<= 8; 01254 event_end >>= 24; 01255 duration = ntohl(*((unsigned int *)(data))); 01256 duration &= 0xFFFF; 01257 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); 01258 } 01259 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01260 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01261 /* It's really special -- process it the Cisco way */ 01262 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01263 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01264 rtp->lastevent = seqno; 01265 } 01266 } else if (rtpPT.code == AST_RTP_CN) { 01267 /* Comfort Noise */ 01268 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01269 } else { 01270 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01271 } 01272 return f ? f : &ast_null_frame; 01273 } 01274 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01275 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01276 01277 if (!rtp->lastrxts) 01278 rtp->lastrxts = timestamp; 01279 01280 rtp->rxseqno = seqno; 01281 01282 /* Record received timestamp as last received now */ 01283 rtp->lastrxts = timestamp; 01284 01285 rtp->f.mallocd = 0; 01286 rtp->f.datalen = res - hdrlen; 01287 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01288 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01289 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01290 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01291 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01292 ast_frame_byteswap_be(&rtp->f); 01293 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01294 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01295 rtp->f.has_timing_info = 1; 01296 rtp->f.ts = timestamp / 8; 01297 rtp->f.len = rtp->f.samples / 8; 01298 rtp->f.seqno = seqno; 01299 } else { 01300 /* Video -- samples is # of samples vs. 90000 */ 01301 if (!rtp->lastividtimestamp) 01302 rtp->lastividtimestamp = timestamp; 01303 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01304 rtp->lastividtimestamp = timestamp; 01305 rtp->f.delivery.tv_sec = 0; 01306 rtp->f.delivery.tv_usec = 0; 01307 if (mark) 01308 rtp->f.subclass |= 0x1; 01309 01310 } 01311 rtp->f.src = "RTP"; 01312 return &rtp->f; 01313 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3637 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().
03638 { 03639 struct ast_config *cfg; 03640 const char *s; 03641 03642 rtpstart = 5000; 03643 rtpend = 31000; 03644 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03645 cfg = ast_config_load("rtp.conf"); 03646 if (cfg) { 03647 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03648 rtpstart = atoi(s); 03649 if (rtpstart < 1024) 03650 rtpstart = 1024; 03651 if (rtpstart > 65535) 03652 rtpstart = 65535; 03653 } 03654 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03655 rtpend = atoi(s); 03656 if (rtpend < 1024) 03657 rtpend = 1024; 03658 if (rtpend > 65535) 03659 rtpend = 65535; 03660 } 03661 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03662 rtcpinterval = atoi(s); 03663 if (rtcpinterval == 0) 03664 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03665 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03666 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03667 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03668 rtcpinterval = RTCP_MAX_INTERVALMS; 03669 } 03670 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03671 #ifdef SO_NO_CHECK 03672 if (ast_false(s)) 03673 nochecksums = 1; 03674 else 03675 nochecksums = 0; 03676 #else 03677 if (ast_false(s)) 03678 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03679 #endif 03680 } 03681 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03682 dtmftimeout = atoi(s); 03683 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03684 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03685 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03686 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03687 }; 03688 } 03689 ast_config_destroy(cfg); 03690 } 03691 if (rtpstart >= rtpend) { 03692 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03693 rtpstart = 5000; 03694 rtpend = 31000; 03695 } 03696 if (option_verbose > 1) 03697 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03698 return 0; 03699 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2023 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.
02024 { 02025 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02026 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02027 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02028 rtp->lastts = 0; 02029 rtp->lastdigitts = 0; 02030 rtp->lastrxts = 0; 02031 rtp->lastividtimestamp = 0; 02032 rtp->lastovidtimestamp = 0; 02033 rtp->lasteventseqn = 0; 02034 rtp->lastevent = 0; 02035 rtp->lasttxformat = 0; 02036 rtp->lastrxformat = 0; 02037 rtp->dtmfcount = 0; 02038 rtp->dtmfsamples = 0; 02039 rtp->seqno = 0; 02040 rtp->rxseqno = 0; 02041 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2530 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().
02531 { 02532 unsigned int *rtpheader; 02533 int hdrlen = 12; 02534 int res; 02535 int payload; 02536 char data[256]; 02537 level = 127 - (level & 0x7f); 02538 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02539 02540 /* If we have no peer, return immediately */ 02541 if (!rtp->them.sin_addr.s_addr) 02542 return 0; 02543 02544 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02545 02546 /* Get a pointer to the header */ 02547 rtpheader = (unsigned int *)data; 02548 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02549 rtpheader[1] = htonl(rtp->lastts); 02550 rtpheader[2] = htonl(rtp->ssrc); 02551 data[12] = level; 02552 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02553 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02554 if (res <0) 02555 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)); 02556 if (rtp_debug_test_addr(&rtp->them)) 02557 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02558 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02559 02560 } 02561 return 0; 02562 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2133 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().
02134 { 02135 unsigned int *rtpheader; 02136 int hdrlen = 12, res = 0, i = 0, payload = 0; 02137 char data[256]; 02138 02139 if ((digit <= '9') && (digit >= '0')) 02140 digit -= '0'; 02141 else if (digit == '*') 02142 digit = 10; 02143 else if (digit == '#') 02144 digit = 11; 02145 else if ((digit >= 'A') && (digit <= 'D')) 02146 digit = digit - 'A' + 12; 02147 else if ((digit >= 'a') && (digit <= 'd')) 02148 digit = digit - 'a' + 12; 02149 else { 02150 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02151 return 0; 02152 } 02153 02154 /* If we have no peer, return immediately */ 02155 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02156 return 0; 02157 02158 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02159 02160 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02161 rtp->send_duration = 160; 02162 02163 /* Get a pointer to the header */ 02164 rtpheader = (unsigned int *)data; 02165 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02166 rtpheader[1] = htonl(rtp->lastdigitts); 02167 rtpheader[2] = htonl(rtp->ssrc); 02168 02169 for (i = 0; i < 2; i++) { 02170 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02171 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02172 if (res < 0) 02173 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02174 ast_inet_ntoa(rtp->them.sin_addr), 02175 ntohs(rtp->them.sin_port), strerror(errno)); 02176 if (rtp_debug_test_addr(&rtp->them)) 02177 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02178 ast_inet_ntoa(rtp->them.sin_addr), 02179 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02180 /* Increment sequence number */ 02181 rtp->seqno++; 02182 /* Increment duration */ 02183 rtp->send_duration += 160; 02184 /* Clear marker bit and set seqno */ 02185 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02186 } 02187 02188 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02189 rtp->sending_digit = 1; 02190 rtp->send_digit = digit; 02191 rtp->send_payload = payload; 02192 02193 return 0; 02194 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2197 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().
02198 { 02199 unsigned int *rtpheader; 02200 int hdrlen = 12, res = 0; 02201 char data[256]; 02202 02203 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02204 return 0; 02205 02206 /* Setup packet to send */ 02207 rtpheader = (unsigned int *)data; 02208 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02209 rtpheader[1] = htonl(rtp->lastdigitts); 02210 rtpheader[2] = htonl(rtp->ssrc); 02211 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02212 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02213 02214 /* Transmit */ 02215 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02216 if (res < 0) 02217 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02218 ast_inet_ntoa(rtp->them.sin_addr), 02219 ntohs(rtp->them.sin_port), strerror(errno)); 02220 if (rtp_debug_test_addr(&rtp->them)) 02221 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02222 ast_inet_ntoa(rtp->them.sin_addr), 02223 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02224 02225 /* Increment sequence number */ 02226 rtp->seqno++; 02227 /* Increment duration */ 02228 rtp->send_duration += 160; 02229 02230 return 0; 02231 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2234 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().
02235 { 02236 unsigned int *rtpheader; 02237 int hdrlen = 12, res = 0, i = 0; 02238 char data[256]; 02239 02240 /* If no address, then bail out */ 02241 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02242 return 0; 02243 02244 if ((digit <= '9') && (digit >= '0')) 02245 digit -= '0'; 02246 else if (digit == '*') 02247 digit = 10; 02248 else if (digit == '#') 02249 digit = 11; 02250 else if ((digit >= 'A') && (digit <= 'D')) 02251 digit = digit - 'A' + 12; 02252 else if ((digit >= 'a') && (digit <= 'd')) 02253 digit = digit - 'a' + 12; 02254 else { 02255 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02256 return 0; 02257 } 02258 02259 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02260 02261 rtpheader = (unsigned int *)data; 02262 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02263 rtpheader[1] = htonl(rtp->lastdigitts); 02264 rtpheader[2] = htonl(rtp->ssrc); 02265 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02266 /* Set end bit */ 02267 rtpheader[3] |= htonl((1 << 23)); 02268 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02269 /* Send 3 termination packets */ 02270 for (i = 0; i < 3; i++) { 02271 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02272 if (res < 0) 02273 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02274 ast_inet_ntoa(rtp->them.sin_addr), 02275 ntohs(rtp->them.sin_port), strerror(errno)); 02276 if (rtp_debug_test_addr(&rtp->them)) 02277 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02278 ast_inet_ntoa(rtp->them.sin_addr), 02279 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02280 } 02281 rtp->sending_digit = 0; 02282 rtp->send_digit = 0; 02283 /* Increment lastdigitts */ 02284 rtp->lastdigitts += 960; 02285 rtp->seqno++; 02286 02287 return res; 02288 }
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 1622 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().
01623 { 01624 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01625 return; /* bogus payload type */ 01626 01627 ast_mutex_lock(&rtp->bridge_lock); 01628 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01629 ast_mutex_unlock(&rtp->bridge_lock); 01630 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 1966 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().
01967 { 01968 rtp->them.sin_port = them->sin_port; 01969 rtp->them.sin_addr = them->sin_addr; 01970 if (rtp->rtcp) { 01971 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 01972 rtp->rtcp->them.sin_addr = them->sin_addr; 01973 } 01974 rtp->rxseqno = 0; 01975 }
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 1635 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().
01638 { 01639 unsigned int i; 01640 01641 if (pt < 0 || pt > MAX_RTP_PT) 01642 return; /* bogus payload type */ 01643 01644 ast_mutex_lock(&rtp->bridge_lock); 01645 01646 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01647 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01648 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01649 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01650 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01651 mimeTypes[i].payloadType.isAstFormat && 01652 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01653 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01654 break; 01655 } 01656 } 01657 01658 ast_mutex_unlock(&rtp->bridge_lock); 01659 01660 return; 01661 }
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 1957 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
01958 { 01959 int res; 01960 01961 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 01962 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 01963 return res; 01964 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2006 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().
02007 { 02008 if (rtp->rtcp && rtp->rtcp->schedid > 0) { 02009 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02010 rtp->rtcp->schedid = -1; 02011 } 02012 02013 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02014 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02015 if (rtp->rtcp) { 02016 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02017 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02018 } 02019 02020 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02021 }
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 2682 of file rtp.c.
References ast_codec_pref_getsize(), 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().
02683 { 02684 struct ast_frame *f; 02685 int codec; 02686 int hdrlen = 12; 02687 int subclass; 02688 02689 02690 /* If we have no peer, return immediately */ 02691 if (!rtp->them.sin_addr.s_addr) 02692 return 0; 02693 02694 /* If there is no data length, return immediately */ 02695 if (!_f->datalen) 02696 return 0; 02697 02698 /* Make sure we have enough space for RTP header */ 02699 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02700 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02701 return -1; 02702 } 02703 02704 subclass = _f->subclass; 02705 if (_f->frametype == AST_FRAME_VIDEO) 02706 subclass &= ~0x1; 02707 02708 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02709 if (codec < 0) { 02710 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02711 return -1; 02712 } 02713 02714 if (rtp->lasttxformat != subclass) { 02715 /* New format, reset the smoother */ 02716 if (option_debug) 02717 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02718 rtp->lasttxformat = subclass; 02719 if (rtp->smoother) 02720 ast_smoother_free(rtp->smoother); 02721 rtp->smoother = NULL; 02722 } 02723 02724 if (!rtp->smoother) { 02725 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02726 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02727 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02728 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)); 02729 return -1; 02730 } 02731 if (fmt.flags) 02732 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02733 if (option_debug) 02734 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)); 02735 } 02736 } 02737 if (rtp->smoother) { 02738 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02739 ast_smoother_feed_be(rtp->smoother, _f); 02740 } else { 02741 ast_smoother_feed(rtp->smoother, _f); 02742 } 02743 02744 while((f = ast_smoother_read(rtp->smoother))) 02745 ast_rtp_raw_write(rtp, f, codec); 02746 } else { 02747 /* Don't buffer outgoing frames; send them one-per-packet: */ 02748 if (_f->offset < hdrlen) { 02749 f = ast_frdup(_f); 02750 } else { 02751 f = _f; 02752 } 02753 ast_rtp_raw_write(rtp, f, codec); 02754 if (f != _f) 02755 ast_frfree(f); 02756 } 02757 02758 return 0; 02759 }
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 2789 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().
02790 { 02791 struct ast_frame *fr = NULL; 02792 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02793 int oldcodec0 = codec0, oldcodec1 = codec1; 02794 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02795 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02796 02797 /* Set it up so audio goes directly between the two endpoints */ 02798 02799 /* Test the first channel */ 02800 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02801 ast_rtp_get_peer(p1, &ac1); 02802 if (vp1) 02803 ast_rtp_get_peer(vp1, &vac1); 02804 } else 02805 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 02806 02807 /* Test the second channel */ 02808 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 02809 ast_rtp_get_peer(p0, &ac0); 02810 if (vp0) 02811 ast_rtp_get_peer(vp0, &vac0); 02812 } else 02813 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 02814 02815 /* Now we can unlock and move into our loop */ 02816 ast_channel_unlock(c0); 02817 ast_channel_unlock(c1); 02818 02819 /* Throw our channels into the structure and enter the loop */ 02820 cs[0] = c0; 02821 cs[1] = c1; 02822 cs[2] = NULL; 02823 for (;;) { 02824 /* Check if anything changed */ 02825 if ((c0->tech_pvt != pvt0) || 02826 (c1->tech_pvt != pvt1) || 02827 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 02828 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 02829 if (c0->tech_pvt == pvt0) 02830 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02831 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02832 if (c1->tech_pvt == pvt1) 02833 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02834 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02835 return AST_BRIDGE_RETRY; 02836 } 02837 02838 /* Check if they have changed their address */ 02839 ast_rtp_get_peer(p1, &t1); 02840 if (vp1) 02841 ast_rtp_get_peer(vp1, &vt1); 02842 if (pr1->get_codec) 02843 codec1 = pr1->get_codec(c1); 02844 ast_rtp_get_peer(p0, &t0); 02845 if (vp0) 02846 ast_rtp_get_peer(vp0, &vt0); 02847 if (pr0->get_codec) 02848 codec0 = pr0->get_codec(c0); 02849 if ((inaddrcmp(&t1, &ac1)) || 02850 (vp1 && inaddrcmp(&vt1, &vac1)) || 02851 (codec1 != oldcodec1)) { 02852 if (option_debug > 1) { 02853 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02854 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 02855 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 02856 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 02857 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02858 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 02859 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02860 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 02861 } 02862 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))) 02863 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 02864 memcpy(&ac1, &t1, sizeof(ac1)); 02865 memcpy(&vac1, &vt1, sizeof(vac1)); 02866 oldcodec1 = codec1; 02867 } 02868 if ((inaddrcmp(&t0, &ac0)) || 02869 (vp0 && inaddrcmp(&vt0, &vac0))) { 02870 if (option_debug > 1) { 02871 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02872 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 02873 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02874 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 02875 } 02876 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))) 02877 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 02878 memcpy(&ac0, &t0, sizeof(ac0)); 02879 memcpy(&vac0, &vt0, sizeof(vac0)); 02880 oldcodec0 = codec0; 02881 } 02882 02883 /* Wait for frame to come in on the channels */ 02884 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 02885 if (!timeoutms) 02886 return AST_BRIDGE_RETRY; 02887 if (option_debug) 02888 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 02889 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 02890 break; 02891 continue; 02892 } 02893 fr = ast_read(who); 02894 other = (who == c0) ? c1 : c0; 02895 if (!fr || ((fr->frametype == AST_FRAME_DTMF) && 02896 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 02897 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 02898 /* Break out of bridge */ 02899 *fo = fr; 02900 *rc = who; 02901 if (option_debug) 02902 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 02903 if (c0->tech_pvt == pvt0) 02904 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02905 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02906 if (c1->tech_pvt == pvt1) 02907 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02908 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02909 return AST_BRIDGE_COMPLETE; 02910 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02911 if ((fr->subclass == AST_CONTROL_HOLD) || 02912 (fr->subclass == AST_CONTROL_UNHOLD) || 02913 (fr->subclass == AST_CONTROL_VIDUPDATE)) { 02914 if (fr->subclass == AST_CONTROL_HOLD) { 02915 /* If we someone went on hold we want the other side to reinvite back to us */ 02916 if (who == c0) 02917 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 02918 else 02919 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 02920 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 02921 /* If they went off hold they should go back to being direct */ 02922 if (who == c0) 02923 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 02924 else 02925 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 02926 } 02927 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 02928 ast_frfree(fr); 02929 } else { 02930 *fo = fr; 02931 *rc = who; 02932 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 02933 return AST_BRIDGE_COMPLETE; 02934 } 02935 } else { 02936 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 02937 (fr->frametype == AST_FRAME_DTMF) || 02938 (fr->frametype == AST_FRAME_VOICE) || 02939 (fr->frametype == AST_FRAME_VIDEO) || 02940 (fr->frametype == AST_FRAME_IMAGE) || 02941 (fr->frametype == AST_FRAME_HTML) || 02942 (fr->frametype == AST_FRAME_MODEM) || 02943 (fr->frametype == AST_FRAME_TEXT)) { 02944 ast_write(other, fr); 02945 } 02946 ast_frfree(fr); 02947 } 02948 /* Swap priority */ 02949 cs[2] = cs[0]; 02950 cs[0] = cs[1]; 02951 cs[1] = cs[2]; 02952 } 02953 02954 return AST_BRIDGE_FAILED; 02955 }
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 3053 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().
03054 { 03055 struct ast_frame *fr = NULL; 03056 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03057 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03058 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03059 int p0_callback = 0, p1_callback = 0; 03060 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03061 03062 /* Okay, setup each RTP structure to do P2P forwarding */ 03063 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03064 p2p_set_bridge(p0, p1); 03065 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03066 p2p_set_bridge(p1, p0); 03067 03068 /* Activate callback modes if possible */ 03069 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03070 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03071 03072 /* Now let go of the channel locks and be on our way */ 03073 ast_channel_unlock(c0); 03074 ast_channel_unlock(c1); 03075 03076 /* Go into a loop forwarding frames until we don't need to anymore */ 03077 cs[0] = c0; 03078 cs[1] = c1; 03079 cs[2] = NULL; 03080 for (;;) { 03081 /* Check if anything changed */ 03082 if ((c0->tech_pvt != pvt0) || 03083 (c1->tech_pvt != pvt1) || 03084 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 03085 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03086 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03087 ast_frfree(fr); 03088 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03089 ast_frfree(fr); 03090 res = AST_BRIDGE_RETRY; 03091 break; 03092 } 03093 /* Wait on a channel to feed us a frame */ 03094 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03095 if (!timeoutms) { 03096 res = AST_BRIDGE_RETRY; 03097 break; 03098 } 03099 if (option_debug) 03100 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03101 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03102 break; 03103 continue; 03104 } 03105 /* Read in frame from channel */ 03106 fr = ast_read(who); 03107 other = (who == c0) ? c1 : c0; 03108 /* Dependong on the frame we may need to break out of our bridge */ 03109 if (!fr || ((fr->frametype == AST_FRAME_DTMF) && 03110 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03111 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03112 /* Record received frame and who */ 03113 *fo = fr; 03114 *rc = who; 03115 if (option_debug) 03116 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03117 res = AST_BRIDGE_COMPLETE; 03118 break; 03119 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03120 if ((fr->subclass == AST_CONTROL_HOLD) || 03121 (fr->subclass == AST_CONTROL_UNHOLD) || 03122 (fr->subclass == AST_CONTROL_VIDUPDATE)) { 03123 /* If we are going on hold, then break callback mode and P2P bridging */ 03124 if (fr->subclass == AST_CONTROL_HOLD) { 03125 if (p0_callback) 03126 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03127 if (p1_callback) 03128 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03129 p2p_set_bridge(p0, NULL); 03130 p2p_set_bridge(p1, NULL); 03131 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03132 /* If we are off hold, then go back to callback mode and P2P bridging */ 03133 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03134 p2p_set_bridge(p0, p1); 03135 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03136 p2p_set_bridge(p1, p0); 03137 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03138 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03139 } 03140 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03141 ast_frfree(fr); 03142 } else { 03143 *fo = fr; 03144 *rc = who; 03145 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03146 res = AST_BRIDGE_COMPLETE; 03147 break; 03148 } 03149 } else { 03150 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03151 (fr->frametype == AST_FRAME_DTMF) || 03152 (fr->frametype == AST_FRAME_VOICE) || 03153 (fr->frametype == AST_FRAME_VIDEO) || 03154 (fr->frametype == AST_FRAME_IMAGE) || 03155 (fr->frametype == AST_FRAME_HTML) || 03156 (fr->frametype == AST_FRAME_MODEM) || 03157 (fr->frametype == AST_FRAME_TEXT)) { 03158 ast_write(other, fr); 03159 } 03160 03161 ast_frfree(fr); 03162 } 03163 /* Swap priority */ 03164 cs[2] = cs[0]; 03165 cs[0] = cs[1]; 03166 cs[1] = cs[2]; 03167 } 03168 03169 /* If we are totally avoiding the core, then restore our link to it */ 03170 if (p0_callback) 03171 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03172 if (p1_callback) 03173 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03174 03175 /* Break out of the direct bridge */ 03176 p2p_set_bridge(p0, NULL); 03177 p2p_set_bridge(p1, NULL); 03178 03179 return res; 03180 }
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 1030 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, ext, 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, rtp_debug_test_addr(), ast_rtp::s, and ast_rtp::them.
Referenced by ast_rtp_read().
01031 { 01032 int res = 0, payload = 0, bridged_payload = 0, version, padding, mark, ext; 01033 struct rtpPayloadType rtpPT; 01034 unsigned int seqno; 01035 01036 /* Get fields from packet */ 01037 seqno = ntohl(rtpheader[0]); 01038 version = (seqno & 0xC0000000) >> 30; 01039 payload = (seqno & 0x7f0000) >> 16; 01040 padding = seqno & (1 << 29); 01041 mark = (seqno & 0x800000) >> 23; 01042 ext = seqno & (1 << 28); 01043 seqno &= 0xffff; 01044 01045 /* Check what the payload value should be */ 01046 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01047 01048 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01049 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01050 return -1; 01051 01052 /* Otherwise adjust bridged payload to match */ 01053 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01054 01055 /* If the mark bit has not been sent yet... do it now */ 01056 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01057 mark = 1; 01058 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01059 } 01060 01061 /* Reconstruct part of the packet */ 01062 rtpheader[0] = htonl((version << 30) | (mark << 23) | (bridged_payload << 16) | (seqno)); 01063 01064 /* Send the packet back out */ 01065 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01066 if (res < 0) { 01067 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01068 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)); 01069 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01070 if (option_debug || rtpdebug) 01071 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)); 01072 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01073 } 01074 return 0; 01075 } else if (rtp_debug_test_addr(&bridged->them)) 01076 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); 01077 01078 return 0; 01079 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 981 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().
00982 { 00983 struct timeval now; 00984 double transit; 00985 double current_time; 00986 double d; 00987 double dtv; 00988 double prog; 00989 00990 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 00991 gettimeofday(&rtp->rxcore, NULL); 00992 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 00993 /* map timestamp to a real time */ 00994 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 00995 rtp->rxcore.tv_sec -= timestamp / 8000; 00996 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 00997 /* Round to 0.1ms for nice, pretty timestamps */ 00998 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 00999 if (rtp->rxcore.tv_usec < 0) { 01000 /* Adjust appropriately if necessary */ 01001 rtp->rxcore.tv_usec += 1000000; 01002 rtp->rxcore.tv_sec -= 1; 01003 } 01004 } 01005 01006 gettimeofday(&now,NULL); 01007 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01008 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01009 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01010 if (tv->tv_usec >= 1000000) { 01011 tv->tv_usec -= 1000000; 01012 tv->tv_sec += 1; 01013 } 01014 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01015 dtv = (double)rtp->drxcore + (double)(prog); 01016 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01017 transit = current_time - dtv; 01018 d = transit - rtp->rxtransit; 01019 rtp->rxtransit = transit; 01020 if (d<0) 01021 d=-d; 01022 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01023 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01024 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01025 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01026 rtp->rtcp->minrxjitter = rtp->rxjitter; 01027 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2113 of file rtp.c.
References t, and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02114 { 02115 struct timeval t; 02116 long ms; 02117 if (ast_tvzero(rtp->txcore)) { 02118 rtp->txcore = ast_tvnow(); 02119 /* Round to 20ms for nice, pretty timestamps */ 02120 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02121 } 02122 /* Use previous txcore if available */ 02123 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02124 ms = ast_tvdiff_ms(t, rtp->txcore); 02125 if (ms < 0) 02126 ms = 0; 02127 /* Use what we just got for next time */ 02128 rtp->txcore = t; 02129 return (unsigned int) ms; 02130 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 1445 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().
01446 { 01447 struct ast_rtp_protocol *cur = NULL; 01448 01449 AST_LIST_LOCK(&protos); 01450 AST_LIST_TRAVERSE(&protos, cur, list) { 01451 if (cur->type == chan->tech->type) 01452 break; 01453 } 01454 AST_LIST_UNLOCK(&protos); 01455 01456 return cur; 01457 }
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 3024 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().
03025 { 03026 ast_channel_lock(chan); 03027 03028 /* Remove the callback from the IO context */ 03029 ast_io_remove(rtp->io, iod[0]); 03030 03031 /* Restore file descriptors */ 03032 chan->fds[0] = fds[0]; 03033 ast_channel_unlock(chan); 03034 03035 /* Restore callback mode if previously used */ 03036 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03037 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03038 03039 return 0; 03040 }
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 3043 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03044 { 03045 ast_mutex_lock(&rtp0->bridge_lock); 03046 rtp0->bridged = rtp1; 03047 ast_mutex_unlock(&rtp0->bridge_lock); 03048 03049 return; 03050 }
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 3434 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip().
03434 { 03435 if (argc != 2) { 03436 if (argc != 4) 03437 return RESULT_SHOWUSAGE; 03438 return rtcp_do_debug_ip(fd, argc, argv); 03439 } 03440 rtcpdebug = 1; 03441 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03442 ast_cli(fd, "RTCP Debugging Enabled\n"); 03443 return RESULT_SUCCESS; 03444 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3422 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcp_do_debug_ip_deprecated().
03422 { 03423 if (argc != 3) { 03424 if (argc != 5) 03425 return RESULT_SHOWUSAGE; 03426 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03427 } 03428 rtcpdebug = 1; 03429 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03430 ast_cli(fd, "RTCP Debugging Enabled\n"); 03431 return RESULT_SUCCESS; 03432 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3379 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtcp_do_debug().
03380 { 03381 struct hostent *hp; 03382 struct ast_hostent ahp; 03383 int port = 0; 03384 char *p, *arg; 03385 if (argc != 4) 03386 return RESULT_SHOWUSAGE; 03387 03388 arg = argv[3]; 03389 p = strstr(arg, ":"); 03390 if (p) { 03391 *p = '\0'; 03392 p++; 03393 port = atoi(p); 03394 } 03395 hp = ast_gethostbyname(arg, &ahp); 03396 if (hp == NULL) 03397 return RESULT_SHOWUSAGE; 03398 rtcpdebugaddr.sin_family = AF_INET; 03399 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03400 rtcpdebugaddr.sin_port = htons(port); 03401 if (port == 0) 03402 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03403 else 03404 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03405 rtcpdebug = 1; 03406 return RESULT_SUCCESS; 03407 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3349 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().
03350 { 03351 struct hostent *hp; 03352 struct ast_hostent ahp; 03353 int port = 0; 03354 char *p, *arg; 03355 if (argc != 5) 03356 return RESULT_SHOWUSAGE; 03357 03358 arg = argv[4]; 03359 p = strstr(arg, ":"); 03360 if (p) { 03361 *p = '\0'; 03362 p++; 03363 port = atoi(p); 03364 } 03365 hp = ast_gethostbyname(arg, &ahp); 03366 if (hp == NULL) 03367 return RESULT_SHOWUSAGE; 03368 rtcpdebugaddr.sin_family = AF_INET; 03369 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03370 rtcpdebugaddr.sin_port = htons(port); 03371 if (port == 0) 03372 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03373 else 03374 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03375 rtcpdebug = 1; 03376 return RESULT_SUCCESS; 03377 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3455 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03455 { 03456 if (argc != 2) { 03457 return RESULT_SHOWUSAGE; 03458 } 03459 rtcpstats = 1; 03460 ast_cli(fd, "RTCP Stats Enabled\n"); 03461 return RESULT_SUCCESS; 03462 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3446 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03446 { 03447 if (argc != 3) { 03448 return RESULT_SHOWUSAGE; 03449 } 03450 rtcpstats = 1; 03451 ast_cli(fd, "RTCP Stats Enabled\n"); 03452 return RESULT_SUCCESS; 03453 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3482 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03483 { 03484 if (argc != 3) 03485 return RESULT_SHOWUSAGE; 03486 rtcpdebug = 0; 03487 ast_cli(fd,"RTCP Debugging Disabled\n"); 03488 return RESULT_SUCCESS; 03489 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3473 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03474 { 03475 if (argc != 4) 03476 return RESULT_SHOWUSAGE; 03477 rtcpdebug = 0; 03478 ast_cli(fd,"RTCP Debugging Disabled\n"); 03479 return RESULT_SUCCESS; 03480 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3500 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03501 { 03502 if (argc != 3) 03503 return RESULT_SHOWUSAGE; 03504 rtcpstats = 0; 03505 ast_cli(fd,"RTCP Stats Disabled\n"); 03506 return RESULT_SUCCESS; 03507 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3491 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03492 { 03493 if (argc != 4) 03494 return RESULT_SHOWUSAGE; 03495 rtcpstats = 0; 03496 ast_cli(fd,"RTCP Stats Disabled\n"); 03497 return RESULT_SUCCESS; 03498 }
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 3409 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtp_do_debug_ip().
03410 { 03411 if (argc != 2) { 03412 if (argc != 4) 03413 return RESULT_SHOWUSAGE; 03414 return rtp_do_debug_ip(fd, argc, argv); 03415 } 03416 rtpdebug = 1; 03417 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03418 ast_cli(fd, "RTP Debugging Enabled\n"); 03419 return RESULT_SUCCESS; 03420 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3319 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by rtp_do_debug().
03320 { 03321 struct hostent *hp; 03322 struct ast_hostent ahp; 03323 int port = 0; 03324 char *p, *arg; 03325 03326 if (argc != 4) 03327 return RESULT_SHOWUSAGE; 03328 arg = argv[3]; 03329 p = strstr(arg, ":"); 03330 if (p) { 03331 *p = '\0'; 03332 p++; 03333 port = atoi(p); 03334 } 03335 hp = ast_gethostbyname(arg, &ahp); 03336 if (hp == NULL) 03337 return RESULT_SHOWUSAGE; 03338 rtpdebugaddr.sin_family = AF_INET; 03339 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03340 rtpdebugaddr.sin_port = htons(port); 03341 if (port == 0) 03342 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03343 else 03344 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03345 rtpdebug = 1; 03346 return RESULT_SUCCESS; 03347 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3464 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03465 { 03466 if (argc != 3) 03467 return RESULT_SHOWUSAGE; 03468 rtpdebug = 0; 03469 ast_cli(fd,"RTP Debugging Disabled\n"); 03470 return RESULT_SUCCESS; 03471 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1805 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01806 { 01807 int s; 01808 long flags; 01809 s = socket(AF_INET, SOCK_DGRAM, 0); 01810 if (s > -1) { 01811 flags = fcntl(s, F_GETFL); 01812 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01813 #ifdef SO_NO_CHECK 01814 if (nochecksums) 01815 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01816 #endif 01817 } 01818 return s; 01819 }
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 3509 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03510 { 03511 if (argc != 2) { 03512 return RESULT_SHOWUSAGE; 03513 } 03514 stundebug = 1; 03515 ast_cli(fd, "STUN Debugging Enabled\n"); 03516 return RESULT_SUCCESS; 03517 }
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) > len) { 00454 if (option_debug) 00455 ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %zd)\n", ntohs(attr->len), 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 3519 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03520 { 03521 if (argc != 3) 03522 return RESULT_SHOWUSAGE; 03523 stundebug = 0; 03524 ast_cli(fd, "STUN Debugging Disabled\n"); 03525 return RESULT_SUCCESS; 03526 }
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 1318 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 1350 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 1319 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().