#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <math.h>
#include "asterisk/rtp.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
Go to the source code of this file.
Data Structures | |
struct | ast_rtcp |
Structure defining an RTCP session. More... | |
struct | ast_rtp |
RTP session description. More... | |
struct | protos |
List of current sessions. More... | |
struct | rtp_red |
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 |
here we store credentials extracted from a message More... | |
struct | stun_trans_id |
STUN support code. More... | |
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_JITTER_FORMAT1 |
#define | RTCP_JITTER_FORMAT2 "rxjitter=%f;" |
#define | RTCP_LOSS_FORMAT1 |
#define | RTCP_LOSS_FORMAT2 |
#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 | SQUARE(x) ((x) * (x)) |
#define | STUN_ACCEPT (1) |
#define | STUN_BINDERR 0x0111 |
#define | STUN_BINDREQ 0x0001 |
STUN message types 'BIND' refers to transactions used to determine the externally visible addresses. 'SEC' refers to transactions used to establish a session key for subsequent requests. 'SEC' functionality is not supported here. | |
#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 |
Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7fff). | |
#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 |
Typedefs | |
typedef int( | stun_cb_f )(struct stun_attr *attr, void *arg) |
callback type to be invoked on stun responses. | |
Enumerations | |
enum | strict_rtp_state { STRICT_RTP_OPEN = 0, STRICT_RTP_LEARN, STRICT_RTP_CLOSED } |
Functions | |
static double | __ast_rtp_get_qos (struct ast_rtp *rtp, const char *qos, int *found) |
static char * | __ast_rtp_get_quality (struct ast_rtp *rtp) |
static char * | __ast_rtp_get_quality_jitter (struct ast_rtp *rtp) |
static char * | __ast_rtp_get_quality_loss (struct ast_rtp *rtp) |
static char * | __ast_rtp_get_quality_rtt (struct ast_rtp *rtp) |
static int | __ast_rtp_reload (int reload) |
static void | append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sock_in, int *len, int *left) |
append an address to an STUN message | |
static void | append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left) |
append a string to an STUN message | |
static unsigned int | ast_rtcp_calc_interval (struct ast_rtp *rtp) |
int | ast_rtcp_fd (struct ast_rtp *rtp) |
static struct ast_rtcp * | ast_rtcp_new (void) |
Initialize a new RTCP session. | |
ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
int | ast_rtcp_send_h261fur (void *data) |
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP. | |
static int | ast_rtcp_write (const void *data) |
Write and RTCP packet to the far end. | |
static int | ast_rtcp_write_rr (const void *data) |
Send RTCP recipient's report. | |
static int | ast_rtcp_write_sr (const void *data) |
Send RTCP sender's report. | |
size_t | ast_rtp_alloc_size (void) |
Get the amount of space required to hold an RTP session. | |
enum ast_bridge_result | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
The RTP bridge. | |
int | ast_rtp_codec_getformat (int pt) |
get format from predefined dynamic payload format | |
ast_codec_pref * | ast_rtp_codec_getpref (struct ast_rtp *rtp) |
Get codec preference. | |
void | ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs) |
Set codec preference. | |
void | ast_rtp_destroy (struct ast_rtp *rtp) |
int | ast_rtp_early_bridge (struct ast_channel *c0, struct ast_channel *c1) |
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) |
int | ast_rtp_get_qos (struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen) |
Get QOS stats on a RTP channel. | |
unsigned int | ast_rtp_get_qosvalue (struct ast_rtp *rtp, enum ast_rtp_qos_vars value) |
Return RTP and RTCP QoS values. | |
char * | ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype) |
Return RTCP quality string. | |
int | ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp) |
Get rtp hold timeout. | |
int | ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp) |
Get RTP keepalive interval. | |
int | ast_rtp_get_rtptimeout (struct ast_rtp *rtp) |
Get rtp timeout. | |
void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
int | ast_rtp_getnat (struct ast_rtp *rtp) |
void | ast_rtp_init (void) |
Initialize the RTP system in Asterisk. | |
int | ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code) |
Looks up an RTP code out of our *static* outbound list. | |
char * | ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options) |
Build a string of MIME subtype names from a capability list. | |
const char * | ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code, enum ast_rtp_options options) |
Mapping an Asterisk code into a MIME subtype (string):. | |
rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
Mapping between RTP payload format codes and Asterisk codes:. | |
int | ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media) |
ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
Initializate a RTP session. | |
void | ast_rtp_new_init (struct ast_rtp *rtp) |
Initialize a new RTP structure. | |
void | ast_rtp_new_source (struct ast_rtp *rtp) |
ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr) |
Initializate a RTP session using an in_addr structure. | |
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
Register an RTP channel client. | |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
Unregister an RTP channel client. | |
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) |
Write RTP packet with audio or video media frames into UDP packet. | |
ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
int | ast_rtp_reload (void) |
void | ast_rtp_reset (struct ast_rtp *rtp) |
int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
generate comfort noice (CNG) | |
int | ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit) |
Send begin frames for DTMF. | |
static int | ast_rtp_senddigit_continuation (struct ast_rtp *rtp) |
Send continuation frame for DTMF. | |
int | ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit) |
Send end packets for DTMF. | |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
Activate payload type. | |
void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
void | ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout) |
Set rtp hold timeout. | |
void | ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period) |
set RTP keepalive interval | |
int | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options) |
Initiate payload type to a known MIME media type for a codec. | |
void | ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout) |
Set rtp timeout. | |
void | ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp) |
void | ast_rtp_set_vars (struct ast_channel *chan, struct ast_rtp *rtp) |
Set RTPAUDIOQOS(...) variables on a channel when it is being hung up. | |
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) |
int | ast_rtp_setqos (struct ast_rtp *rtp, int type_of_service, int class_of_service, char *desc) |
void | ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable) |
Enable STUN capability. | |
void | ast_rtp_stop (struct ast_rtp *rtp) |
void | ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username) |
Send STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request(). | |
void | ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt) |
clear payload type | |
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f) |
int | ast_stun_request (int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer) |
Generic STUN request send a generic stun request to the server specified. | |
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 *tp0, struct ast_rtp *tp1, 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 *when, 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 char * | handle_cli_rtcp_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rtcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rtcp_set_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rtcp_stats_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rtp_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rtp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_stun_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_stun_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static double | normdev_compute (double normdev, double sample, unsigned int sample_count) |
Calculate normal deviation. | |
static int | p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, 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 **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. | |
void | red_buffer_t140 (struct ast_rtp *rtp, struct ast_frame *f) |
Buffer t.140 data. | |
static struct ast_frame * | red_t140_to_red (struct rtp_red *red) |
Construct a redundant frame. | |
static int | red_write (const void *data) |
Write t140 redundacy frame. | |
static int | rtcp_debug_test_addr (struct sockaddr_in *addr) |
static char * | rtcp_do_debug_ip (struct ast_cli_args *a) |
static void | rtp_bridge_lock (struct ast_rtp *rtp) |
static void | rtp_bridge_unlock (struct ast_rtp *rtp) |
static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
static char * | rtp_do_debug_ip (struct ast_cli_args *a) |
int | rtp_red_init (struct ast_rtp *rtp, int ti, int *red_data_pt, int num_gen) |
Initalize t.140 redudancy. | |
static int | rtp_socket (const char *type) |
Open RTP or RTCP socket for a session. Print a message on failure. | |
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 double | stddev_compute (double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count) |
static const char * | stun_attr2str (int msg) |
helper function to print attribute names | |
static int | stun_get_mapped (struct stun_attr *attr, void *arg) |
Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_response when called from ast_stun_request. | |
static int | stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg) |
handle an incoming STUN message. | |
static const char * | stun_msg2str (int msg) |
helper function to print message names | |
static int | stun_process_attr (struct stun_state *state, struct stun_attr *attr) |
static void | stun_req_id (struct stun_header *req) |
helper function to generate a random request id | |
static int | stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp) |
wrapper to send an STUN message | |
static void | timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw) |
Variables | |
static struct ast_cli_entry | cli_rtcp_debug_deprecated = { .handler = handle_cli_rtcp_debug_deprecated , .summary = "Enable/Disable RTCP debugging" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_rtcp_stats_deprecated = { .handler = handle_cli_rtcp_stats_deprecated , .summary = "Enable/Disable RTCP stats" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_rtp [] |
static struct ast_cli_entry | cli_rtp_debug_deprecated = { .handler = handle_cli_rtp_debug_deprecated , .summary = "Enable/Disable RTP debugging" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_stun_debug_deprecated = { .handler = handle_cli_stun_debug_deprecated , .summary = "Enable/Disable STUN debugging" ,__VA_ARGS__ } |
static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
struct { | |
rtpPayloadType payloadType | |
char * subtype | |
char * type | |
} | mimeTypes [] |
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 = 31000 |
static int | rtpstart = 5000 |
static struct rtpPayloadType | static_RTP_PT [MAX_RTP_PT] |
Mapping between Asterisk codecs and rtp payload types. | |
static int | strictrtp |
static int | stundebug |
Definition in file rtp.c.
#define DEFAULT_DTMF_TIMEOUT 3000 |
#define FLAG_3389_WARNING (1 << 0) |
#define FLAG_CALLBACK_MODE (1 << 6) |
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 220 of file rtp.c.
Referenced by ast_rtp_setdtmfcompensate(), process_cisco_dtmf(), process_rfc2833(), and send_dtmf().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 216 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 213 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 214 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 215 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 217 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 51 of file rtp.c.
Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp().
#define RTCP_DEFAULT_INTERVALMS 5000 |
#define RTCP_JITTER_FORMAT1 |
Referenced by __ast_rtp_get_quality_jitter().
#define RTCP_JITTER_FORMAT2 "rxjitter=%f;" |
Referenced by __ast_rtp_get_quality_jitter().
#define RTCP_LOSS_FORMAT1 |
Referenced by __ast_rtp_get_quality_loss().
#define RTCP_LOSS_FORMAT2 |
#define RTCP_MAX_INTERVALMS 60000 |
Max milli-seconds between RTCP reports we send
Definition at line 56 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 55 of file rtp.c.
Referenced by __ast_rtp_reload().
#define RTCP_PT_BYE 203 |
#define RTCP_PT_FUR 192 |
Definition at line 58 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 61 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 53 of file rtp.c.
Referenced by ast_rtp_read().
#define SQUARE | ( | x | ) | ((x) * (x)) |
Referenced by stddev_compute().
#define STUN_ACCEPT (1) |
#define STUN_BINDERR 0x0111 |
#define STUN_BINDREQ 0x0001 |
STUN message types 'BIND' refers to transactions used to determine the externally visible addresses. 'SEC' refers to transactions used to establish a session key for subsequent requests. 'SEC' functionality is not supported here.
Definition at line 350 of file rtp.c.
Referenced by ast_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 |
Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7fff).
Definition at line 360 of file rtp.c.
Referenced by stun_attr2str(), stun_get_mapped(), and stun_handle_packet().
#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 365 of file rtp.c.
Referenced by ast_stun_request(), stun_attr2str(), stun_handle_packet(), and stun_process_attr().
enum strict_rtp_state |
STRICT_RTP_OPEN | |
STRICT_RTP_LEARN | No RTP packets should be dropped, all sources accepted |
STRICT_RTP_CLOSED | Accept next packet as source |
Definition at line 85 of file rtp.c.
00085 { 00086 STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */ 00087 STRICT_RTP_LEARN, /*! Accept next packet as source */ 00088 STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */ 00089 };
static double __ast_rtp_get_qos | ( | struct ast_rtp * | rtp, | |
const char * | qos, | |||
int * | found | |||
) | [static] |
Definition at line 2680 of file rtp.c.
References ast_rtcp::maxrtt, ast_rtcp::maxrxjitter, ast_rtcp::minrtt, ast_rtcp::minrxjitter, ast_rtcp::normdev_rxjitter, ast_rtcp::normdevrtt, ast_rtcp::reported_maxjitter, ast_rtcp::reported_minjitter, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_stdev_jitter, ast_rtp::rtcp, ast_rtcp::stdev_rxjitter, and ast_rtcp::stdevrtt.
Referenced by ast_rtp_get_qos().
02681 { 02682 *found = 1; 02683 02684 if (!strcasecmp(qos, "remote_maxjitter")) 02685 return rtp->rtcp->reported_maxjitter * 1000.0; 02686 if (!strcasecmp(qos, "remote_minjitter")) 02687 return rtp->rtcp->reported_minjitter * 1000.0; 02688 if (!strcasecmp(qos, "remote_normdevjitter")) 02689 return rtp->rtcp->reported_normdev_jitter * 1000.0; 02690 if (!strcasecmp(qos, "remote_stdevjitter")) 02691 return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0; 02692 02693 if (!strcasecmp(qos, "local_maxjitter")) 02694 return rtp->rtcp->maxrxjitter * 1000.0; 02695 if (!strcasecmp(qos, "local_minjitter")) 02696 return rtp->rtcp->minrxjitter * 1000.0; 02697 if (!strcasecmp(qos, "local_normdevjitter")) 02698 return rtp->rtcp->normdev_rxjitter * 1000.0; 02699 if (!strcasecmp(qos, "local_stdevjitter")) 02700 return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0; 02701 02702 if (!strcasecmp(qos, "maxrtt")) 02703 return rtp->rtcp->maxrtt * 1000.0; 02704 if (!strcasecmp(qos, "minrtt")) 02705 return rtp->rtcp->minrtt * 1000.0; 02706 if (!strcasecmp(qos, "normdevrtt")) 02707 return rtp->rtcp->normdevrtt * 1000.0; 02708 if (!strcasecmp(qos, "stdevrtt")) 02709 return sqrt(rtp->rtcp->stdevrtt) * 1000.0; 02710 02711 *found = 0; 02712 02713 return 0.0; 02714 }
static char* __ast_rtp_get_quality | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2883 of file rtp.c.
References ast_rtcp::expected_prior, ast_rtcp::quality, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtcp_info, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.
Referenced by ast_rtp_get_quality().
02884 { 02885 /* 02886 *ssrc our ssrc 02887 *themssrc their ssrc 02888 *lp lost packets 02889 *rxjitter our calculated jitter(rx) 02890 *rxcount no. received packets 02891 *txjitter reported jitter of the other end 02892 *txcount transmitted packets 02893 *rlp remote lost packets 02894 *rtt round trip time 02895 */ 02896 02897 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 02898 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02899 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02900 rtp->ssrc, 02901 rtp->themssrc, 02902 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02903 rtp->rxjitter, 02904 rtp->rxcount, 02905 (double)rtp->rtcp->reported_jitter / 65536.0, 02906 rtp->txcount, 02907 rtp->rtcp->reported_lost, 02908 rtp->rtcp->rtt 02909 ); 02910 } else { 02911 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;", 02912 rtp->ssrc, 02913 rtp->themssrc, 02914 rtp->rxjitter, 02915 rtp->rxcount, 02916 rtp->txcount 02917 ); 02918 } 02919 02920 return rtp->rtcp->quality; 02921 }
static char* __ast_rtp_get_quality_jitter | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2762 of file rtp.c.
References ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtcp::normdev_rxjitter, ast_rtcp::quality_jitter, ast_rtcp::reported_maxjitter, ast_rtcp::reported_minjitter, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_stdev_jitter, ast_rtp::rtcp, ast_rtcp::rtcp_info, RTCP_JITTER_FORMAT1, RTCP_JITTER_FORMAT2, ast_rtp::rxjitter, and ast_rtcp::stdev_rxjitter.
Referenced by ast_rtp_get_quality().
02763 { 02764 /* 02765 *ssrc our ssrc 02766 *themssrc their ssrc 02767 *lp lost packets 02768 *rxjitter our calculated jitter(rx) 02769 *rxcount no. received packets 02770 *txjitter reported jitter of the other end 02771 *txcount transmitted packets 02772 *rlp remote lost packets 02773 *rtt round trip time 02774 */ 02775 #define RTCP_JITTER_FORMAT1 \ 02776 "minrxjitter=%f;" \ 02777 "maxrxjitter=%f;" \ 02778 "avgrxjitter=%f;" \ 02779 "stdevrxjitter=%f;" \ 02780 "reported_minjitter=%f;" \ 02781 "reported_maxjitter=%f;" \ 02782 "reported_avgjitter=%f;" \ 02783 "reported_stdevjitter=%f;" 02784 02785 #define RTCP_JITTER_FORMAT2 \ 02786 "rxjitter=%f;" 02787 02788 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 02789 snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1, 02790 rtp->rtcp->minrxjitter, 02791 rtp->rtcp->maxrxjitter, 02792 rtp->rtcp->normdev_rxjitter, 02793 sqrt(rtp->rtcp->stdev_rxjitter), 02794 rtp->rtcp->reported_minjitter, 02795 rtp->rtcp->reported_maxjitter, 02796 rtp->rtcp->reported_normdev_jitter, 02797 sqrt(rtp->rtcp->reported_stdev_jitter) 02798 ); 02799 } else { 02800 snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2, 02801 rtp->rxjitter 02802 ); 02803 } 02804 02805 return rtp->rtcp->quality_jitter; 02806 02807 #undef RTCP_JITTER_FORMAT1 02808 #undef RTCP_JITTER_FORMAT2 02809 }
static char* __ast_rtp_get_quality_loss | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2811 of file rtp.c.
References ast_rtp::cycles, ast_rtp::lastrxseqno, ast_rtcp::maxrxlost, ast_rtcp::minrxlost, ast_rtcp::normdev_rxlost, ast_rtcp::quality_loss, ast_rtcp::reported_maxlost, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, ast_rtcp::rtcp_info, RTCP_LOSS_FORMAT1, RTCP_LOSS_FORMAT2, ast_rtp::rxcount, ast_rtp::seedrxseqno, and ast_rtcp::stdev_rxlost.
Referenced by ast_rtp_get_quality().
02812 { 02813 unsigned int lost; 02814 unsigned int extended; 02815 unsigned int expected; 02816 int fraction; 02817 02818 #define RTCP_LOSS_FORMAT1 \ 02819 "minrxlost=%f;" \ 02820 "maxrxlost=%f;" \ 02821 "avgrxlostr=%f;" \ 02822 "stdevrxlost=%f;" \ 02823 "reported_minlost=%f;" \ 02824 "reported_maxlost=%f;" \ 02825 "reported_avglost=%f;" \ 02826 "reported_stdevlost=%f;" 02827 02828 #define RTCP_LOSS_FORMAT2 \ 02829 "lost=%d;" \ 02830 "expected=%d;" 02831 02832 if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) { 02833 snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1, 02834 rtp->rtcp->minrxlost, 02835 rtp->rtcp->maxrxlost, 02836 rtp->rtcp->normdev_rxlost, 02837 sqrt(rtp->rtcp->stdev_rxlost), 02838 rtp->rtcp->reported_minlost, 02839 rtp->rtcp->reported_maxlost, 02840 rtp->rtcp->reported_normdev_lost, 02841 sqrt(rtp->rtcp->reported_stdev_lost) 02842 ); 02843 } else { 02844 extended = rtp->cycles + rtp->lastrxseqno; 02845 expected = extended - rtp->seedrxseqno + 1; 02846 if (rtp->rxcount > expected) 02847 expected += rtp->rxcount - expected; 02848 lost = expected - rtp->rxcount; 02849 02850 if (!expected || lost <= 0) 02851 fraction = 0; 02852 else 02853 fraction = (lost << 8) / expected; 02854 02855 snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2, 02856 lost, 02857 expected 02858 ); 02859 } 02860 02861 return rtp->rtcp->quality_loss; 02862 02863 #undef RTCP_LOSS_FORMAT1 02864 #undef RTCP_LOSS_FORMAT2 02865 }
static char* __ast_rtp_get_quality_rtt | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2867 of file rtp.c.
References ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtcp::normdevrtt, ast_rtcp::quality_rtt, ast_rtp::rtcp, ast_rtcp::rtcp_info, and ast_rtcp::stdevrtt.
Referenced by ast_rtp_get_quality().
02868 { 02869 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 02870 snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;", 02871 rtp->rtcp->minrtt, 02872 rtp->rtcp->maxrtt, 02873 rtp->rtcp->normdevrtt, 02874 sqrt(rtp->rtcp->stdevrtt) 02875 ); 02876 } else { 02877 snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available"); 02878 } 02879 02880 return rtp->rtcp->quality_rtt; 02881 }
static int __ast_rtp_reload | ( | int | reload | ) | [static] |
Definition at line 4745 of file rtp.c.
References ast_config_destroy(), ast_config_load2(), ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTMF_TIMEOUT, LOG_WARNING, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and STRICT_RTP_OPEN.
Referenced by ast_rtp_init(), and ast_rtp_reload().
04746 { 04747 struct ast_config *cfg; 04748 const char *s; 04749 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04750 04751 if ((cfg = ast_config_load2("rtp.conf", "rtp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 04752 return 0; 04753 04754 rtpstart = 5000; 04755 rtpend = 31000; 04756 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04757 strictrtp = STRICT_RTP_OPEN; 04758 if (cfg) { 04759 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 04760 rtpstart = atoi(s); 04761 if (rtpstart < 1024) 04762 rtpstart = 1024; 04763 if (rtpstart > 65535) 04764 rtpstart = 65535; 04765 } 04766 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 04767 rtpend = atoi(s); 04768 if (rtpend < 1024) 04769 rtpend = 1024; 04770 if (rtpend > 65535) 04771 rtpend = 65535; 04772 } 04773 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 04774 rtcpinterval = atoi(s); 04775 if (rtcpinterval == 0) 04776 rtcpinterval = 0; /* Just so we're clear... it's zero */ 04777 if (rtcpinterval < RTCP_MIN_INTERVALMS) 04778 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 04779 if (rtcpinterval > RTCP_MAX_INTERVALMS) 04780 rtcpinterval = RTCP_MAX_INTERVALMS; 04781 } 04782 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 04783 #ifdef SO_NO_CHECK 04784 if (ast_false(s)) 04785 nochecksums = 1; 04786 else 04787 nochecksums = 0; 04788 #else 04789 if (ast_false(s)) 04790 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 04791 #endif 04792 } 04793 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 04794 dtmftimeout = atoi(s); 04795 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 04796 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 04797 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 04798 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04799 }; 04800 } 04801 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) { 04802 strictrtp = ast_true(s); 04803 } 04804 ast_config_destroy(cfg); 04805 } 04806 if (rtpstart >= rtpend) { 04807 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 04808 rtpstart = 5000; 04809 rtpend = 31000; 04810 } 04811 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 04812 return 0; 04813 }
static void append_attr_address | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
struct sockaddr_in * | sock_in, | |||
int * | len, | |||
int * | left | |||
) | [static] |
append an address to an STUN message
Definition at line 463 of file rtp.c.
References stun_addr::addr.
Referenced by stun_handle_packet().
00464 { 00465 int size = sizeof(**attr) + 8; 00466 struct stun_addr *addr; 00467 if (*left > size) { 00468 (*attr)->attr = htons(attrval); 00469 (*attr)->len = htons(8); 00470 addr = (struct stun_addr *)((*attr)->value); 00471 addr->unused = 0; 00472 addr->family = 0x01; 00473 addr->port = sock_in->sin_port; 00474 addr->addr = sock_in->sin_addr.s_addr; 00475 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00476 *len += size; 00477 *left -= size; 00478 } 00479 }
static void append_attr_string | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
const char * | s, | |||
int * | len, | |||
int * | left | |||
) | [static] |
append a string to an STUN message
Definition at line 449 of file rtp.c.
Referenced by ast_stun_request(), and stun_handle_packet().
00450 { 00451 int size = sizeof(**attr) + strlen(s); 00452 if (*left > size) { 00453 (*attr)->attr = htons(attrval); 00454 (*attr)->len = htons(strlen(s)); 00455 memcpy((*attr)->value, s, strlen(s)); 00456 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00457 *len += size; 00458 *left -= size; 00459 } 00460 }
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 732 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00733 { 00734 unsigned int interval; 00735 /*! \todo XXX Do a more reasonable calculation on this one 00736 * Look in RFC 3550 Section A.7 for an example*/ 00737 interval = rtcpinterval; 00738 return interval; 00739 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 725 of file rtp.c.
References ast_rtp::rtcp, and ast_rtcp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), jingle_new(), sip_new(), start_rtp(), and unistim_new().
static struct ast_rtcp* ast_rtcp_new | ( | void | ) | [static] |
Initialize a new RTCP session.
Definition at line 2409 of file rtp.c.
References ast_calloc, ast_free, rtp_socket(), and ast_rtcp::s.
Referenced by ast_rtp_new_with_bindaddr().
02410 { 02411 struct ast_rtcp *rtcp; 02412 02413 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 02414 return NULL; 02415 rtcp->s = rtp_socket("RTCP"); 02416 rtcp->us.sin_family = AF_INET; 02417 rtcp->them.sin_family = AF_INET; 02418 rtcp->schedid = -1; 02419 02420 if (rtcp->s < 0) { 02421 ast_free(rtcp); 02422 return NULL; 02423 } 02424 02425 return rtcp; 02426 }
Definition at line 1130 of file rtp.c.
References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose, ast_frame::datalen, errno, EVENT_FLAG_REPORTING, f, ast_rtp::f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, normdev_compute(), ast_rtcp::normdevrtt, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_jitter_count, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtcp_info, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, stddev_compute(), ast_rtcp::stdevrtt, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().
Referenced by oh323_read(), sip_rtp_read(), skinny_rtp_read(), and unistim_rtp_read().
01131 { 01132 socklen_t len; 01133 int position, i, packetwords; 01134 int res; 01135 struct sockaddr_in sock_in; 01136 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 01137 unsigned int *rtcpheader; 01138 int pt; 01139 struct timeval now; 01140 unsigned int length; 01141 int rc; 01142 double rttsec; 01143 uint64_t rtt = 0; 01144 unsigned int dlsr; 01145 unsigned int lsr; 01146 unsigned int msw; 01147 unsigned int lsw; 01148 unsigned int comp; 01149 struct ast_frame *f = &ast_null_frame; 01150 01151 double reported_jitter; 01152 double reported_normdev_jitter_current; 01153 double normdevrtt_current; 01154 double reported_lost; 01155 double reported_normdev_lost_current; 01156 01157 if (!rtp || !rtp->rtcp) 01158 return &ast_null_frame; 01159 01160 len = sizeof(sock_in); 01161 01162 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 01163 0, (struct sockaddr *)&sock_in, &len); 01164 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 01165 01166 if (res < 0) { 01167 ast_assert(errno != EBADF); 01168 if (errno != EAGAIN) { 01169 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 01170 return NULL; 01171 } 01172 return &ast_null_frame; 01173 } 01174 01175 packetwords = res / 4; 01176 01177 if (rtp->nat) { 01178 /* Send to whoever sent to us */ 01179 if ((rtp->rtcp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01180 (rtp->rtcp->them.sin_port != sock_in.sin_port)) { 01181 memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them)); 01182 if (option_debug || rtpdebug) 01183 ast_debug(0, "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)); 01184 } 01185 } 01186 01187 ast_debug(1, "Got RTCP report of %d bytes\n", res); 01188 01189 /* Process a compound packet */ 01190 position = 0; 01191 while (position < packetwords) { 01192 i = position; 01193 length = ntohl(rtcpheader[i]); 01194 pt = (length & 0xff0000) >> 16; 01195 rc = (length & 0x1f000000) >> 24; 01196 length &= 0xffff; 01197 01198 if ((i + length) > packetwords) { 01199 if (option_debug || rtpdebug) 01200 ast_log(LOG_DEBUG, "RTCP Read too short\n"); 01201 return &ast_null_frame; 01202 } 01203 01204 if (rtcp_debug_test_addr(&sock_in)) { 01205 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port)); 01206 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 01207 ast_verbose("Reception reports: %d\n", rc); 01208 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 01209 } 01210 01211 i += 2; /* Advance past header and ssrc */ 01212 01213 switch (pt) { 01214 case RTCP_PT_SR: 01215 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 01216 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 01217 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 01218 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 01219 01220 if (rtcp_debug_test_addr(&sock_in)) { 01221 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 01222 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 01223 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 01224 } 01225 i += 5; 01226 if (rc < 1) 01227 break; 01228 /* Intentional fall through */ 01229 case RTCP_PT_RR: 01230 /* Don't handle multiple reception reports (rc > 1) yet */ 01231 /* Calculate RTT per RFC */ 01232 gettimeofday(&now, NULL); 01233 timeval2ntp(now, &msw, &lsw); 01234 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 01235 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 01236 lsr = ntohl(rtcpheader[i + 4]); 01237 dlsr = ntohl(rtcpheader[i + 5]); 01238 rtt = comp - lsr - dlsr; 01239 01240 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 01241 sess->ee_delay = (eedelay * 1000) / 65536; */ 01242 if (rtt < 4294) { 01243 rtt = (rtt * 1000000) >> 16; 01244 } else { 01245 rtt = (rtt * 1000) >> 16; 01246 rtt *= 1000; 01247 } 01248 rtt = rtt / 1000.; 01249 rttsec = rtt / 1000.; 01250 rtp->rtcp->rtt = rttsec; 01251 01252 if (comp - dlsr >= lsr) { 01253 rtp->rtcp->accumulated_transit += rttsec; 01254 01255 if (rtp->rtcp->rtt_count == 0) 01256 rtp->rtcp->minrtt = rttsec; 01257 01258 if (rtp->rtcp->maxrtt<rttsec) 01259 rtp->rtcp->maxrtt = rttsec; 01260 01261 if (rtp->rtcp->minrtt>rttsec) 01262 rtp->rtcp->minrtt = rttsec; 01263 01264 normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count); 01265 01266 rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count); 01267 01268 rtp->rtcp->normdevrtt = normdevrtt_current; 01269 01270 rtp->rtcp->rtt_count++; 01271 } else if (rtcp_debug_test_addr(&sock_in)) { 01272 ast_verbose("Internal RTCP NTP clock skew detected: " 01273 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 01274 "diff=%d\n", 01275 lsr, comp, dlsr, dlsr / 65536, 01276 (dlsr % 65536) * 1000 / 65536, 01277 dlsr - (comp - lsr)); 01278 } 01279 } 01280 01281 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 01282 reported_jitter = (double) rtp->rtcp->reported_jitter; 01283 01284 if (rtp->rtcp->reported_jitter_count == 0) 01285 rtp->rtcp->reported_minjitter = reported_jitter; 01286 01287 if (reported_jitter < rtp->rtcp->reported_minjitter) 01288 rtp->rtcp->reported_minjitter = reported_jitter; 01289 01290 if (reported_jitter > rtp->rtcp->reported_maxjitter) 01291 rtp->rtcp->reported_maxjitter = reported_jitter; 01292 01293 reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count); 01294 01295 rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count); 01296 01297 rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current; 01298 01299 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 01300 01301 reported_lost = (double) rtp->rtcp->reported_lost; 01302 01303 /* using same counter as for jitter */ 01304 if (rtp->rtcp->reported_jitter_count == 0) 01305 rtp->rtcp->reported_minlost = reported_lost; 01306 01307 if (reported_lost < rtp->rtcp->reported_minlost) 01308 rtp->rtcp->reported_minlost = reported_lost; 01309 01310 if (reported_lost > rtp->rtcp->reported_maxlost) 01311 rtp->rtcp->reported_maxlost = reported_lost; 01312 01313 reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count); 01314 01315 rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count); 01316 01317 rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current; 01318 01319 rtp->rtcp->reported_jitter_count++; 01320 01321 if (rtcp_debug_test_addr(&sock_in)) { 01322 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 01323 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 01324 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 01325 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 01326 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 01327 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 01328 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 01329 if (rtt) 01330 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 01331 } 01332 01333 if (rtt) { 01334 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n" 01335 "PT: %d(%s)\r\n" 01336 "ReceptionReports: %d\r\n" 01337 "SenderSSRC: %u\r\n" 01338 "FractionLost: %ld\r\n" 01339 "PacketsLost: %d\r\n" 01340 "HighestSequence: %ld\r\n" 01341 "SequenceNumberCycles: %ld\r\n" 01342 "IAJitter: %u\r\n" 01343 "LastSR: %lu.%010lu\r\n" 01344 "DLSR: %4.4f(sec)\r\n" 01345 "RTT: %llu(sec)\r\n", 01346 ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), 01347 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01348 rc, 01349 rtcpheader[i + 1], 01350 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01351 rtp->rtcp->reported_lost, 01352 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01353 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01354 rtp->rtcp->reported_jitter, 01355 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01356 ntohl(rtcpheader[i + 5])/65536.0, 01357 (unsigned long long)rtt); 01358 } else { 01359 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n" 01360 "PT: %d(%s)\r\n" 01361 "ReceptionReports: %d\r\n" 01362 "SenderSSRC: %u\r\n" 01363 "FractionLost: %ld\r\n" 01364 "PacketsLost: %d\r\n" 01365 "HighestSequence: %ld\r\n" 01366 "SequenceNumberCycles: %ld\r\n" 01367 "IAJitter: %u\r\n" 01368 "LastSR: %lu.%010lu\r\n" 01369 "DLSR: %4.4f(sec)\r\n", 01370 ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), 01371 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01372 rc, 01373 rtcpheader[i + 1], 01374 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01375 rtp->rtcp->reported_lost, 01376 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01377 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01378 rtp->rtcp->reported_jitter, 01379 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, 01380 ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01381 ntohl(rtcpheader[i + 5])/65536.0); 01382 } 01383 break; 01384 case RTCP_PT_FUR: 01385 if (rtcp_debug_test_addr(&sock_in)) 01386 ast_verbose("Received an RTCP Fast Update Request\n"); 01387 rtp->f.frametype = AST_FRAME_CONTROL; 01388 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 01389 rtp->f.datalen = 0; 01390 rtp->f.samples = 0; 01391 rtp->f.mallocd = 0; 01392 rtp->f.src = "RTP"; 01393 f = &rtp->f; 01394 break; 01395 case RTCP_PT_SDES: 01396 if (rtcp_debug_test_addr(&sock_in)) 01397 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01398 break; 01399 case RTCP_PT_BYE: 01400 if (rtcp_debug_test_addr(&sock_in)) 01401 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01402 break; 01403 default: 01404 ast_debug(1, "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)); 01405 break; 01406 } 01407 position += (length + 1); 01408 } 01409 rtp->rtcp->rtcp_info = 1; 01410 return f; 01411 }
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 3195 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
03196 { 03197 struct ast_rtp *rtp = data; 03198 int res; 03199 03200 rtp->rtcp->sendfur = 1; 03201 res = ast_rtcp_write(data); 03202 03203 return res; 03204 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 3453 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().
03454 { 03455 struct ast_rtp *rtp = (struct ast_rtp *)data; 03456 int res; 03457 03458 if (!rtp || !rtp->rtcp) 03459 return 0; 03460 03461 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 03462 res = ast_rtcp_write_sr(data); 03463 else 03464 res = ast_rtcp_write_rr(data); 03465 03466 return res; 03467 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recipient's report.
Definition at line 3340 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose, ast_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, len(), LOG_ERROR, ast_rtcp::maxrxlost, ast_rtcp::minrxlost, normdev_compute(), ast_rtcp::normdev_rxlost, 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::rxlost, ast_rtcp::rxlost_count, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtp::ssrc, stddev_compute(), ast_rtcp::stdev_rxlost, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, and timersub().
Referenced by ast_rtcp_write().
03341 { 03342 struct ast_rtp *rtp = (struct ast_rtp *)data; 03343 int res; 03344 int len = 32; 03345 unsigned int lost; 03346 unsigned int extended; 03347 unsigned int expected; 03348 unsigned int expected_interval; 03349 unsigned int received_interval; 03350 int lost_interval; 03351 struct timeval now; 03352 unsigned int *rtcpheader; 03353 char bdata[1024]; 03354 struct timeval dlsr; 03355 int fraction; 03356 03357 double rxlost_current; 03358 03359 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 03360 return 0; 03361 03362 if (!rtp->rtcp->them.sin_addr.s_addr) { 03363 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 03364 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03365 return 0; 03366 } 03367 03368 extended = rtp->cycles + rtp->lastrxseqno; 03369 expected = extended - rtp->seedrxseqno + 1; 03370 lost = expected - rtp->rxcount; 03371 expected_interval = expected - rtp->rtcp->expected_prior; 03372 rtp->rtcp->expected_prior = expected; 03373 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 03374 rtp->rtcp->received_prior = rtp->rxcount; 03375 lost_interval = expected_interval - received_interval; 03376 03377 if (lost_interval <= 0) 03378 rtp->rtcp->rxlost = 0; 03379 else rtp->rtcp->rxlost = rtp->rtcp->rxlost; 03380 if (rtp->rtcp->rxlost_count == 0) 03381 rtp->rtcp->minrxlost = rtp->rtcp->rxlost; 03382 if (lost_interval < rtp->rtcp->minrxlost) 03383 rtp->rtcp->minrxlost = rtp->rtcp->rxlost; 03384 if (lost_interval > rtp->rtcp->maxrxlost) 03385 rtp->rtcp->maxrxlost = rtp->rtcp->rxlost; 03386 03387 rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count); 03388 rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count); 03389 rtp->rtcp->normdev_rxlost = rxlost_current; 03390 rtp->rtcp->rxlost_count++; 03391 03392 if (expected_interval == 0 || lost_interval <= 0) 03393 fraction = 0; 03394 else 03395 fraction = (lost_interval << 8) / expected_interval; 03396 gettimeofday(&now, NULL); 03397 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 03398 rtcpheader = (unsigned int *)bdata; 03399 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 03400 rtcpheader[1] = htonl(rtp->ssrc); 03401 rtcpheader[2] = htonl(rtp->themssrc); 03402 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 03403 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 03404 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 03405 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 03406 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 03407 03408 if (rtp->rtcp->sendfur) { 03409 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 03410 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 03411 len += 8; 03412 rtp->rtcp->sendfur = 0; 03413 } 03414 03415 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 03416 it can change mid call, and SDES can't) */ 03417 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 03418 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 03419 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 03420 len += 12; 03421 03422 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 03423 03424 if (res < 0) { 03425 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 03426 /* Remove the scheduler */ 03427 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03428 return 0; 03429 } 03430 03431 rtp->rtcp->rr_count++; 03432 03433 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 03434 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 03435 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 03436 " IA jitter: %.4f\n" 03437 " Their last SR: %u\n" 03438 " DLSR: %4.4f (sec)\n\n", 03439 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 03440 ntohs(rtp->rtcp->them.sin_port), 03441 rtp->ssrc, rtp->themssrc, fraction, lost, 03442 rtp->rxjitter, 03443 rtp->rtcp->themrxlsr, 03444 (double)(ntohl(rtcpheader[7])/65536.0)); 03445 } 03446 03447 return res; 03448 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 3207 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose, ast_rtp::cycles, errno, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len(), LOG_ERROR, manager_event, 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, timersub(), timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.
Referenced by ast_rtcp_write().
03208 { 03209 struct ast_rtp *rtp = (struct ast_rtp *)data; 03210 int res; 03211 int len = 0; 03212 struct timeval now; 03213 unsigned int now_lsw; 03214 unsigned int now_msw; 03215 unsigned int *rtcpheader; 03216 unsigned int lost; 03217 unsigned int extended; 03218 unsigned int expected; 03219 unsigned int expected_interval; 03220 unsigned int received_interval; 03221 int lost_interval; 03222 int fraction; 03223 struct timeval dlsr; 03224 char bdata[512]; 03225 03226 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 03227 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 03228 return 0; 03229 03230 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 03231 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 03232 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03233 return 0; 03234 } 03235 03236 gettimeofday(&now, NULL); 03237 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 03238 rtcpheader = (unsigned int *)bdata; 03239 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 03240 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 03241 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 03242 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 03243 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 03244 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 03245 len += 28; 03246 03247 extended = rtp->cycles + rtp->lastrxseqno; 03248 expected = extended - rtp->seedrxseqno + 1; 03249 if (rtp->rxcount > expected) 03250 expected += rtp->rxcount - expected; 03251 lost = expected - rtp->rxcount; 03252 expected_interval = expected - rtp->rtcp->expected_prior; 03253 rtp->rtcp->expected_prior = expected; 03254 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 03255 rtp->rtcp->received_prior = rtp->rxcount; 03256 lost_interval = expected_interval - received_interval; 03257 if (expected_interval == 0 || lost_interval <= 0) 03258 fraction = 0; 03259 else 03260 fraction = (lost_interval << 8) / expected_interval; 03261 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 03262 rtcpheader[7] = htonl(rtp->themssrc); 03263 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 03264 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 03265 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 03266 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 03267 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 03268 len += 24; 03269 03270 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 03271 03272 if (rtp->rtcp->sendfur) { 03273 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 03274 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 03275 len += 8; 03276 rtp->rtcp->sendfur = 0; 03277 } 03278 03279 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 03280 /* it can change mid call, and SDES can't) */ 03281 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 03282 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 03283 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 03284 len += 12; 03285 03286 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 03287 if (res < 0) { 03288 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)); 03289 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03290 return 0; 03291 } 03292 03293 /* FIXME Don't need to get a new one */ 03294 gettimeofday(&rtp->rtcp->txlsr, NULL); 03295 rtp->rtcp->sr_count++; 03296 03297 rtp->rtcp->lastsrtxcount = rtp->txcount; 03298 03299 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 03300 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 03301 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 03302 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 03303 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 03304 ast_verbose(" Sent packets: %u\n", rtp->txcount); 03305 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 03306 ast_verbose(" Report block:\n"); 03307 ast_verbose(" Fraction lost: %u\n", fraction); 03308 ast_verbose(" Cumulative loss: %u\n", lost); 03309 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 03310 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 03311 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 03312 } 03313 manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n" 03314 "OurSSRC: %u\r\n" 03315 "SentNTP: %u.%010u\r\n" 03316 "SentRTP: %u\r\n" 03317 "SentPackets: %u\r\n" 03318 "SentOctets: %u\r\n" 03319 "ReportBlock:\r\n" 03320 "FractionLost: %u\r\n" 03321 "CumulativeLoss: %u\r\n" 03322 "IAJitter: %.4f\r\n" 03323 "TheirLastSR: %u\r\n" 03324 "DLSR: %4.4f (sec)\r\n", 03325 ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), 03326 rtp->ssrc, 03327 (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096, 03328 rtp->lastts, 03329 rtp->txcount, 03330 rtp->txoctetcount, 03331 fraction, 03332 lost, 03333 rtp->rxjitter, 03334 rtp->rtcp->themrxlsr, 03335 (double)(ntohl(rtcpheader[12])/65536.0)); 03336 return res; 03337 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 496 of file rtp.c.
Referenced by process_sdp().
00497 { 00498 return sizeof(struct ast_rtp); 00499 }
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 | |||
) |
The RTP bridge.
Definition at line 4282 of file rtp.c.
References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_debug, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verb, bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_channel::name, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, and ast_channel::tech_pvt.
04283 { 04284 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 04285 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 04286 struct ast_rtp *tp0 = NULL, *tp1 = NULL; /* Text RTP channels */ 04287 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 04288 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED, text_p0_res = AST_RTP_GET_FAILED; 04289 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED, text_p1_res = AST_RTP_GET_FAILED; 04290 enum ast_bridge_result res = AST_BRIDGE_FAILED; 04291 int codec0 = 0, codec1 = 0; 04292 void *pvt0 = NULL, *pvt1 = NULL; 04293 04294 /* Lock channels */ 04295 ast_channel_lock(c0); 04296 while (ast_channel_trylock(c1)) { 04297 ast_channel_unlock(c0); 04298 usleep(1); 04299 ast_channel_lock(c0); 04300 } 04301 04302 /* Ensure neither channel got hungup during lock avoidance */ 04303 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 04304 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 04305 ast_channel_unlock(c0); 04306 ast_channel_unlock(c1); 04307 return AST_BRIDGE_FAILED; 04308 } 04309 04310 /* Find channel driver interfaces */ 04311 if (!(pr0 = get_proto(c0))) { 04312 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 04313 ast_channel_unlock(c0); 04314 ast_channel_unlock(c1); 04315 return AST_BRIDGE_FAILED; 04316 } 04317 if (!(pr1 = get_proto(c1))) { 04318 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 04319 ast_channel_unlock(c0); 04320 ast_channel_unlock(c1); 04321 return AST_BRIDGE_FAILED; 04322 } 04323 04324 /* Get channel specific interface structures */ 04325 pvt0 = c0->tech_pvt; 04326 pvt1 = c1->tech_pvt; 04327 04328 /* Get audio and video interface (if native bridge is possible) */ 04329 audio_p0_res = pr0->get_rtp_info(c0, &p0); 04330 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 04331 text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 04332 audio_p1_res = pr1->get_rtp_info(c1, &p1); 04333 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 04334 text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 04335 04336 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 04337 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 04338 audio_p0_res = AST_RTP_GET_FAILED; 04339 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 04340 audio_p1_res = AST_RTP_GET_FAILED; 04341 04342 /* Check if a bridge is possible (partial/native) */ 04343 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 04344 /* Somebody doesn't want to play... */ 04345 ast_channel_unlock(c0); 04346 ast_channel_unlock(c1); 04347 return AST_BRIDGE_FAILED_NOWARN; 04348 } 04349 04350 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 04351 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 04352 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 04353 audio_p0_res = AST_RTP_TRY_PARTIAL; 04354 } 04355 04356 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 04357 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 04358 audio_p1_res = AST_RTP_TRY_PARTIAL; 04359 } 04360 04361 /* If both sides are not using the same method of DTMF transmission 04362 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 04363 * -------------------------------------------------- 04364 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 04365 * |-----------|------------|-----------------------| 04366 * | Inband | False | True | 04367 * | RFC2833 | True | True | 04368 * | SIP INFO | False | False | 04369 * -------------------------------------------------- 04370 * However, if DTMF from both channels is being monitored by the core, then 04371 * we can still do packet-to-packet bridging, because passing through the 04372 * core will handle DTMF mode translation. 04373 */ 04374 if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 04375 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 04376 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 04377 ast_channel_unlock(c0); 04378 ast_channel_unlock(c1); 04379 return AST_BRIDGE_FAILED_NOWARN; 04380 } 04381 audio_p0_res = AST_RTP_TRY_PARTIAL; 04382 audio_p1_res = AST_RTP_TRY_PARTIAL; 04383 } 04384 04385 /* If we need to feed frames into the core don't do a P2P bridge */ 04386 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 04387 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 04388 ast_channel_unlock(c0); 04389 ast_channel_unlock(c1); 04390 return AST_BRIDGE_FAILED_NOWARN; 04391 } 04392 04393 /* Get codecs from both sides */ 04394 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 04395 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 04396 if (codec0 && codec1 && !(codec0 & codec1)) { 04397 /* Hey, we can't do native bridging if both parties speak different codecs */ 04398 ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 04399 ast_channel_unlock(c0); 04400 ast_channel_unlock(c1); 04401 return AST_BRIDGE_FAILED_NOWARN; 04402 } 04403 04404 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 04405 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 04406 struct ast_format_list fmt0, fmt1; 04407 04408 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 04409 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 04410 ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n"); 04411 ast_channel_unlock(c0); 04412 ast_channel_unlock(c1); 04413 return AST_BRIDGE_FAILED_NOWARN; 04414 } 04415 /* They must also be using the same packetization */ 04416 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 04417 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 04418 if (fmt0.cur_ms != fmt1.cur_ms) { 04419 ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n"); 04420 ast_channel_unlock(c0); 04421 ast_channel_unlock(c1); 04422 return AST_BRIDGE_FAILED_NOWARN; 04423 } 04424 04425 ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 04426 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 04427 } else { 04428 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04429 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 04430 } 04431 04432 return res; 04433 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
get format from predefined dynamic payload format
Definition at line 3670 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp().
03671 { 03672 if (pt < 0 || pt > MAX_RTP_PT) 03673 return 0; /* bogus payload type */ 03674 03675 if (static_RTP_PT[pt].isAstFormat) 03676 return static_RTP_PT[pt].code; 03677 else 03678 return 0; 03679 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Get codec preference.
Definition at line 3665 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
03666 { 03667 return &rtp->pref; 03668 }
void ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Set codec preference.
Definition at line 3619 of file rtp.c.
References ast_codec_pref_getsize(), ast_log(), ast_smoother_new(), ast_smoother_reconfigure(), ast_smoother_set_flags(), ast_format_list::cur_ms, ast_format_list::flags, ast_format_list::fr_len, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, option_debug, ast_rtp::pref, prefs, and ast_rtp::smoother.
Referenced by __oh323_rtp_create(), check_peer_ok(), create_addr_from_peer(), gtalk_new(), jingle_new(), process_sdp(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().
03620 { 03621 struct ast_format_list current_format_old, current_format_new; 03622 03623 /* if no packets have been sent through this session yet, then 03624 * changing preferences does not require any extra work 03625 */ 03626 if (rtp->lasttxformat == 0) { 03627 rtp->pref = *prefs; 03628 return; 03629 } 03630 03631 current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 03632 03633 rtp->pref = *prefs; 03634 03635 current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 03636 03637 /* if the framing desired for the current format has changed, we may have to create 03638 * or adjust the smoother for this session 03639 */ 03640 if ((current_format_new.inc_ms != 0) && 03641 (current_format_new.cur_ms != current_format_old.cur_ms)) { 03642 int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms; 03643 03644 if (rtp->smoother) { 03645 ast_smoother_reconfigure(rtp->smoother, new_size); 03646 if (option_debug) { 03647 ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size); 03648 } 03649 } else { 03650 if (!(rtp->smoother = ast_smoother_new(new_size))) { 03651 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 03652 return; 03653 } 03654 if (current_format_new.flags) { 03655 ast_smoother_set_flags(rtp->smoother, current_format_new.flags); 03656 } 03657 if (option_debug) { 03658 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 03659 } 03660 } 03661 } 03662 03663 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Destroy RTP session
Definition at line 2954 of file rtp.c.
References ast_free, ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::io, ast_rtp::ioid, manager_event, 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_peer_ok(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), jingle_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), unalloc_sub(), and unistim_hangup().
02955 { 02956 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02957 /*Print some info on the call here */ 02958 ast_verbose(" RTP-stats\n"); 02959 ast_verbose("* Our Receiver:\n"); 02960 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02961 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02962 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0); 02963 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02964 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02965 ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0); 02966 ast_verbose("* Our Sender:\n"); 02967 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02968 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02969 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0); 02970 ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0); 02971 ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0); 02972 ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0); 02973 } 02974 02975 manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n" 02976 "ReceivedPackets: %u\r\n" 02977 "LostPackets: %u\r\n" 02978 "Jitter: %.4f\r\n" 02979 "Transit: %.4f\r\n" 02980 "RRCount: %u\r\n", 02981 rtp->themssrc, 02982 rtp->rxcount, 02983 rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0, 02984 rtp->rxjitter, 02985 rtp->rxtransit, 02986 rtp->rtcp ? rtp->rtcp->rr_count : 0); 02987 manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n" 02988 "SentPackets: %u\r\n" 02989 "LostPackets: %u\r\n" 02990 "Jitter: %u\r\n" 02991 "SRCount: %u\r\n" 02992 "RTT: %f\r\n", 02993 rtp->ssrc, 02994 rtp->txcount, 02995 rtp->rtcp ? rtp->rtcp->reported_lost : 0, 02996 rtp->rtcp ? rtp->rtcp->reported_jitter : 0, 02997 rtp->rtcp ? rtp->rtcp->sr_count : 0, 02998 rtp->rtcp ? rtp->rtcp->rtt : 0); 02999 if (rtp->smoother) 03000 ast_smoother_free(rtp->smoother); 03001 if (rtp->ioid) 03002 ast_io_remove(rtp->io, rtp->ioid); 03003 if (rtp->s > -1) 03004 close(rtp->s); 03005 if (rtp->rtcp) { 03006 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03007 close(rtp->rtcp->s); 03008 ast_free(rtp->rtcp); 03009 rtp->rtcp=NULL; 03010 } 03011 #ifdef P2P_INTENSE 03012 ast_mutex_destroy(&rtp->bridge_lock); 03013 #endif 03014 ast_free(rtp); 03015 }
int ast_rtp_early_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
If possible, create an early bridge directly between the devices without having to send a re-invite later.
Definition at line 2023 of file rtp.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, 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_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_channel::name, and ast_rtp_protocol::set_rtp_peer.
02024 { 02025 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 02026 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 02027 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 02028 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 02029 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED; 02030 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED; 02031 int srccodec, destcodec, nat_active = 0; 02032 02033 /* Lock channels */ 02034 ast_channel_lock(c0); 02035 if (c1) { 02036 while (ast_channel_trylock(c1)) { 02037 ast_channel_unlock(c0); 02038 usleep(1); 02039 ast_channel_lock(c0); 02040 } 02041 } 02042 02043 /* Find channel driver interfaces */ 02044 destpr = get_proto(c0); 02045 if (c1) 02046 srcpr = get_proto(c1); 02047 if (!destpr) { 02048 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name); 02049 ast_channel_unlock(c0); 02050 if (c1) 02051 ast_channel_unlock(c1); 02052 return -1; 02053 } 02054 if (!srcpr) { 02055 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>"); 02056 ast_channel_unlock(c0); 02057 if (c1) 02058 ast_channel_unlock(c1); 02059 return -1; 02060 } 02061 02062 /* Get audio, video and text interface (if native bridge is possible) */ 02063 audio_dest_res = destpr->get_rtp_info(c0, &destp); 02064 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED; 02065 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED; 02066 if (srcpr) { 02067 audio_src_res = srcpr->get_rtp_info(c1, &srcp); 02068 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED; 02069 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED; 02070 } 02071 02072 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 02073 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) { 02074 /* Somebody doesn't want to play... */ 02075 ast_channel_unlock(c0); 02076 if (c1) 02077 ast_channel_unlock(c1); 02078 return -1; 02079 } 02080 if (audio_src_res == AST_RTP_TRY_NATIVE && (video_src_res == AST_RTP_GET_FAILED || video_src_res == AST_RTP_TRY_NATIVE) && srcpr->get_codec) 02081 srccodec = srcpr->get_codec(c1); 02082 else 02083 srccodec = 0; 02084 if (audio_dest_res == AST_RTP_TRY_NATIVE && (video_dest_res == AST_RTP_GET_FAILED || video_dest_res == AST_RTP_TRY_NATIVE) && destpr->get_codec) 02085 destcodec = destpr->get_codec(c0); 02086 else 02087 destcodec = 0; 02088 /* Ensure we have at least one matching codec */ 02089 if (srcp && !(srccodec & destcodec)) { 02090 ast_channel_unlock(c0); 02091 ast_channel_unlock(c1); 02092 return 0; 02093 } 02094 /* Consider empty media as non-existent */ 02095 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 02096 srcp = NULL; 02097 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02098 nat_active = 1; 02099 /* Bridge media early */ 02100 if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active)) 02101 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 02102 ast_channel_unlock(c0); 02103 if (c1) 02104 ast_channel_unlock(c1); 02105 ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 02106 return 0; 02107 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 720 of file rtp.c.
References ast_rtp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), jingle_new(), mgcp_new(), p2p_callback_disable(), sip_new(), skinny_new(), start_rtp(), and unistim_new().
00721 { 00722 return rtp->s; 00723 }
Definition at line 2595 of file rtp.c.
References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().
Referenced by __sip_destroy(), ast_rtp_read(), and dialog_needdestroy().
02596 { 02597 struct ast_rtp *bridged = NULL; 02598 02599 rtp_bridge_lock(rtp); 02600 bridged = rtp->bridged; 02601 rtp_bridge_unlock(rtp); 02602 02603 return bridged; 02604 }
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 2245 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and rtp_bridge_lock().
Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().
02247 { 02248 int pt; 02249 02250 rtp_bridge_lock(rtp); 02251 02252 *astFormats = *nonAstFormats = 0; 02253 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02254 if (rtp->current_RTP_PT[pt].isAstFormat) { 02255 *astFormats |= rtp->current_RTP_PT[pt].code; 02256 } else { 02257 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 02258 } 02259 } 02260 02261 rtp_bridge_unlock(rtp); 02262 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2577 of file rtp.c.
References ast_rtp::them.
Referenced by acf_channel_read(), add_sdp(), bridge_native_loop(), check_rtp_timeout(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), skinny_set_rtp_peer(), and transmit_modify_with_sdp().
02578 { 02579 if ((them->sin_family != AF_INET) || 02580 (them->sin_port != rtp->them.sin_port) || 02581 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02582 them->sin_family = AF_INET; 02583 them->sin_port = rtp->them.sin_port; 02584 them->sin_addr = rtp->them.sin_addr; 02585 return 1; 02586 } 02587 return 0; 02588 }
int ast_rtp_get_qos | ( | struct ast_rtp * | rtp, | |
const char * | qos, | |||
char * | buf, | |||
unsigned int | buflen | |||
) |
Get QOS stats on a RTP channel.
Definition at line 2716 of file rtp.c.
References __ast_rtp_get_qos().
Referenced by acf_channel_read().
02717 { 02718 double value; 02719 int found; 02720 02721 value = __ast_rtp_get_qos(rtp, qos, &found); 02722 02723 if (!found) 02724 return -1; 02725 02726 snprintf(buf, buflen, "%.0lf", value); 02727 02728 return 0; 02729 }
unsigned int ast_rtp_get_qosvalue | ( | struct ast_rtp * | rtp, | |
enum ast_rtp_qos_vars | value | |||
) |
Return RTP and RTCP QoS values.
Get QoS values from RTP and RTCP data (used in "sip show channelstats")
Definition at line 2650 of file rtp.c.
References ast_log(), AST_RTP_RTT, AST_RTP_RXCOUNT, AST_RTP_RXJITTER, AST_RTP_RXPLOSS, AST_RTP_TXCOUNT, AST_RTP_TXJITTER, AST_RTP_TXPLOSS, ast_rtcp::expected_prior, LOG_DEBUG, option_debug, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, and ast_rtp::txcount.
Referenced by show_chanstats_cb().
02651 { 02652 if (rtp == NULL) { 02653 if (option_debug > 1) 02654 ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n"); 02655 return 0; 02656 } 02657 if (option_debug > 1 && rtp->rtcp == NULL) { 02658 ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n"); 02659 } 02660 02661 switch (value) { 02662 case AST_RTP_TXCOUNT: 02663 return (unsigned int) rtp->txcount; 02664 case AST_RTP_RXCOUNT: 02665 return (unsigned int) rtp->rxcount; 02666 case AST_RTP_TXJITTER: 02667 return (unsigned int) (rtp->rxjitter * 100.0); 02668 case AST_RTP_RXJITTER: 02669 return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0); 02670 case AST_RTP_RXPLOSS: 02671 return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0; 02672 case AST_RTP_TXPLOSS: 02673 return rtp->rtcp ? rtp->rtcp->reported_lost : 0; 02674 case AST_RTP_RTT: 02675 return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0); 02676 } 02677 return 0; /* To make the compiler happy */ 02678 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual, | |||
enum ast_rtp_quality_type | qtype | |||
) |
Return RTCP quality string.
rtp | An rtp structure to get qos information about. | |
qual | An (optional) rtp quality structure that will be filled with the quality information described in the ast_rtp_quality structure. This structure is not dependent on any qtype, so a call for any type of information would yield the same results because ast_rtp_quality is not a data type specific to any qos type. | |
qtype | The quality type you'd like, default should be RTPQOS_SUMMARY which returns basic information about the call. The return from RTPQOS_SUMMARY is basically ast_rtp_quality in a string. The other types are RTPQOS_JITTER, RTPQOS_LOSS and RTPQOS_RTT which will return more specific statistics. |
Definition at line 2923 of file rtp.c.
References __ast_rtp_get_quality(), __ast_rtp_get_quality_jitter(), __ast_rtp_get_quality_loss(), __ast_rtp_get_quality_rtt(), 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::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, RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, RTPQOS_SUMMARY, 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(), ast_rtp_set_vars(), handle_request_bye(), and sip_hangup().
02924 { 02925 if (qual && rtp) { 02926 qual->local_ssrc = rtp->ssrc; 02927 qual->local_jitter = rtp->rxjitter; 02928 qual->local_count = rtp->rxcount; 02929 qual->remote_ssrc = rtp->themssrc; 02930 qual->remote_count = rtp->txcount; 02931 02932 if (rtp->rtcp) { 02933 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02934 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02935 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02936 qual->rtt = rtp->rtcp->rtt; 02937 } 02938 } 02939 02940 switch (qtype) { 02941 case RTPQOS_SUMMARY: 02942 return __ast_rtp_get_quality(rtp); 02943 case RTPQOS_JITTER: 02944 return __ast_rtp_get_quality_jitter(rtp); 02945 case RTPQOS_LOSS: 02946 return __ast_rtp_get_quality_loss(rtp); 02947 case RTPQOS_RTT: 02948 return __ast_rtp_get_quality_rtt(rtp); 02949 } 02950 02951 return NULL; 02952 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 775 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by check_rtp_timeout().
00776 { 00777 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00778 return 0; 00779 return rtp->rtpholdtimeout; 00780 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 783 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by check_rtp_timeout().
00784 { 00785 return rtp->rtpkeepalive; 00786 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 767 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by check_rtp_timeout().
00768 { 00769 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00770 return 0; 00771 return rtp->rtptimeout; 00772 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2590 of file rtp.c.
References ast_rtp::us.
Referenced by add_sdp(), external_rtp_create(), get_our_media_address(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), jingle_create_candidates(), oh323_set_rtp_peer(), skinny_set_rtp_peer(), and start_rtp().
int ast_rtp_getnat | ( | struct ast_rtp * | rtp | ) |
Definition at line 803 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00804 { 00805 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00806 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 4821 of file rtp.c.
References __ast_rtp_reload(), ast_cli_register_multiple(), and cli_rtp.
Referenced by main().
04822 { 04823 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 04824 __ast_rtp_reload(0); 04825 }
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 2286 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), 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(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), bridge_p2p_rtp_write(), and start_rtp().
02287 { 02288 int pt = 0; 02289 02290 rtp_bridge_lock(rtp); 02291 02292 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 02293 code == rtp->rtp_lookup_code_cache_code) { 02294 /* Use our cached mapping, to avoid the overhead of the loop below */ 02295 pt = rtp->rtp_lookup_code_cache_result; 02296 rtp_bridge_unlock(rtp); 02297 return pt; 02298 } 02299 02300 /* Check the dynamic list first */ 02301 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02302 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 02303 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02304 rtp->rtp_lookup_code_cache_code = code; 02305 rtp->rtp_lookup_code_cache_result = pt; 02306 rtp_bridge_unlock(rtp); 02307 return pt; 02308 } 02309 } 02310 02311 /* Then the static list */ 02312 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02313 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 02314 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02315 rtp->rtp_lookup_code_cache_code = code; 02316 rtp->rtp_lookup_code_cache_result = pt; 02317 rtp_bridge_unlock(rtp); 02318 return pt; 02319 } 02320 } 02321 02322 rtp_bridge_unlock(rtp); 02323 02324 return -1; 02325 }
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 2346 of file rtp.c.
References ast_copy_string(), ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.
Referenced by process_sdp().
02348 { 02349 int format; 02350 unsigned len; 02351 char *end = buf; 02352 char *start = buf; 02353 02354 if (!buf || !size) 02355 return NULL; 02356 02357 snprintf(end, size, "0x%x (", capability); 02358 02359 len = strlen(end); 02360 end += len; 02361 size -= len; 02362 start = end; 02363 02364 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 02365 if (capability & format) { 02366 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 02367 02368 snprintf(end, size, "%s|", name); 02369 len = strlen(end); 02370 end += len; 02371 size -= len; 02372 } 02373 } 02374 02375 if (start == end) 02376 ast_copy_string(start, "nothing)", size); 02377 else if (size > 1) 02378 *(end -1) = ')'; 02379 02380 return buf; 02381 }
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 2327 of file rtp.c.
References ARRAY_LEN, 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(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().
02329 { 02330 unsigned int i; 02331 02332 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02333 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 02334 if (isAstFormat && 02335 (code == AST_FORMAT_G726_AAL2) && 02336 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02337 return "G726-32"; 02338 else 02339 return mimeTypes[i].subtype; 02340 } 02341 } 02342 02343 return ""; 02344 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 2264 of file rtp.c.
References rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), and static_RTP_PT.
Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().
02265 { 02266 struct rtpPayloadType result; 02267 02268 result.isAstFormat = result.code = 0; 02269 02270 if (pt < 0 || pt > MAX_RTP_PT) 02271 return result; /* bogus payload type */ 02272 02273 /* Start with negotiated codecs */ 02274 rtp_bridge_lock(rtp); 02275 result = rtp->current_RTP_PT[pt]; 02276 rtp_bridge_unlock(rtp); 02277 02278 /* If it doesn't exist, check our static RTP type list, just in case */ 02279 if (!result.code) 02280 result = static_RTP_PT[pt]; 02281 02282 return result; 02283 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 2109 of file rtp.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, 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_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_channel::name, and ast_rtp_protocol::set_rtp_peer.
Referenced by dial_exec_full(), and do_forward().
02110 { 02111 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 02112 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 02113 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 02114 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 02115 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED; 02116 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED; 02117 int srccodec, destcodec; 02118 02119 /* Lock channels */ 02120 ast_channel_lock(dest); 02121 while (ast_channel_trylock(src)) { 02122 ast_channel_unlock(dest); 02123 usleep(1); 02124 ast_channel_lock(dest); 02125 } 02126 02127 /* Find channel driver interfaces */ 02128 if (!(destpr = get_proto(dest))) { 02129 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name); 02130 ast_channel_unlock(dest); 02131 ast_channel_unlock(src); 02132 return 0; 02133 } 02134 if (!(srcpr = get_proto(src))) { 02135 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name); 02136 ast_channel_unlock(dest); 02137 ast_channel_unlock(src); 02138 return 0; 02139 } 02140 02141 /* Get audio and video interface (if native bridge is possible) */ 02142 audio_dest_res = destpr->get_rtp_info(dest, &destp); 02143 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 02144 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED; 02145 audio_src_res = srcpr->get_rtp_info(src, &srcp); 02146 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 02147 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED; 02148 02149 /* Ensure we have at least one matching codec */ 02150 if (srcpr->get_codec) 02151 srccodec = srcpr->get_codec(src); 02152 else 02153 srccodec = 0; 02154 if (destpr->get_codec) 02155 destcodec = destpr->get_codec(dest); 02156 else 02157 destcodec = 0; 02158 02159 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 02160 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE) || audio_src_res != AST_RTP_TRY_NATIVE || (video_src_res != AST_RTP_GET_FAILED && video_src_res != AST_RTP_TRY_NATIVE) || !(srccodec & destcodec)) { 02161 /* Somebody doesn't want to play... */ 02162 ast_channel_unlock(dest); 02163 ast_channel_unlock(src); 02164 return 0; 02165 } 02166 ast_rtp_pt_copy(destp, srcp); 02167 if (vdestp && vsrcp) 02168 ast_rtp_pt_copy(vdestp, vsrcp); 02169 if (tdestp && tsrcp) 02170 ast_rtp_pt_copy(tdestp, tsrcp); 02171 if (media) { 02172 /* Bridge early */ 02173 if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02174 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 02175 } 02176 ast_channel_unlock(dest); 02177 ast_channel_unlock(src); 02178 ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 02179 return 1; 02180 }
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 2541 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
02542 { 02543 struct in_addr ia; 02544 02545 memset(&ia, 0, sizeof(ia)); 02546 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02547 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
reload rtp configuration
Definition at line 2432 of file rtp.c.
References ast_mutex_init(), ast_random(), ast_set_flag, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, STRICT_RTP_LEARN, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, ast_rtp::them, and ast_rtp::us.
Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().
02433 { 02434 #ifdef P2P_INTENSE 02435 ast_mutex_init(&rtp->bridge_lock); 02436 #endif 02437 02438 rtp->them.sin_family = AF_INET; 02439 rtp->us.sin_family = AF_INET; 02440 rtp->ssrc = ast_random(); 02441 rtp->seqno = ast_random() & 0xffff; 02442 ast_set_flag(rtp, FLAG_HAS_DTMF); 02443 rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN); 02444 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2554 of file rtp.c.
References ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_answer(), sip_indicate(), sip_write(), and skinny_indicate().
struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode, | |||
struct in_addr | in | |||
) |
Initializate a RTP session using an in_addr structure.
This fuction gets called by ast_rtp_new().
sched | ||
io | ||
rtcpenable | ||
callbackmode | ||
in |
Definition at line 2446 of file rtp.c.
References ast_calloc, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), errno, LOG_ERROR, rtp_socket(), and sched.
Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), jingle_alloc(), sip_alloc(), and start_rtp().
02447 { 02448 struct ast_rtp *rtp; 02449 int x; 02450 int startplace; 02451 02452 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 02453 return NULL; 02454 02455 ast_rtp_new_init(rtp); 02456 02457 rtp->s = rtp_socket("RTP"); 02458 if (rtp->s < 0) 02459 goto fail; 02460 if (sched && rtcpenable) { 02461 rtp->sched = sched; 02462 rtp->rtcp = ast_rtcp_new(); 02463 } 02464 02465 /* 02466 * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well. 02467 * Start from a random (even, by RTP spec) port number, and 02468 * iterate until success or no ports are available. 02469 * Note that the requirement of RTP port being even, or RTCP being the 02470 * next one, cannot be enforced in presence of a NAT box because the 02471 * mapping is not under our control. 02472 */ 02473 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 02474 x = x & ~1; /* make it an even number */ 02475 startplace = x; /* remember the starting point */ 02476 /* this is constant across the loop */ 02477 rtp->us.sin_addr = addr; 02478 if (rtp->rtcp) 02479 rtp->rtcp->us.sin_addr = addr; 02480 for (;;) { 02481 rtp->us.sin_port = htons(x); 02482 if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) { 02483 /* bind succeeded, if no rtcp then we are done */ 02484 if (!rtp->rtcp) 02485 break; 02486 /* have rtcp, try to bind it */ 02487 rtp->rtcp->us.sin_port = htons(x + 1); 02488 if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) 02489 break; /* success again, we are really done */ 02490 /* 02491 * RTCP bind failed, so close and recreate the 02492 * already bound RTP socket for the next round. 02493 */ 02494 close(rtp->s); 02495 rtp->s = rtp_socket("RTP"); 02496 if (rtp->s < 0) 02497 goto fail; 02498 } 02499 /* 02500 * If we get here, there was an error in one of the bind() 02501 * calls, so make sure it is nothing unexpected. 02502 */ 02503 if (errno != EADDRINUSE) { 02504 /* We got an error that wasn't expected, abort! */ 02505 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 02506 goto fail; 02507 } 02508 /* 02509 * One of the ports is in use. For the next iteration, 02510 * increment by two and handle wraparound. 02511 * If we reach the starting point, then declare failure. 02512 */ 02513 x += 2; 02514 if (x > rtpend) 02515 x = (rtpstart + 1) & ~1; 02516 if (x == startplace) { 02517 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 02518 goto fail; 02519 } 02520 } 02521 rtp->sched = sched; 02522 rtp->io = io; 02523 if (callbackmode) { 02524 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 02525 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 02526 } 02527 ast_rtp_pt_default(rtp); 02528 return rtp; 02529 02530 fail: 02531 if (rtp->s >= 0) 02532 close(rtp->s); 02533 if (rtp->rtcp) { 02534 close(rtp->rtcp->s); 02535 ast_free(rtp->rtcp); 02536 } 02537 ast_free(rtp); 02538 return NULL; 02539 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register an RTP channel client.
Definition at line 3781 of file rtp.c.
References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_rtp_protocol::list, LOG_WARNING, and ast_rtp_protocol::type.
Referenced by load_module().
03782 { 03783 struct ast_rtp_protocol *cur; 03784 03785 AST_RWLIST_WRLOCK(&protos); 03786 AST_RWLIST_TRAVERSE(&protos, cur, list) { 03787 if (!strcmp(cur->type, proto->type)) { 03788 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 03789 AST_RWLIST_UNLOCK(&protos); 03790 return -1; 03791 } 03792 } 03793 AST_RWLIST_INSERT_HEAD(&protos, proto, list); 03794 AST_RWLIST_UNLOCK(&protos); 03795 03796 return 0; 03797 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister an RTP channel client.
Definition at line 3773 of file rtp.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by load_module(), and unload_module().
03774 { 03775 AST_RWLIST_WRLOCK(&protos); 03776 AST_RWLIST_REMOVE(&protos, proto, list); 03777 AST_RWLIST_UNLOCK(&protos); 03778 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1947 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by gtalk_alloc(), and process_sdp().
01948 { 01949 int i; 01950 01951 if (!rtp) 01952 return; 01953 01954 rtp_bridge_lock(rtp); 01955 01956 for (i = 0; i < MAX_RTP_PT; ++i) { 01957 rtp->current_RTP_PT[i].isAstFormat = 0; 01958 rtp->current_RTP_PT[i].code = 0; 01959 } 01960 01961 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01962 rtp->rtp_lookup_code_cache_code = 0; 01963 rtp->rtp_lookup_code_cache_result = 0; 01964 01965 rtp_bridge_unlock(rtp); 01966 }
Copy payload types between RTP structures.
Definition at line 1987 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), 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().
01988 { 01989 unsigned int i; 01990 01991 rtp_bridge_lock(dest); 01992 rtp_bridge_lock(src); 01993 01994 for (i = 0; i < MAX_RTP_PT; ++i) { 01995 dest->current_RTP_PT[i].isAstFormat = 01996 src->current_RTP_PT[i].isAstFormat; 01997 dest->current_RTP_PT[i].code = 01998 src->current_RTP_PT[i].code; 01999 } 02000 dest->rtp_lookup_code_cache_isAstFormat = 0; 02001 dest->rtp_lookup_code_cache_code = 0; 02002 dest->rtp_lookup_code_cache_result = 0; 02003 02004 rtp_bridge_unlock(src); 02005 rtp_bridge_unlock(dest); 02006 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1968 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), 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.
01969 { 01970 int i; 01971 01972 rtp_bridge_lock(rtp); 01973 01974 /* Initialize to default payload types */ 01975 for (i = 0; i < MAX_RTP_PT; ++i) { 01976 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01977 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01978 } 01979 01980 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01981 rtp->rtp_lookup_code_cache_code = 0; 01982 rtp->rtp_lookup_code_cache_result = 0; 01983 01984 rtp_bridge_unlock(rtp); 01985 }
Write RTP packet with audio or video media frames into UDP packet.
Definition at line 3505 of file rtp.c.
References ast_debug, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, ast_inet_ntoa(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_tvzero(), ast_verbose, calc_txstamp(), errno, f, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::set_marker_bit, ast_rtp::ssrc, ast_rtcp::them, ast_rtp::them, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
03506 { 03507 unsigned char *rtpheader; 03508 int hdrlen = 12; 03509 int res; 03510 unsigned int ms; 03511 int pred; 03512 int mark = 0; 03513 03514 if (rtp->sending_digit) { 03515 return 0; 03516 } 03517 03518 ms = calc_txstamp(rtp, &f->delivery); 03519 /* Default prediction */ 03520 if (f->frametype == AST_FRAME_VOICE) { 03521 pred = rtp->lastts + f->samples; 03522 03523 /* Re-calculate last TS */ 03524 rtp->lastts = rtp->lastts + ms * 8; 03525 if (ast_tvzero(f->delivery)) { 03526 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 03527 and if so, go with our prediction */ 03528 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 03529 rtp->lastts = pred; 03530 else { 03531 ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 03532 mark = 1; 03533 } 03534 } 03535 } else if (f->frametype == AST_FRAME_VIDEO) { 03536 mark = f->subclass & 0x1; 03537 pred = rtp->lastovidtimestamp + f->samples; 03538 /* Re-calculate last TS */ 03539 rtp->lastts = rtp->lastts + ms * 90; 03540 /* If it's close to our prediction, go for it */ 03541 if (ast_tvzero(f->delivery)) { 03542 if (abs(rtp->lastts - pred) < 7200) { 03543 rtp->lastts = pred; 03544 rtp->lastovidtimestamp += f->samples; 03545 } else { 03546 ast_debug(3, "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); 03547 rtp->lastovidtimestamp = rtp->lastts; 03548 } 03549 } 03550 } else { 03551 pred = rtp->lastotexttimestamp + f->samples; 03552 /* Re-calculate last TS */ 03553 rtp->lastts = rtp->lastts + ms; 03554 /* If it's close to our prediction, go for it */ 03555 if (ast_tvzero(f->delivery)) { 03556 if (abs(rtp->lastts - pred) < 7200) { 03557 rtp->lastts = pred; 03558 rtp->lastotexttimestamp += f->samples; 03559 } else { 03560 ast_debug(3, "Difference is %d, ms is %d, pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, rtp->lastts, pred, f->samples); 03561 rtp->lastotexttimestamp = rtp->lastts; 03562 } 03563 } 03564 } 03565 03566 /* If we have been explicitly told to set the marker bit do so */ 03567 if (rtp->set_marker_bit) { 03568 mark = 1; 03569 rtp->set_marker_bit = 0; 03570 } 03571 03572 /* If the timestamp for non-digit packets has moved beyond the timestamp 03573 for digits, update the digit timestamp. 03574 */ 03575 if (rtp->lastts > rtp->lastdigitts) 03576 rtp->lastdigitts = rtp->lastts; 03577 03578 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 03579 rtp->lastts = f->ts * 8; 03580 03581 /* Get a pointer to the header */ 03582 rtpheader = (unsigned char *)(f->data.ptr - hdrlen); 03583 03584 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 03585 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 03586 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 03587 03588 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 03589 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 03590 if (res < 0) { 03591 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 03592 ast_debug(1, "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)); 03593 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 03594 /* Only give this error message once if we are not RTP debugging */ 03595 if (option_debug || rtpdebug) 03596 ast_debug(0, "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)); 03597 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 03598 } 03599 } else { 03600 rtp->txcount++; 03601 rtp->txoctetcount +=(res - hdrlen); 03602 03603 /* Do not schedule RR if RTCP isn't run */ 03604 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 03605 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 03606 } 03607 } 03608 03609 if (rtp_debug_test_addr(&rtp->them)) 03610 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03611 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 03612 } 03613 03614 rtp->seqno++; 03615 03616 return 0; 03617 }
Definition at line 1525 of file rtp.c.
References ast_assert, ast_codec_get_samples(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose, bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, errno, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len(), ast_frame::len, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_frame::ptr, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, rtp_debug_test_addr(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, send_dtmf(), ast_rtp::sending_digit, ast_frame::seqno, ast_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtp::them, ast_rtcp::them, ast_rtp::themssrc, ast_frame::ts, and version.
Referenced by gtalk_rtp_read(), jingle_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), skinny_rtp_read(), and unistim_rtp_read().
01526 { 01527 int res; 01528 struct sockaddr_in sock_in; 01529 socklen_t len; 01530 unsigned int seqno; 01531 int version; 01532 int payloadtype; 01533 int hdrlen = 12; 01534 int padding; 01535 int mark; 01536 int ext; 01537 int cc; 01538 unsigned int ssrc; 01539 unsigned int timestamp; 01540 unsigned int *rtpheader; 01541 struct rtpPayloadType rtpPT; 01542 struct ast_rtp *bridged = NULL; 01543 int prev_seqno; 01544 01545 /* If time is up, kill it */ 01546 if (rtp->sending_digit) 01547 ast_rtp_senddigit_continuation(rtp); 01548 01549 len = sizeof(sock_in); 01550 01551 /* Cache where the header will go */ 01552 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01553 0, (struct sockaddr *)&sock_in, &len); 01554 01555 /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */ 01556 if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { 01557 /* Copy over address that this packet was received on */ 01558 memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address)); 01559 /* Now move over to actually protecting the RTP port */ 01560 rtp->strict_rtp_state = STRICT_RTP_CLOSED; 01561 ast_debug(1, "Learned remote address is %s:%d for strict RTP purposes, now protecting the port.\n", ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port)); 01562 } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { 01563 /* If the address we previously learned doesn't match the address this packet came in on simply drop it */ 01564 if ((rtp->strict_rtp_address.sin_addr.s_addr != sock_in.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sock_in.sin_port)) { 01565 ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port)); 01566 return &ast_null_frame; 01567 } 01568 } 01569 01570 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01571 if (res < 0) { 01572 ast_assert(errno != EBADF); 01573 if (errno != EAGAIN) { 01574 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01575 return NULL; 01576 } 01577 return &ast_null_frame; 01578 } 01579 01580 if (res < hdrlen) { 01581 ast_log(LOG_WARNING, "RTP Read too short\n"); 01582 return &ast_null_frame; 01583 } 01584 01585 /* Get fields */ 01586 seqno = ntohl(rtpheader[0]); 01587 01588 /* Check RTP version */ 01589 version = (seqno & 0xC0000000) >> 30; 01590 if (!version) { 01591 /* If the two high bits are 0, this might be a 01592 * STUN message, so process it. stun_handle_packet() 01593 * answers to requests, and it returns STUN_ACCEPT 01594 * if the request is valid. 01595 */ 01596 if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) && 01597 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01598 memcpy(&rtp->them, &sock_in, sizeof(rtp->them)); 01599 } 01600 return &ast_null_frame; 01601 } 01602 01603 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01604 /* If we don't have the other side's address, then ignore this */ 01605 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01606 return &ast_null_frame; 01607 #endif 01608 01609 /* Send to whoever send to us if NAT is turned on */ 01610 if (rtp->nat) { 01611 if ((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01612 (rtp->them.sin_port != sock_in.sin_port)) { 01613 rtp->them = sock_in; 01614 if (rtp->rtcp) { 01615 int h = 0; 01616 memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them)); 01617 h = ntohs(rtp->them.sin_port); 01618 rtp->rtcp->them.sin_port = htons(h + 1); 01619 } 01620 rtp->rxseqno = 0; 01621 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01622 if (option_debug || rtpdebug) 01623 ast_debug(0, "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)); 01624 } 01625 } 01626 01627 /* If we are bridged to another RTP stream, send direct */ 01628 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01629 return &ast_null_frame; 01630 01631 if (version != 2) 01632 return &ast_null_frame; 01633 01634 payloadtype = (seqno & 0x7f0000) >> 16; 01635 padding = seqno & (1 << 29); 01636 mark = seqno & (1 << 23); 01637 ext = seqno & (1 << 28); 01638 cc = (seqno & 0xF000000) >> 24; 01639 seqno &= 0xffff; 01640 timestamp = ntohl(rtpheader[1]); 01641 ssrc = ntohl(rtpheader[2]); 01642 01643 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01644 if (option_debug || rtpdebug) 01645 ast_debug(0, "Forcing Marker bit, because SSRC has changed\n"); 01646 mark = 1; 01647 } 01648 01649 rtp->rxssrc = ssrc; 01650 01651 if (padding) { 01652 /* Remove padding bytes */ 01653 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01654 } 01655 01656 if (cc) { 01657 /* CSRC fields present */ 01658 hdrlen += cc*4; 01659 } 01660 01661 if (ext) { 01662 /* RTP Extension present */ 01663 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01664 hdrlen += 4; 01665 if (option_debug) { 01666 int profile; 01667 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01668 if (profile == 0x505a) 01669 ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01670 else 01671 ast_debug(1, "Found unknown RTP Extensions %x\n", profile); 01672 } 01673 } 01674 01675 if (res < hdrlen) { 01676 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01677 return &ast_null_frame; 01678 } 01679 01680 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01681 01682 if (rtp->rxcount==1) { 01683 /* This is the first RTP packet successfully received from source */ 01684 rtp->seedrxseqno = seqno; 01685 } 01686 01687 /* Do not schedule RR if RTCP isn't run */ 01688 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01689 /* Schedule transmission of Receiver Report */ 01690 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01691 } 01692 if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01693 rtp->cycles += RTP_SEQ_MOD; 01694 01695 prev_seqno = rtp->lastrxseqno; 01696 01697 rtp->lastrxseqno = seqno; 01698 01699 if (!rtp->themssrc) 01700 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01701 01702 if (rtp_debug_test_addr(&sock_in)) 01703 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01704 ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01705 01706 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01707 if (!rtpPT.isAstFormat) { 01708 struct ast_frame *f = NULL; 01709 01710 /* This is special in-band data that's not one of our codecs */ 01711 if (rtpPT.code == AST_RTP_DTMF) { 01712 /* It's special -- rfc2833 process it */ 01713 if (rtp_debug_test_addr(&sock_in)) { 01714 unsigned char *data; 01715 unsigned int event; 01716 unsigned int event_end; 01717 unsigned int duration; 01718 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01719 event = ntohl(*((unsigned int *)(data))); 01720 event >>= 24; 01721 event_end = ntohl(*((unsigned int *)(data))); 01722 event_end <<= 8; 01723 event_end >>= 24; 01724 duration = ntohl(*((unsigned int *)(data))); 01725 duration &= 0xFFFF; 01726 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(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration); 01727 } 01728 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01729 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01730 /* It's really special -- process it the Cisco way */ 01731 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01732 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01733 rtp->lastevent = seqno; 01734 } 01735 } else if (rtpPT.code == AST_RTP_CN) { 01736 /* Comfort Noise */ 01737 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01738 } else { 01739 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01740 } 01741 return f ? f : &ast_null_frame; 01742 } 01743 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01744 rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT; 01745 01746 rtp->rxseqno = seqno; 01747 01748 if (rtp->dtmfcount) { 01749 rtp->dtmfcount -= (timestamp - rtp->lastrxts); 01750 01751 if (rtp->dtmfcount < 0) { 01752 rtp->dtmfcount = 0; 01753 } 01754 01755 if (rtp->resp && !rtp->dtmfcount) { 01756 struct ast_frame *f; 01757 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01758 rtp->resp = 0; 01759 return f; 01760 } 01761 } 01762 01763 /* Record received timestamp as last received now */ 01764 rtp->lastrxts = timestamp; 01765 01766 rtp->f.mallocd = 0; 01767 rtp->f.datalen = res - hdrlen; 01768 rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01769 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01770 rtp->f.seqno = seqno; 01771 01772 if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) { 01773 unsigned char *data = rtp->f.data.ptr; 01774 01775 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen); 01776 rtp->f.datalen +=3; 01777 *data++ = 0xEF; 01778 *data++ = 0xBF; 01779 *data = 0xBD; 01780 } 01781 01782 if (rtp->f.subclass == AST_FORMAT_T140RED) { 01783 unsigned char *data = rtp->f.data.ptr; 01784 unsigned char *header_end; 01785 int num_generations; 01786 int header_length; 01787 int length; 01788 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/ 01789 int x; 01790 01791 rtp->f.subclass = AST_FORMAT_T140; 01792 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); 01793 header_end++; 01794 01795 header_length = header_end - data; 01796 num_generations = header_length / 4; 01797 length = header_length; 01798 01799 if (!diff) { 01800 for (x = 0; x < num_generations; x++) 01801 length += data[x * 4 + 3]; 01802 01803 if (!(rtp->f.datalen - length)) 01804 return &ast_null_frame; 01805 01806 rtp->f.data.ptr += length; 01807 rtp->f.datalen -= length; 01808 } else if (diff > num_generations && diff < 10) { 01809 length -= 3; 01810 rtp->f.data.ptr += length; 01811 rtp->f.datalen -= length; 01812 01813 data = rtp->f.data.ptr; 01814 *data++ = 0xEF; 01815 *data++ = 0xBF; 01816 *data = 0xBD; 01817 } else { 01818 for ( x = 0; x < num_generations - diff; x++) 01819 length += data[x * 4 + 3]; 01820 01821 rtp->f.data.ptr += length; 01822 rtp->f.datalen -= length; 01823 } 01824 } 01825 01826 if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) { 01827 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01828 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01829 ast_frame_byteswap_be(&rtp->f); 01830 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01831 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01832 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01833 rtp->f.ts = timestamp / 8; 01834 rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 ); 01835 } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) { 01836 /* Video -- samples is # of samples vs. 90000 */ 01837 if (!rtp->lastividtimestamp) 01838 rtp->lastividtimestamp = timestamp; 01839 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01840 rtp->lastividtimestamp = timestamp; 01841 rtp->f.delivery.tv_sec = 0; 01842 rtp->f.delivery.tv_usec = 0; 01843 /* Pass the RTP marker bit as bit 0 in the subclass field. 01844 * This is ok because subclass is actually a bitmask, and 01845 * the low bits represent audio formats, that are not 01846 * involved here since we deal with video. 01847 */ 01848 if (mark) 01849 rtp->f.subclass |= 0x1; 01850 } else { 01851 /* TEXT -- samples is # of samples vs. 1000 */ 01852 if (!rtp->lastitexttimestamp) 01853 rtp->lastitexttimestamp = timestamp; 01854 rtp->f.samples = timestamp - rtp->lastitexttimestamp; 01855 rtp->lastitexttimestamp = timestamp; 01856 rtp->f.delivery.tv_sec = 0; 01857 rtp->f.delivery.tv_usec = 0; 01858 } 01859 rtp->f.src = "RTP"; 01860 return &rtp->f; 01861 }
int ast_rtp_reload | ( | void | ) |
Initialize RTP subsystem
Definition at line 4815 of file rtp.c.
References __ast_rtp_reload().
04816 { 04817 return __ast_rtp_reload(1); 04818 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2627 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::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastotexttimestamp, 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.
02628 { 02629 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02630 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02631 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02632 rtp->lastts = 0; 02633 rtp->lastdigitts = 0; 02634 rtp->lastrxts = 0; 02635 rtp->lastividtimestamp = 0; 02636 rtp->lastovidtimestamp = 0; 02637 rtp->lastitexttimestamp = 0; 02638 rtp->lastotexttimestamp = 0; 02639 rtp->lasteventseqn = 0; 02640 rtp->lastevent = 0; 02641 rtp->lasttxformat = 0; 02642 rtp->lastrxformat = 0; 02643 rtp->dtmfcount = 0; 02644 rtp->dtmfsamples = 0; 02645 rtp->seqno = 0; 02646 rtp->rxseqno = 0; 02647 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 3470 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::data, ast_rtp::dtmfmute, errno, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by check_rtp_timeout().
03471 { 03472 unsigned int *rtpheader; 03473 int hdrlen = 12; 03474 int res; 03475 int payload; 03476 char data[256]; 03477 level = 127 - (level & 0x7f); 03478 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 03479 03480 /* If we have no peer, return immediately */ 03481 if (!rtp->them.sin_addr.s_addr) 03482 return 0; 03483 03484 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03485 03486 /* Get a pointer to the header */ 03487 rtpheader = (unsigned int *)data; 03488 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 03489 rtpheader[1] = htonl(rtp->lastts); 03490 rtpheader[2] = htonl(rtp->ssrc); 03491 data[12] = level; 03492 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 03493 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 03494 if (res <0) 03495 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)); 03496 if (rtp_debug_test_addr(&rtp->them)) 03497 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 03498 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 03499 03500 } 03501 return 0; 03502 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 3037 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by mgcp_senddigit_begin(), oh323_digit_begin(), and sip_senddigit_begin().
03038 { 03039 unsigned int *rtpheader; 03040 int hdrlen = 12, res = 0, i = 0, payload = 0; 03041 char data[256]; 03042 03043 if ((digit <= '9') && (digit >= '0')) 03044 digit -= '0'; 03045 else if (digit == '*') 03046 digit = 10; 03047 else if (digit == '#') 03048 digit = 11; 03049 else if ((digit >= 'A') && (digit <= 'D')) 03050 digit = digit - 'A' + 12; 03051 else if ((digit >= 'a') && (digit <= 'd')) 03052 digit = digit - 'a' + 12; 03053 else { 03054 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 03055 return 0; 03056 } 03057 03058 /* If we have no peer, return immediately */ 03059 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03060 return 0; 03061 03062 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 03063 03064 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03065 rtp->send_duration = 160; 03066 rtp->lastdigitts = rtp->lastts + rtp->send_duration; 03067 03068 /* Get a pointer to the header */ 03069 rtpheader = (unsigned int *)data; 03070 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 03071 rtpheader[1] = htonl(rtp->lastdigitts); 03072 rtpheader[2] = htonl(rtp->ssrc); 03073 03074 for (i = 0; i < 2; i++) { 03075 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 03076 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03077 if (res < 0) 03078 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 03079 ast_inet_ntoa(rtp->them.sin_addr), 03080 ntohs(rtp->them.sin_port), strerror(errno)); 03081 if (rtp_debug_test_addr(&rtp->them)) 03082 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03083 ast_inet_ntoa(rtp->them.sin_addr), 03084 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03085 /* Increment sequence number */ 03086 rtp->seqno++; 03087 /* Increment duration */ 03088 rtp->send_duration += 160; 03089 /* Clear marker bit and set seqno */ 03090 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 03091 } 03092 03093 /* Since we received a begin, we can safely store the digit and disable any compensation */ 03094 rtp->sending_digit = 1; 03095 rtp->send_digit = digit; 03096 rtp->send_payload = payload; 03097 03098 return 0; 03099 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 3102 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_verbose, errno, ast_rtp::lastdigitts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by ast_rtp_read().
03103 { 03104 unsigned int *rtpheader; 03105 int hdrlen = 12, res = 0; 03106 char data[256]; 03107 03108 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03109 return 0; 03110 03111 /* Setup packet to send */ 03112 rtpheader = (unsigned int *)data; 03113 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 03114 rtpheader[1] = htonl(rtp->lastdigitts); 03115 rtpheader[2] = htonl(rtp->ssrc); 03116 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 03117 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 03118 03119 /* Transmit */ 03120 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03121 if (res < 0) 03122 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 03123 ast_inet_ntoa(rtp->them.sin_addr), 03124 ntohs(rtp->them.sin_port), strerror(errno)); 03125 if (rtp_debug_test_addr(&rtp->them)) 03126 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03127 ast_inet_ntoa(rtp->them.sin_addr), 03128 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03129 03130 /* Increment sequence number */ 03131 rtp->seqno++; 03132 /* Increment duration */ 03133 rtp->send_duration += 160; 03134 03135 return 0; 03136 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 3139 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by mgcp_senddigit_end(), oh323_digit_end(), and sip_senddigit_end().
03140 { 03141 unsigned int *rtpheader; 03142 int hdrlen = 12, res = 0, i = 0; 03143 char data[256]; 03144 03145 /* If no address, then bail out */ 03146 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03147 return 0; 03148 03149 if ((digit <= '9') && (digit >= '0')) 03150 digit -= '0'; 03151 else if (digit == '*') 03152 digit = 10; 03153 else if (digit == '#') 03154 digit = 11; 03155 else if ((digit >= 'A') && (digit <= 'D')) 03156 digit = digit - 'A' + 12; 03157 else if ((digit >= 'a') && (digit <= 'd')) 03158 digit = digit - 'a' + 12; 03159 else { 03160 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 03161 return 0; 03162 } 03163 03164 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03165 03166 rtpheader = (unsigned int *)data; 03167 rtpheader[1] = htonl(rtp->lastdigitts); 03168 rtpheader[2] = htonl(rtp->ssrc); 03169 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 03170 /* Set end bit */ 03171 rtpheader[3] |= htonl((1 << 23)); 03172 03173 /* Send 3 termination packets */ 03174 for (i = 0; i < 3; i++) { 03175 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 03176 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03177 rtp->seqno++; 03178 if (res < 0) 03179 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 03180 ast_inet_ntoa(rtp->them.sin_addr), 03181 ntohs(rtp->them.sin_port), strerror(errno)); 03182 if (rtp_debug_test_addr(&rtp->them)) 03183 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03184 ast_inet_ntoa(rtp->them.sin_addr), 03185 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03186 } 03187 rtp->lastts += rtp->send_duration; 03188 rtp->sending_digit = 0; 03189 rtp->send_digit = 0; 03190 03191 return res; 03192 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 793 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00794 { 00795 rtp->callback = callback; 00796 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Activate payload type.
Definition at line 2186 of file rtp.c.
References ast_rtp::current_RTP_PT, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), and static_RTP_PT.
Referenced by gtalk_is_answered(), gtalk_newcall(), jingle_newcall(), and process_sdp().
02187 { 02188 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 02189 return; /* bogus payload type */ 02190 02191 rtp_bridge_lock(rtp); 02192 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 02193 rtp_bridge_unlock(rtp); 02194 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2562 of file rtp.c.
References ast_rtp::rtcp, ast_rtp::rxseqno, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, ast_rtp::them, and ast_rtcp::them.
Referenced by handle_open_receive_channel_ack_message(), process_sdp(), setup_rtp_connection(), and start_rtp().
02563 { 02564 rtp->them.sin_port = them->sin_port; 02565 rtp->them.sin_addr = them->sin_addr; 02566 if (rtp->rtcp) { 02567 int h = ntohs(them->sin_port); 02568 rtp->rtcp->them.sin_port = htons(h + 1); 02569 rtp->rtcp->them.sin_addr = them->sin_addr; 02570 } 02571 rtp->rxseqno = 0; 02572 /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */ 02573 if (strictrtp) 02574 rtp->strict_rtp_state = STRICT_RTP_LEARN; 02575 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 755 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().
00756 { 00757 rtp->rtpholdtimeout = timeout; 00758 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 761 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00762 { 00763 rtp->rtpkeepalive = period; 00764 }
int ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
int | pt, | |||
char * | mimeType, | |||
char * | mimeSubtype, | |||
enum ast_rtp_options | options | |||
) |
Initiate payload type to a known MIME media type for a codec.
Definition at line 2213 of file rtp.c.
References ARRAY_LEN, AST_FORMAT_G726, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, rtp_bridge_lock(), rtp_bridge_unlock(), subtype, and type.
Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), jingle_newcall(), process_sdp(), set_dtmf_payload(), and setup_rtp_connection().
02216 { 02217 unsigned int i; 02218 int found = 0; 02219 02220 if (pt < 0 || pt > MAX_RTP_PT) 02221 return -1; /* bogus payload type */ 02222 02223 rtp_bridge_lock(rtp); 02224 02225 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02226 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 02227 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 02228 found = 1; 02229 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 02230 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 02231 mimeTypes[i].payloadType.isAstFormat && 02232 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02233 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 02234 break; 02235 } 02236 } 02237 02238 rtp_bridge_unlock(rtp); 02239 02240 return (found ? 0 : -1); 02241 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 749 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().
00750 { 00751 rtp->rtptimeout = timeout; 00752 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 742 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00743 { 00744 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00745 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00746 }
void ast_rtp_set_vars | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp | |||
) |
Set RTPAUDIOQOS(...) variables on a channel when it is being hung up.
Definition at line 2731 of file rtp.c.
References ast_bridged_channel(), ast_rtp_get_quality(), chan, pbx_builtin_setvar_helper(), RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, and RTPQOS_SUMMARY.
Referenced by handle_request_bye(), and sip_hangup().
02731 { 02732 char *audioqos; 02733 char *audioqos_jitter; 02734 char *audioqos_loss; 02735 char *audioqos_rtt; 02736 struct ast_channel *bridge; 02737 02738 if (!rtp || !chan) 02739 return; 02740 02741 bridge = ast_bridged_channel(chan); 02742 02743 audioqos = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY); 02744 audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER); 02745 audioqos_loss = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS); 02746 audioqos_rtt = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT); 02747 02748 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos); 02749 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter); 02750 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss); 02751 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt); 02752 02753 if (!bridge) 02754 return; 02755 02756 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos); 02757 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter); 02758 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss); 02759 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt); 02760 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 808 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().
00809 { 00810 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00811 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 813 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().
00814 { 00815 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00816 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 798 of file rtp.c.
References ast_rtp::nat.
Referenced by __oh323_rtp_create(), do_setnat(), oh323_rtp_read(), and start_rtp().
int ast_rtp_setqos | ( | struct ast_rtp * | rtp, | |
int | type_of_service, | |||
int | class_of_service, | |||
char * | desc | |||
) |
Definition at line 2549 of file rtp.c.
References ast_netsock_set_qos(), and ast_rtp::s.
Referenced by __oh323_rtp_create(), sip_alloc(), and start_rtp().
02550 { 02551 return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc); 02552 }
void ast_rtp_setstun | ( | struct ast_rtp * | rtp, | |
int | stun_enable | |||
) |
Enable STUN capability.
Definition at line 818 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00819 { 00820 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00821 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Stop RTP session, do not destroy structure
Definition at line 2606 of file rtp.c.
References ast_clear_flag, AST_SCHED_DEL, FLAG_P2P_SENT_MARK, free, ast_rtp::red, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, rtp_red::schedid, ast_rtp::them, and ast_rtcp::them.
Referenced by process_sdp(), setup_rtp_connection(), and stop_media_flows().
02607 { 02608 if (rtp->rtcp) { 02609 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02610 } 02611 if (rtp->red) { 02612 AST_SCHED_DEL(rtp->sched, rtp->red->schedid); 02613 free(rtp->red); 02614 rtp->red = NULL; 02615 } 02616 02617 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02618 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02619 if (rtp->rtcp) { 02620 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02621 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02622 } 02623 02624 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02625 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Send STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().
Definition at line 702 of file rtp.c.
References ast_stun_request(), and ast_rtp::s.
Referenced by gtalk_update_stun(), and jingle_update_stun().
00703 { 00704 ast_stun_request(rtp->s, suggestion, username, NULL); 00705 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
clear payload type
Definition at line 2198 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().
Referenced by process_sdp().
02199 { 02200 if (pt < 0 || pt > MAX_RTP_PT) 02201 return; /* bogus payload type */ 02202 02203 rtp_bridge_lock(rtp); 02204 rtp->current_RTP_PT[pt].isAstFormat = 0; 02205 rtp->current_RTP_PT[pt].code = 0; 02206 rtp_bridge_unlock(rtp); 02207 }
Definition at line 3681 of file rtp.c.
References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_rtp::pref, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
Referenced by gtalk_write(), jingle_write(), mgcp_write(), oh323_write(), red_write(), sip_write(), skinny_write(), and unistim_write().
03682 { 03683 struct ast_frame *f; 03684 int codec; 03685 int hdrlen = 12; 03686 int subclass; 03687 03688 03689 /* If we have no peer, return immediately */ 03690 if (!rtp->them.sin_addr.s_addr) 03691 return 0; 03692 03693 /* If there is no data length, return immediately */ 03694 if (!_f->datalen && !rtp->red) 03695 return 0; 03696 03697 /* Make sure we have enough space for RTP header */ 03698 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) { 03699 ast_log(LOG_WARNING, "RTP can only send voice, video and text\n"); 03700 return -1; 03701 } 03702 03703 if (rtp->red) { 03704 /* return 0; */ 03705 /* no primary data or generations to send */ 03706 if ((_f = red_t140_to_red(rtp->red)) == NULL) 03707 return 0; 03708 } 03709 03710 /* The bottom bit of a video subclass contains the marker bit */ 03711 subclass = _f->subclass; 03712 if (_f->frametype == AST_FRAME_VIDEO) 03713 subclass &= ~0x1; 03714 03715 codec = ast_rtp_lookup_code(rtp, 1, subclass); 03716 if (codec < 0) { 03717 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 03718 return -1; 03719 } 03720 03721 if (rtp->lasttxformat != subclass) { 03722 /* New format, reset the smoother */ 03723 ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 03724 rtp->lasttxformat = subclass; 03725 if (rtp->smoother) 03726 ast_smoother_free(rtp->smoother); 03727 rtp->smoother = NULL; 03728 } 03729 03730 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 03731 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 03732 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 03733 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 03734 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)); 03735 return -1; 03736 } 03737 if (fmt.flags) 03738 ast_smoother_set_flags(rtp->smoother, fmt.flags); 03739 ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); 03740 } 03741 } 03742 if (rtp->smoother) { 03743 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 03744 ast_smoother_feed_be(rtp->smoother, _f); 03745 } else { 03746 ast_smoother_feed(rtp->smoother, _f); 03747 } 03748 03749 while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) { 03750 if (f->subclass == AST_FORMAT_G722) { 03751 /* G.722 is silllllllllllllly */ 03752 f->samples /= 2; 03753 } 03754 03755 ast_rtp_raw_write(rtp, f, codec); 03756 } 03757 } else { 03758 /* Don't buffer outgoing frames; send them one-per-packet: */ 03759 if (_f->offset < hdrlen) 03760 f = ast_frdup(_f); /*! \bug XXX this might never be free'd. Why do we do this? */ 03761 else 03762 f = _f; 03763 if (f->data.ptr) 03764 ast_rtp_raw_write(rtp, f, codec); 03765 if (f != _f) 03766 ast_frfree(f); 03767 } 03768 03769 return 0; 03770 }
int ast_stun_request | ( | int | s, | |
struct sockaddr_in * | dst, | |||
const char * | username, | |||
struct sockaddr_in * | answer | |||
) |
Generic STUN request send a generic stun request to the server specified.
s | the socket used to send the request | |
dst | the address of the STUN server | |
username | if non null, add the username in the request | |
answer | if non null, the function waits for a response and puts here the externally visible address. |
Definition at line 636 of file rtp.c.
References append_attr_string(), ast_log(), ast_select(), stun_attr::attr, LOG_WARNING, STUN_BINDREQ, stun_get_mapped(), stun_handle_packet(), stun_req_id(), stun_send(), and STUN_USERNAME.
Referenced by ast_rtp_stun_request(), and ast_sip_ouraddrfor().
00638 { 00639 struct stun_header *req; 00640 unsigned char reqdata[1024]; 00641 int reqlen, reqleft; 00642 struct stun_attr *attr; 00643 int res = 0; 00644 int retry; 00645 00646 req = (struct stun_header *)reqdata; 00647 stun_req_id(req); 00648 reqlen = 0; 00649 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00650 req->msgtype = 0; 00651 req->msglen = 0; 00652 attr = (struct stun_attr *)req->ies; 00653 if (username) 00654 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00655 req->msglen = htons(reqlen); 00656 req->msgtype = htons(STUN_BINDREQ); 00657 for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */ 00658 /* send request, possibly wait for reply */ 00659 unsigned char reply_buf[1024]; 00660 fd_set rfds; 00661 struct timeval to = { 3, 0 }; /* timeout, make it configurable */ 00662 struct sockaddr_in src; 00663 socklen_t srclen; 00664 00665 res = stun_send(s, dst, req); 00666 if (res < 0) { 00667 ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n", 00668 retry, res); 00669 continue; 00670 } 00671 if (answer == NULL) 00672 break; 00673 FD_ZERO(&rfds); 00674 FD_SET(s, &rfds); 00675 res = ast_select(s + 1, &rfds, NULL, NULL, &to); 00676 if (res <= 0) /* timeout or error */ 00677 continue; 00678 memset(&src, '\0', sizeof(src)); 00679 srclen = sizeof(src); 00680 /* XXX pass -1 in the size, because stun_handle_packet might 00681 * write past the end of the buffer. 00682 */ 00683 res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1, 00684 0, (struct sockaddr *)&src, &srclen); 00685 if (res < 0) { 00686 ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n", 00687 retry, res); 00688 continue; 00689 } 00690 memset(answer, '\0', sizeof(struct sockaddr_in)); 00691 stun_handle_packet(s, &src, reply_buf, res, 00692 stun_get_mapped, answer); 00693 res = 0; /* signal regular exit */ 00694 break; 00695 } 00696 return res; 00697 }
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 * | tp0, | |||
struct ast_rtp * | tp1, | |||
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 3800 of file rtp.c.
References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate_data(), ast_inet_ntoa(), ast_log(), ast_poll_channel_add(), ast_poll_channel_del(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), ast_channel::audiohooks, ast_frame::data, ast_frame::datalen, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, inaddrcmp(), LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, ast_channel::name, ast_frame::ptr, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
03801 { 03802 struct ast_frame *fr = NULL; 03803 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03804 int oldcodec0 = codec0, oldcodec1 = codec1; 03805 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,}; 03806 struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,}; 03807 03808 /* Set it up so audio goes directly between the two endpoints */ 03809 03810 /* Test the first channel */ 03811 if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 03812 ast_rtp_get_peer(p1, &ac1); 03813 if (vp1) 03814 ast_rtp_get_peer(vp1, &vac1); 03815 if (tp1) 03816 ast_rtp_get_peer(tp1, &tac1); 03817 } else 03818 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 03819 03820 /* Test the second channel */ 03821 if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 03822 ast_rtp_get_peer(p0, &ac0); 03823 if (vp0) 03824 ast_rtp_get_peer(vp0, &vac0); 03825 if (tp0) 03826 ast_rtp_get_peer(tp0, &tac0); 03827 } else 03828 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 03829 03830 /* Now we can unlock and move into our loop */ 03831 ast_channel_unlock(c0); 03832 ast_channel_unlock(c1); 03833 03834 ast_poll_channel_add(c0, c1); 03835 03836 /* Throw our channels into the structure and enter the loop */ 03837 cs[0] = c0; 03838 cs[1] = c1; 03839 cs[2] = NULL; 03840 for (;;) { 03841 /* Check if anything changed */ 03842 if ((c0->tech_pvt != pvt0) || 03843 (c1->tech_pvt != pvt1) || 03844 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03845 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03846 ast_debug(1, "Oooh, something is weird, backing out\n"); 03847 if (c0->tech_pvt == pvt0) 03848 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03849 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03850 if (c1->tech_pvt == pvt1) 03851 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03852 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03853 ast_poll_channel_del(c0, c1); 03854 return AST_BRIDGE_RETRY; 03855 } 03856 03857 /* Check if they have changed their address */ 03858 ast_rtp_get_peer(p1, &t1); 03859 if (vp1) 03860 ast_rtp_get_peer(vp1, &vt1); 03861 if (tp1) 03862 ast_rtp_get_peer(tp1, &tt1); 03863 if (pr1->get_codec) 03864 codec1 = pr1->get_codec(c1); 03865 ast_rtp_get_peer(p0, &t0); 03866 if (vp0) 03867 ast_rtp_get_peer(vp0, &vt0); 03868 if (tp0) 03869 ast_rtp_get_peer(tp0, &tt0); 03870 if (pr0->get_codec) 03871 codec0 = pr0->get_codec(c0); 03872 if ((inaddrcmp(&t1, &ac1)) || 03873 (vp1 && inaddrcmp(&vt1, &vac1)) || 03874 (tp1 && inaddrcmp(&tt1, &tac1)) || 03875 (codec1 != oldcodec1)) { 03876 ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03877 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 03878 ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 03879 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 03880 ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n", 03881 c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1); 03882 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03883 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 03884 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03885 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 03886 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03887 c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1); 03888 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, tt1.sin_addr.s_addr ? tp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 03889 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 03890 memcpy(&ac1, &t1, sizeof(ac1)); 03891 memcpy(&vac1, &vt1, sizeof(vac1)); 03892 memcpy(&tac1, &tt1, sizeof(tac1)); 03893 oldcodec1 = codec1; 03894 } 03895 if ((inaddrcmp(&t0, &ac0)) || 03896 (vp0 && inaddrcmp(&vt0, &vac0)) || 03897 (tp0 && inaddrcmp(&tt0, &tac0))) { 03898 ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03899 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 03900 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03901 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 03902 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, tt0.sin_addr.s_addr ? tp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 03903 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 03904 memcpy(&ac0, &t0, sizeof(ac0)); 03905 memcpy(&vac0, &vt0, sizeof(vac0)); 03906 memcpy(&tac0, &tt0, sizeof(tac0)); 03907 oldcodec0 = codec0; 03908 } 03909 03910 /* Wait for frame to come in on the channels */ 03911 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03912 if (!timeoutms) { 03913 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03914 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03915 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03916 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03917 return AST_BRIDGE_RETRY; 03918 } 03919 ast_debug(1, "Ooh, empty read...\n"); 03920 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03921 break; 03922 continue; 03923 } 03924 fr = ast_read(who); 03925 other = (who == c0) ? c1 : c0; 03926 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03927 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 03928 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 03929 /* Break out of bridge */ 03930 *fo = fr; 03931 *rc = who; 03932 ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03933 if (c0->tech_pvt == pvt0) 03934 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03935 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03936 if (c1->tech_pvt == pvt1) 03937 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03938 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03939 ast_poll_channel_del(c0, c1); 03940 return AST_BRIDGE_COMPLETE; 03941 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03942 if ((fr->subclass == AST_CONTROL_HOLD) || 03943 (fr->subclass == AST_CONTROL_UNHOLD) || 03944 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03945 (fr->subclass == AST_CONTROL_T38) || 03946 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03947 if (fr->subclass == AST_CONTROL_HOLD) { 03948 /* If we someone went on hold we want the other side to reinvite back to us */ 03949 if (who == c0) 03950 pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0); 03951 else 03952 pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0); 03953 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03954 /* If they went off hold they should go back to being direct */ 03955 if (who == c0) 03956 pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 03957 else 03958 pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 03959 } 03960 /* Update local address information */ 03961 ast_rtp_get_peer(p0, &t0); 03962 memcpy(&ac0, &t0, sizeof(ac0)); 03963 ast_rtp_get_peer(p1, &t1); 03964 memcpy(&ac1, &t1, sizeof(ac1)); 03965 /* Update codec information */ 03966 if (pr0->get_codec && c0->tech_pvt) 03967 oldcodec0 = codec0 = pr0->get_codec(c0); 03968 if (pr1->get_codec && c1->tech_pvt) 03969 oldcodec1 = codec1 = pr1->get_codec(c1); 03970 ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen); 03971 ast_frfree(fr); 03972 } else { 03973 *fo = fr; 03974 *rc = who; 03975 ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03976 return AST_BRIDGE_COMPLETE; 03977 } 03978 } else { 03979 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03980 (fr->frametype == AST_FRAME_DTMF_END) || 03981 (fr->frametype == AST_FRAME_VOICE) || 03982 (fr->frametype == AST_FRAME_VIDEO) || 03983 (fr->frametype == AST_FRAME_IMAGE) || 03984 (fr->frametype == AST_FRAME_HTML) || 03985 (fr->frametype == AST_FRAME_MODEM) || 03986 (fr->frametype == AST_FRAME_TEXT)) { 03987 ast_write(other, fr); 03988 } 03989 ast_frfree(fr); 03990 } 03991 /* Swap priority */ 03992 #ifndef HAVE_EPOLL 03993 cs[2] = cs[0]; 03994 cs[0] = cs[1]; 03995 cs[1] = cs[2]; 03996 #endif 03997 } 03998 03999 ast_poll_channel_del(c0, c1); 04000 04001 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 04002 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 04003 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 04004 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 04005 04006 return AST_BRIDGE_FAILED; 04007 }
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).
In p2p mode, Asterisk is a very basic RTP proxy, just forwarding whatever rtp/rtcp we get in to the channel.
Definition at line 4107 of file rtp.c.
References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_unlock, ast_clear_flag, ast_debug, ast_frfree, ast_poll_channel_add(), ast_read(), ast_channel::audiohooks, FLAG_P2P_SENT_MARK, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, p2p_callback_enable(), p2p_set_bridge(), ast_channel::rawreadformat, ast_channel::rawwriteformat, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
04108 { 04109 struct ast_frame *fr = NULL; 04110 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 04111 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 04112 int p0_callback = 0, p1_callback = 0; 04113 enum ast_bridge_result res = AST_BRIDGE_FAILED; 04114 04115 /* Okay, setup each RTP structure to do P2P forwarding */ 04116 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 04117 p2p_set_bridge(p0, p1); 04118 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 04119 p2p_set_bridge(p1, p0); 04120 04121 /* Activate callback modes if possible */ 04122 p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]); 04123 p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]); 04124 04125 /* Now let go of the channel locks and be on our way */ 04126 ast_channel_unlock(c0); 04127 ast_channel_unlock(c1); 04128 04129 ast_poll_channel_add(c0, c1); 04130 04131 /* Go into a loop forwarding frames until we don't need to anymore */ 04132 cs[0] = c0; 04133 cs[1] = c1; 04134 cs[2] = NULL; 04135 for (;;) { 04136 /* If the underlying formats have changed force this bridge to break */ 04137 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 04138 ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n"); 04139 res = AST_BRIDGE_FAILED_NOWARN; 04140 break; 04141 } 04142 /* Check if anything changed */ 04143 if ((c0->tech_pvt != pvt0) || 04144 (c1->tech_pvt != pvt1) || 04145 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 04146 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 04147 ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n"); 04148 /* If a masquerade needs to happen we have to try to read in a frame so that it actually happens. Without this we risk being called again and going into a loop */ 04149 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 04150 ast_frfree(fr); 04151 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 04152 ast_frfree(fr); 04153 res = AST_BRIDGE_RETRY; 04154 break; 04155 } 04156 /* Wait on a channel to feed us a frame */ 04157 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 04158 if (!timeoutms) { 04159 res = AST_BRIDGE_RETRY; 04160 break; 04161 } 04162 if (option_debug > 2) 04163 ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n"); 04164 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 04165 break; 04166 continue; 04167 } 04168 /* Read in frame from channel */ 04169 fr = ast_read(who); 04170 other = (who == c0) ? c1 : c0; 04171 /* Depending on the frame we may need to break out of our bridge */ 04172 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 04173 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 04174 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 04175 /* Record received frame and who */ 04176 *fo = fr; 04177 *rc = who; 04178 ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup"); 04179 res = AST_BRIDGE_COMPLETE; 04180 break; 04181 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 04182 if ((fr->subclass == AST_CONTROL_HOLD) || 04183 (fr->subclass == AST_CONTROL_UNHOLD) || 04184 (fr->subclass == AST_CONTROL_VIDUPDATE) || 04185 (fr->subclass == AST_CONTROL_T38) || 04186 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 04187 /* If we are going on hold, then break callback mode and P2P bridging */ 04188 if (fr->subclass == AST_CONTROL_HOLD) { 04189 if (p0_callback) 04190 p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]); 04191 if (p1_callback) 04192 p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]); 04193 p2p_set_bridge(p0, NULL); 04194 p2p_set_bridge(p1, NULL); 04195 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 04196 /* If we are off hold, then go back to callback mode and P2P bridging */ 04197 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 04198 p2p_set_bridge(p0, p1); 04199 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 04200 p2p_set_bridge(p1, p0); 04201 p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]); 04202 p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]); 04203 } 04204 ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen); 04205 ast_frfree(fr); 04206 } else { 04207 *fo = fr; 04208 *rc = who; 04209 ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 04210 res = AST_BRIDGE_COMPLETE; 04211 break; 04212 } 04213 } else { 04214 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 04215 (fr->frametype == AST_FRAME_DTMF_END) || 04216 (fr->frametype == AST_FRAME_VOICE) || 04217 (fr->frametype == AST_FRAME_VIDEO) || 04218 (fr->frametype == AST_FRAME_IMAGE) || 04219 (fr->frametype == AST_FRAME_HTML) || 04220 (fr->frametype == AST_FRAME_MODEM) || 04221 (fr->frametype == AST_FRAME_TEXT)) { 04222 ast_write(other, fr); 04223 } 04224 04225 ast_frfree(fr); 04226 } 04227 /* Swap priority */ 04228 #ifndef HAVE_EPOLL 04229 cs[2] = cs[0]; 04230 cs[0] = cs[1]; 04231 cs[1] = cs[2]; 04232 #endif 04233 } 04234 04235 /* If we are totally avoiding the core, then restore our link to it */ 04236 if (p0_callback) 04237 p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]); 04238 if (p1_callback) 04239 p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]); 04240 04241 /* Break out of the direct bridge */ 04242 p2p_set_bridge(p0, NULL); 04243 p2p_set_bridge(p1, NULL); 04244 04245 ast_poll_channel_del(c0, c1); 04246 04247 return res; 04248 }
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 1471 of file rtp.c.
References ast_debug, ast_inet_ntoa(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_set_flag, ast_test_flag, ast_verbose, rtpPayloadType::code, ast_rtp::current_RTP_PT, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_P2P_NEED_DTMF, FLAG_P2P_SENT_MARK, rtpPayloadType::isAstFormat, ast_rtp::nat, option_debug, reconstruct(), rtp_debug_test_addr(), ast_rtp::s, and ast_rtp::them.
Referenced by ast_rtp_read().
01472 { 01473 int res = 0, payload = 0, bridged_payload = 0, mark; 01474 struct rtpPayloadType rtpPT; 01475 int reconstruct = ntohl(rtpheader[0]); 01476 01477 /* Get fields from packet */ 01478 payload = (reconstruct & 0x7f0000) >> 16; 01479 mark = (((reconstruct & 0x800000) >> 23) != 0); 01480 01481 /* Check what the payload value should be */ 01482 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01483 01484 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01485 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01486 return -1; 01487 01488 /* Otherwise adjust bridged payload to match */ 01489 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01490 01491 /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */ 01492 if (!bridged->current_RTP_PT[bridged_payload].code) 01493 return -1; 01494 01495 01496 /* If the mark bit has not been sent yet... do it now */ 01497 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01498 mark = 1; 01499 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01500 } 01501 01502 /* Reconstruct part of the packet */ 01503 reconstruct &= 0xFF80FFFF; 01504 reconstruct |= (bridged_payload << 16); 01505 reconstruct |= (mark << 23); 01506 rtpheader[0] = htonl(reconstruct); 01507 01508 /* Send the packet back out */ 01509 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01510 if (res < 0) { 01511 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01512 ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno)); 01513 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01514 if (option_debug || rtpdebug) 01515 ast_debug(0, "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)); 01516 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01517 } 01518 return 0; 01519 } else if (rtp_debug_test_addr(&bridged->them)) 01520 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); 01521 01522 return 0; 01523 }
static void calc_rxstamp | ( | struct timeval * | when, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1413 of file rtp.c.
References ast_rtp::drxcore, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, normdev_compute(), ast_rtcp::normdev_rxjitter, ast_rtp::rtcp, ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxtransit, ast_rtp::seedrxts, stddev_compute(), and ast_rtcp::stdev_rxjitter.
Referenced by ast_rtp_read(), and schedule_delivery().
01414 { 01415 struct timeval now; 01416 double transit; 01417 double current_time; 01418 double d; 01419 double dtv; 01420 double prog; 01421 01422 double normdev_rxjitter_current; 01423 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01424 gettimeofday(&rtp->rxcore, NULL); 01425 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01426 /* map timestamp to a real time */ 01427 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01428 rtp->rxcore.tv_sec -= timestamp / 8000; 01429 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01430 /* Round to 0.1ms for nice, pretty timestamps */ 01431 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01432 if (rtp->rxcore.tv_usec < 0) { 01433 /* Adjust appropriately if necessary */ 01434 rtp->rxcore.tv_usec += 1000000; 01435 rtp->rxcore.tv_sec -= 1; 01436 } 01437 } 01438 01439 gettimeofday(&now,NULL); 01440 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01441 when->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01442 when->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01443 if (when->tv_usec >= 1000000) { 01444 when->tv_usec -= 1000000; 01445 when->tv_sec += 1; 01446 } 01447 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01448 dtv = (double)rtp->drxcore + (double)(prog); 01449 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01450 transit = current_time - dtv; 01451 d = transit - rtp->rxtransit; 01452 rtp->rxtransit = transit; 01453 if (d<0) 01454 d=-d; 01455 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01456 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01457 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01458 if (rtp->rtcp->rxjitter_count == 1) 01459 rtp->rtcp->minrxjitter = rtp->rxjitter; 01460 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01461 rtp->rtcp->minrxjitter = rtp->rxjitter; 01462 01463 normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count); 01464 rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count); 01465 01466 rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current; 01467 rtp->rtcp->rxjitter_count++; 01468 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 3017 of file rtp.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
03018 { 03019 struct timeval t; 03020 long ms; 03021 if (ast_tvzero(rtp->txcore)) { 03022 rtp->txcore = ast_tvnow(); 03023 /* Round to 20ms for nice, pretty timestamps */ 03024 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 03025 } 03026 /* Use previous txcore if available */ 03027 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 03028 ms = ast_tvdiff_ms(t, rtp->txcore); 03029 if (ms < 0) 03030 ms = 0; 03031 /* Use what we just got for next time */ 03032 rtp->txcore = t; 03033 return (unsigned int) ms; 03034 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 2009 of file rtp.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, chan, ast_rtp_protocol::list, ast_channel::tech, ast_channel_tech::type, and ast_rtp_protocol::type.
Referenced by ast_rtp_bridge(), ast_rtp_early_bridge(), ast_rtp_make_compatible(), and ast_udptl_bridge().
02010 { 02011 struct ast_rtp_protocol *cur = NULL; 02012 02013 AST_RWLIST_RDLOCK(&protos); 02014 AST_RWLIST_TRAVERSE(&protos, cur, list) { 02015 if (cur->type == chan->tech->type) 02016 break; 02017 } 02018 AST_RWLIST_UNLOCK(&protos); 02019 02020 return cur; 02021 }
static char* handle_cli_rtcp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4563 of file rtp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcp_do_debug_ip(), and ast_cli_entry::usage.
04564 { 04565 switch (cmd) { 04566 case CLI_INIT: 04567 e->command = "rtcp debug [off|ip]"; 04568 e->usage = 04569 "Usage: rtcp debug [off]|[ip host[:port]]\n" 04570 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04571 " specified, limit the dumped packets to those to and from\n" 04572 " the specified 'host' with optional port.\n"; 04573 return NULL; 04574 case CLI_GENERATE: 04575 return NULL; 04576 } 04577 04578 if (a->argc < 2 || a->argc > 4) 04579 return CLI_SHOWUSAGE; 04580 if (a->argc == 2) { 04581 rtcpdebug = 1; 04582 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04583 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04584 } else if (a->argc == 3) { 04585 if (strncasecmp(a->argv[2], "off", 3)) 04586 return CLI_SHOWUSAGE; 04587 rtcpdebug = 0; 04588 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04589 } else { 04590 if (strncasecmp(a->argv[2], "ip", 2)) 04591 return CLI_SHOWUSAGE; 04592 return rtcp_do_debug_ip(a); 04593 } 04594 04595 return CLI_SUCCESS; 04596 }
static char* handle_cli_rtcp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4598 of file rtp.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcp_do_debug_ip(), and ast_cli_entry::usage.
04599 { 04600 switch (cmd) { 04601 case CLI_INIT: 04602 e->command = "rtcp set debug {on|off|ip}"; 04603 e->usage = 04604 "Usage: rtcp set debug {on|off|ip host[:port]}\n" 04605 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04606 " specified, limit the dumped packets to those to and from\n" 04607 " the specified 'host' with optional port.\n"; 04608 return NULL; 04609 case CLI_GENERATE: 04610 return NULL; 04611 } 04612 04613 if (a->argc == e->args) { /* set on or off */ 04614 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04615 rtcpdebug = 1; 04616 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04617 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04618 return CLI_SUCCESS; 04619 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04620 rtcpdebug = 0; 04621 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04622 return CLI_SUCCESS; 04623 } 04624 } else if (a->argc == e->args +1) { /* ip */ 04625 return rtcp_do_debug_ip(a); 04626 } 04627 04628 return CLI_SHOWUSAGE; /* default, failure */ 04629 }
static char* handle_cli_rtcp_set_stats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4654 of file rtp.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
04655 { 04656 switch (cmd) { 04657 case CLI_INIT: 04658 e->command = "rtcp set stats {on|off}"; 04659 e->usage = 04660 "Usage: rtcp set stats {on|off}\n" 04661 " Enable/Disable dumping of RTCP stats.\n"; 04662 return NULL; 04663 case CLI_GENERATE: 04664 return NULL; 04665 } 04666 04667 if (a->argc != e->args) 04668 return CLI_SHOWUSAGE; 04669 04670 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04671 rtcpstats = 1; 04672 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04673 rtcpstats = 0; 04674 else 04675 return CLI_SHOWUSAGE; 04676 04677 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04678 return CLI_SUCCESS; 04679 }
static char* handle_cli_rtcp_stats_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4631 of file rtp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
04632 { 04633 switch (cmd) { 04634 case CLI_INIT: 04635 e->command = "rtcp stats [off]"; 04636 e->usage = 04637 "Usage: rtcp stats [off]\n" 04638 " Enable/Disable dumping of RTCP stats.\n"; 04639 return NULL; 04640 case CLI_GENERATE: 04641 return NULL; 04642 } 04643 04644 if (a->argc < 2 || a->argc > 3) 04645 return CLI_SHOWUSAGE; 04646 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04647 return CLI_SHOWUSAGE; 04648 04649 rtcpstats = (a->argc == 3) ? 0 : 1; 04650 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04651 return CLI_SUCCESS; 04652 }
static char* handle_cli_rtp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4495 of file rtp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtp_do_debug_ip(), and ast_cli_entry::usage.
04496 { 04497 switch (cmd) { 04498 case CLI_INIT: 04499 e->command = "rtp debug [off|ip]"; 04500 e->usage = 04501 "Usage: rtp debug [off]|[ip host[:port]]\n" 04502 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04503 " specified, limit the dumped packets to those to and from\n" 04504 " the specified 'host' with optional port.\n"; 04505 return NULL; 04506 case CLI_GENERATE: 04507 return NULL; 04508 } 04509 04510 if (a->argc < 2 || a->argc > 4) 04511 return CLI_SHOWUSAGE; 04512 if (a->argc == 2) { 04513 rtpdebug = 1; 04514 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04515 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04516 } else if (a->argc == 3) { 04517 if (strncasecmp(a->argv[2], "off", 3)) 04518 return CLI_SHOWUSAGE; 04519 rtpdebug = 0; 04520 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04521 } else { 04522 if (strncasecmp(a->argv[2], "ip", 2)) 04523 return CLI_SHOWUSAGE; 04524 return rtp_do_debug_ip(a); 04525 } 04526 04527 return CLI_SUCCESS; 04528 }
static char* handle_cli_rtp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4530 of file rtp.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtp_do_debug_ip(), and ast_cli_entry::usage.
04531 { 04532 switch (cmd) { 04533 case CLI_INIT: 04534 e->command = "rtp set debug {on|off|ip}"; 04535 e->usage = 04536 "Usage: rtp set debug {on|off|ip host[:port]}\n" 04537 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04538 " specified, limit the dumped packets to those to and from\n" 04539 " the specified 'host' with optional port.\n"; 04540 return NULL; 04541 case CLI_GENERATE: 04542 return NULL; 04543 } 04544 04545 if (a->argc == e->args) { /* set on or off */ 04546 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04547 rtpdebug = 1; 04548 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04549 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04550 return CLI_SUCCESS; 04551 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04552 rtpdebug = 0; 04553 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04554 return CLI_SUCCESS; 04555 } 04556 } else if (a->argc == e->args +1) { /* ip */ 04557 return rtp_do_debug_ip(a); 04558 } 04559 04560 return CLI_SHOWUSAGE; /* default, failure */ 04561 }
static char* handle_cli_stun_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4681 of file rtp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
04682 { 04683 switch (cmd) { 04684 case CLI_INIT: 04685 e->command = "stun debug [off]"; 04686 e->usage = 04687 "Usage: stun debug [off]\n" 04688 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04689 " debugging\n"; 04690 return NULL; 04691 case CLI_GENERATE: 04692 return NULL; 04693 } 04694 04695 if (a->argc < 2 || a->argc > 3) 04696 return CLI_SHOWUSAGE; 04697 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04698 return CLI_SHOWUSAGE; 04699 04700 stundebug = (a->argc == 3) ? 0 : 1; 04701 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04702 return CLI_SUCCESS; 04703 }
static char* handle_cli_stun_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4705 of file rtp.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
04706 { 04707 switch (cmd) { 04708 case CLI_INIT: 04709 e->command = "stun set debug {on|off}"; 04710 e->usage = 04711 "Usage: stun set debug {on|off}\n" 04712 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04713 " debugging\n"; 04714 return NULL; 04715 case CLI_GENERATE: 04716 return NULL; 04717 } 04718 04719 if (a->argc != e->args) 04720 return CLI_SHOWUSAGE; 04721 04722 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04723 stundebug = 1; 04724 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04725 stundebug = 0; 04726 else 04727 return CLI_SHOWUSAGE; 04728 04729 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04730 return CLI_SUCCESS; 04731 }
static double normdev_compute | ( | double | normdev, | |
double | sample, | |||
unsigned int | sample_count | |||
) | [static] |
Calculate normal deviation.
Definition at line 840 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().
00841 { 00842 normdev = normdev * sample_count + sample; 00843 sample_count++; 00844 00845 return normdev / sample_count; 00846 }
static int p2p_callback_disable | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
int ** | iod | |||
) | [static] |
Helper function to switch a channel and RTP stream out of callback mode.
Definition at line 4075 of file rtp.c.
References ast_channel_lock, ast_channel_unlock, ast_io_add(), AST_IO_IN, ast_io_remove(), ast_rtp_fd(), ast_test_flag, chan, ast_channel::fds, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, and rtpread().
04076 { 04077 ast_channel_lock(chan); 04078 04079 /* Remove the callback from the IO context */ 04080 ast_io_remove(rtp->io, iod[0]); 04081 04082 /* Restore file descriptors */ 04083 chan->fds[0] = ast_rtp_fd(rtp); 04084 ast_channel_unlock(chan); 04085 04086 /* Restore callback mode if previously used */ 04087 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 04088 rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp); 04089 04090 return 0; 04091 }
static int p2p_callback_enable | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
int ** | iod | |||
) | [static] |
Helper function that sets what an RTP structure is bridged to.
Definition at line 4094 of file rtp.c.
References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().
Referenced by bridge_p2p_loop().
04095 { 04096 rtp_bridge_lock(rtp0); 04097 rtp0->bridged = rtp1; 04098 rtp_bridge_unlock(rtp0); 04099 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 920 of file rtp.c.
References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_test_flag, ast_rtp::dtmfcount, ast_rtp::dtmfsamples, f, FLAG_DTMF_COMPENSATE, ast_frame::flags, option_debug, ast_rtp::resp, send_dtmf(), and seq.
Referenced by ast_rtp_read().
00921 { 00922 unsigned int event; 00923 char resp = 0; 00924 struct ast_frame *f = NULL; 00925 unsigned char seq; 00926 unsigned int flags; 00927 unsigned int power; 00928 00929 /* We should have at least 4 bytes in RTP data */ 00930 if (len < 4) 00931 return f; 00932 00933 /* The format of Cisco RTP DTMF packet looks like next: 00934 +0 - sequence number of DTMF RTP packet (begins from 1, 00935 wrapped to 0) 00936 +1 - set of flags 00937 +1 (bit 0) - flaps by different DTMF digits delimited by audio 00938 or repeated digit without audio??? 00939 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone 00940 then falls to 0 at its end) 00941 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...) 00942 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right 00943 by each new packet and thus provides some redudancy. 00944 00945 Sample of Cisco RTP DTMF packet is (all data in hex): 00946 19 07 00 02 12 02 20 02 00947 showing end of DTMF digit '2'. 00948 00949 The packets 00950 27 07 00 02 0A 02 20 02 00951 28 06 20 02 00 02 0A 02 00952 shows begin of new digit '2' with very short pause (20 ms) after 00953 previous digit '2'. Bit +1.0 flips at begin of new digit. 00954 00955 Cisco RTP DTMF packets comes as replacement of audio RTP packets 00956 so its uses the same sequencing and timestamping rules as replaced 00957 audio packets. Repeat interval of DTMF packets is 20 ms and not rely 00958 on audio framing parameters. Marker bit isn't used within stream of 00959 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps 00960 are not sequential at borders between DTMF and audio streams, 00961 */ 00962 00963 seq = data[0]; 00964 flags = data[1]; 00965 power = data[2]; 00966 event = data[3] & 0x1f; 00967 00968 if (option_debug > 2 || rtpdebug) 00969 ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2); 00970 if (event < 10) { 00971 resp = '0' + event; 00972 } else if (event < 11) { 00973 resp = '*'; 00974 } else if (event < 12) { 00975 resp = '#'; 00976 } else if (event < 16) { 00977 resp = 'A' + (event - 12); 00978 } else if (event < 17) { 00979 resp = 'X'; 00980 } 00981 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) { 00982 rtp->resp = resp; 00983 /* Why we should care on DTMF compensation at reception? */ 00984 if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00985 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00986 rtp->dtmfsamples = 0; 00987 } 00988 } else if ((rtp->resp == resp) && !power) { 00989 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00990 f->samples = rtp->dtmfsamples * 8; 00991 rtp->resp = 0; 00992 } else if (rtp->resp == resp) 00993 rtp->dtmfsamples += 20 * 8; 00994 rtp->dtmfcount = dtmftimeout; 00995 return f; 00996 }
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 | ||
timestamp |
Definition at line 1010 of file rtp.c.
References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_null_frame, ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), ast_rtp::dtmfcount, ast_rtp::dtmfsamples, f, FLAG_DTMF_COMPENSATE, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, ast_frame::samples, and send_dtmf().
Referenced by ast_rtp_read().
01011 { 01012 unsigned int event; 01013 unsigned int event_end; 01014 unsigned int samples; 01015 char resp = 0; 01016 struct ast_frame *f = NULL; 01017 01018 /* Figure out event, event end, and samples */ 01019 event = ntohl(*((unsigned int *)(data))); 01020 event >>= 24; 01021 event_end = ntohl(*((unsigned int *)(data))); 01022 event_end <<= 8; 01023 event_end >>= 24; 01024 samples = ntohl(*((unsigned int *)(data))); 01025 samples &= 0xFFFF; 01026 01027 /* Print out debug if turned on */ 01028 if (rtpdebug || option_debug > 2) 01029 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 01030 01031 /* Figure out what digit was pressed */ 01032 if (event < 10) { 01033 resp = '0' + event; 01034 } else if (event < 11) { 01035 resp = '*'; 01036 } else if (event < 12) { 01037 resp = '#'; 01038 } else if (event < 16) { 01039 resp = 'A' + (event - 12); 01040 } else if (event < 17) { /* Event 16: Hook flash */ 01041 resp = 'X'; 01042 } else { 01043 /* Not a supported event */ 01044 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 01045 return &ast_null_frame; 01046 } 01047 01048 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 01049 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 01050 rtp->resp = resp; 01051 rtp->dtmfcount = 0; 01052 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01053 f->len = 0; 01054 rtp->lastevent = timestamp; 01055 } 01056 } else { 01057 if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) { 01058 rtp->resp = resp; 01059 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 01060 rtp->dtmfcount = dtmftimeout; 01061 } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) { 01062 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01063 f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */ 01064 rtp->resp = 0; 01065 rtp->dtmfcount = 0; 01066 rtp->lastevent = seqno; 01067 } 01068 } 01069 01070 rtp->dtmfsamples = samples; 01071 01072 return f; 01073 }
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 1081 of file rtp.c.
References ast_debug, 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_NOTICE, ast_frame::offset, ast_frame::ptr, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read().
01082 { 01083 struct ast_frame *f = NULL; 01084 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 01085 totally help us out becuase we don't have an engine to keep it going and we are not 01086 guaranteed to have it every 20ms or anything */ 01087 if (rtpdebug) 01088 ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 01089 01090 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 01091 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 01092 ast_inet_ntoa(rtp->them.sin_addr)); 01093 ast_set_flag(rtp, FLAG_3389_WARNING); 01094 } 01095 01096 /* Must have at least one byte */ 01097 if (!len) 01098 return NULL; 01099 if (len < 24) { 01100 rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET; 01101 rtp->f.datalen = len - 1; 01102 rtp->f.offset = AST_FRIENDLY_OFFSET; 01103 memcpy(rtp->f.data.ptr, data + 1, len - 1); 01104 } else { 01105 rtp->f.data.ptr = NULL; 01106 rtp->f.offset = 0; 01107 rtp->f.datalen = 0; 01108 } 01109 rtp->f.frametype = AST_FRAME_CNG; 01110 rtp->f.subclass = data[0] & 0x7f; 01111 rtp->f.datalen = len - 1; 01112 rtp->f.samples = 0; 01113 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 01114 f = &rtp->f; 01115 return f; 01116 }
Buffer t.140 data.
rtp | ||
f | frame |
Definition at line 4925 of file rtp.c.
References rtp_red::buf_data, ast_frame::datalen, f, ast_rtp::red, rtp_red::t140, and ast_frame::ts.
Referenced by sip_write().
04926 { 04927 if (f->datalen > -1) { 04928 struct rtp_red *red = rtp->red; 04929 memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen); 04930 red->t140.datalen += f->datalen; 04931 red->t140.ts = f->ts; 04932 } 04933 }
Construct a redundant frame.
red | redundant data structure |
Definition at line 4842 of file rtp.c.
References ast_frame::data, ast_frame::datalen, rtp_red::hdrlen, rtp_red::len, rtp_red::num_gen, ast_frame::ptr, rtp_red::t140, and rtp_red::t140red.
Referenced by ast_rtp_write().
04842 { 04843 unsigned char *data = red->t140red.data.ptr; 04844 int len = 0; 04845 int i; 04846 04847 /* replace most aged generation */ 04848 if (red->len[0]) { 04849 for (i = 1; i < red->num_gen+1; i++) 04850 len += red->len[i]; 04851 04852 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 04853 } 04854 04855 /* Store length of each generation and primary data length*/ 04856 for (i = 0; i < red->num_gen; i++) 04857 red->len[i] = red->len[i+1]; 04858 red->len[i] = red->t140.datalen; 04859 04860 /* write each generation length in red header */ 04861 len = red->hdrlen; 04862 for (i = 0; i < red->num_gen; i++) 04863 len += data[i*4+3] = red->len[i]; 04864 04865 /* add primary data to buffer */ 04866 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 04867 red->t140red.datalen = len + red->t140.datalen; 04868 04869 /* no primary data and no generations to send */ 04870 if (len == red->hdrlen && !red->t140.datalen) 04871 return NULL; 04872 04873 /* reset t.140 buffer */ 04874 red->t140.datalen = 0; 04875 04876 return &red->t140red; 04877 }
static int red_write | ( | const void * | data | ) | [static] |
Write t140 redundacy frame.
data | primary data to be buffered |
Definition at line 4830 of file rtp.c.
References ast_rtp_write(), ast_rtp::red, and rtp_red::t140.
Referenced by rtp_red_init().
04831 { 04832 struct ast_rtp *rtp = (struct ast_rtp*) data; 04833 04834 ast_rtp_write(rtp, &rtp->red->t140); 04835 04836 return 1; 04837 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 906 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00907 { 00908 if (rtcpdebug == 0) 00909 return 0; 00910 if (rtcpdebugaddr.sin_addr.s_addr) { 00911 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00912 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00913 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00914 return 0; 00915 } 00916 return 1; 00917 }
static char* rtcp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 4465 of file rtp.c.
References ahp, ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, and hp.
Referenced by handle_cli_rtcp_debug_deprecated(), and handle_cli_rtcp_set_debug().
04466 { 04467 struct hostent *hp; 04468 struct ast_hostent ahp; 04469 int port = 0; 04470 char *p, *arg; 04471 04472 arg = a->argv[3]; 04473 p = strstr(arg, ":"); 04474 if (p) { 04475 *p = '\0'; 04476 p++; 04477 port = atoi(p); 04478 } 04479 hp = ast_gethostbyname(arg, &ahp); 04480 if (hp == NULL) { 04481 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04482 return CLI_FAILURE; 04483 } 04484 rtcpdebugaddr.sin_family = AF_INET; 04485 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 04486 rtcpdebugaddr.sin_port = htons(port); 04487 if (port == 0) 04488 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 04489 else 04490 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 04491 rtcpdebug = 1; 04492 return CLI_SUCCESS; 04493 }
static void rtp_bridge_lock | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 823 of file rtp.c.
References ast_mutex_lock().
Referenced by ast_rtp_get_bridged(), ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_pt_default(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_rtp_unset_m_type(), and p2p_set_bridge().
00824 { 00825 #ifdef P2P_INTENSE 00826 ast_mutex_lock(&rtp->bridge_lock); 00827 #endif 00828 return; 00829 }
static void rtp_bridge_unlock | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 831 of file rtp.c.
References ast_mutex_unlock().
Referenced by ast_rtp_get_bridged(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_pt_default(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_rtp_unset_m_type(), and p2p_set_bridge().
00832 { 00833 #ifdef P2P_INTENSE 00834 ast_mutex_unlock(&rtp->bridge_lock); 00835 #endif 00836 return; 00837 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 893 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().
00894 { 00895 if (rtpdebug == 0) 00896 return 0; 00897 if (rtpdebugaddr.sin_addr.s_addr) { 00898 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00899 && (rtpdebugaddr.sin_port != addr->sin_port)) 00900 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00901 return 0; 00902 } 00903 return 1; 00904 }
static char* rtp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 4435 of file rtp.c.
References ahp, ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, and hp.
Referenced by handle_cli_rtp_debug_deprecated(), and handle_cli_rtp_set_debug().
04436 { 04437 struct hostent *hp; 04438 struct ast_hostent ahp; 04439 int port = 0; 04440 char *p, *arg; 04441 04442 arg = a->argv[3]; 04443 p = strstr(arg, ":"); 04444 if (p) { 04445 *p = '\0'; 04446 p++; 04447 port = atoi(p); 04448 } 04449 hp = ast_gethostbyname(arg, &ahp); 04450 if (hp == NULL) { 04451 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04452 return CLI_FAILURE; 04453 } 04454 rtpdebugaddr.sin_family = AF_INET; 04455 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 04456 rtpdebugaddr.sin_port = htons(port); 04457 if (port == 0) 04458 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 04459 else 04460 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 04461 rtpdebug = 1; 04462 return CLI_SUCCESS; 04463 }
int rtp_red_init | ( | struct ast_rtp * | rtp, | |
int | ti, | |||
int * | red_data_pt, | |||
int | num_gen | |||
) |
Initalize t.140 redudancy.
rtp | ||
ti | buffer t140 for ti (msecs) before sending redundant frame | |
red_data_pt | Payloadtypes for primary- and generation-data | |
num_gen | numbers of generations (primary generation not encounted) |
Definition at line 4886 of file rtp.c.
References ast_calloc, AST_FORMAT_T140RED, AST_FRAME_TEXT, ast_sched_add(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::frametype, rtp_red::hdrlen, rtp_red::num_gen, rtp_red::prev_ts, rtp_red::pt, ast_frame::ptr, ast_rtp::red, red_write(), ast_rtp::sched, rtp_red::schedid, ast_frame::subclass, rtp_red::t140, rtp_red::t140red, rtp_red::t140red_data, rtp_red::ti, and ast_frame::ts.
Referenced by process_sdp().
04887 { 04888 struct rtp_red *r; 04889 int x; 04890 04891 if (!(r = ast_calloc(1, sizeof(struct rtp_red)))) 04892 return -1; 04893 04894 r->t140.frametype = AST_FRAME_TEXT; 04895 r->t140.subclass = AST_FORMAT_T140RED; 04896 r->t140.data.ptr = &r->buf_data; 04897 04898 r->t140.ts = 0; 04899 r->t140red = r->t140; 04900 r->t140red.data.ptr = &r->t140red_data; 04901 r->t140red.datalen = 0; 04902 r->ti = ti; 04903 r->num_gen = num_gen; 04904 r->hdrlen = num_gen * 4 + 1; 04905 r->prev_ts = 0; 04906 04907 for (x = 0; x < num_gen; x++) { 04908 r->pt[x] = red_data_pt[x]; 04909 r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 04910 r->t140red_data[x*4] = r->pt[x]; 04911 } 04912 r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */ 04913 r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp); 04914 rtp->red = r; 04915 04916 r->t140.datalen = 0; 04917 04918 return 0; 04919 }
static int rtp_socket | ( | const char * | type | ) | [static] |
Open RTP or RTCP socket for a session. Print a message on failure.
Definition at line 2386 of file rtp.c.
References ast_log(), errno, LOG_WARNING, and s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
02387 { 02388 int s = socket(AF_INET, SOCK_DGRAM, 0); 02389 if (s < 0) { 02390 if (type == NULL) 02391 type = "RTP/RTCP"; 02392 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno)); 02393 } else { 02394 long flags = fcntl(s, F_GETFL); 02395 fcntl(s, F_SETFL, flags | O_NONBLOCK); 02396 #ifdef SO_NO_CHECK 02397 if (nochecksums) 02398 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 02399 #endif 02400 } 02401 return s; 02402 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 1118 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and f.
Referenced by p2p_callback_disable().
01119 { 01120 struct ast_rtp *rtp = cbdata; 01121 struct ast_frame *f; 01122 f = ast_rtp_read(rtp); 01123 if (f) { 01124 if (rtp->callback) 01125 rtp->callback(rtp, f, rtp->data); 01126 } 01127 return 1; 01128 }
static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static] |
Definition at line 868 of file rtp.c.
References AST_CONTROL_FLASH, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_null_frame, ast_test_flag, ast_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::f, FLAG_DTMF_COMPENSATE, ast_frame::frametype, ast_frame::mallocd, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read(), process_cisco_dtmf(), and process_rfc2833().
00869 { 00870 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00871 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00872 ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00873 rtp->resp = 0; 00874 rtp->dtmfsamples = 0; 00875 return &ast_null_frame; 00876 } 00877 ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00878 if (rtp->resp == 'X') { 00879 rtp->f.frametype = AST_FRAME_CONTROL; 00880 rtp->f.subclass = AST_CONTROL_FLASH; 00881 } else { 00882 rtp->f.frametype = type; 00883 rtp->f.subclass = rtp->resp; 00884 } 00885 rtp->f.datalen = 0; 00886 rtp->f.samples = 0; 00887 rtp->f.mallocd = 0; 00888 rtp->f.src = "RTP"; 00889 return &rtp->f; 00890 00891 }
static double stddev_compute | ( | double | stddev, | |
double | sample, | |||
double | normdev, | |||
double | normdev_curent, | |||
unsigned int | sample_count | |||
) | [static] |
Definition at line 848 of file rtp.c.
References SQUARE.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().
00849 { 00850 /* 00851 for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf 00852 return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1)); 00853 we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute 00854 optimized formula 00855 */ 00856 #define SQUARE(x) ((x) * (x)) 00857 00858 stddev = sample_count * stddev; 00859 sample_count++; 00860 00861 return stddev + 00862 ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) + 00863 ( SQUARE(sample - normdev_curent) / sample_count ); 00864 00865 #undef SQUARE 00866 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
helper function to print attribute names
Definition at line 393 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().
00394 { 00395 switch (msg) { 00396 case STUN_MAPPED_ADDRESS: 00397 return "Mapped Address"; 00398 case STUN_RESPONSE_ADDRESS: 00399 return "Response Address"; 00400 case STUN_CHANGE_REQUEST: 00401 return "Change Request"; 00402 case STUN_SOURCE_ADDRESS: 00403 return "Source Address"; 00404 case STUN_CHANGED_ADDRESS: 00405 return "Changed Address"; 00406 case STUN_USERNAME: 00407 return "Username"; 00408 case STUN_PASSWORD: 00409 return "Password"; 00410 case STUN_MESSAGE_INTEGRITY: 00411 return "Message Integrity"; 00412 case STUN_ERROR_CODE: 00413 return "Error Code"; 00414 case STUN_UNKNOWN_ATTRIBUTES: 00415 return "Unknown Attributes"; 00416 case STUN_REFLECTED_FROM: 00417 return "Reflected From"; 00418 } 00419 return "Non-RFC3489 Attribute"; 00420 }
static int stun_get_mapped | ( | struct stun_attr * | attr, | |
void * | arg | |||
) | [static] |
Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_response when called from ast_stun_request.
Definition at line 610 of file rtp.c.
References stun_addr::addr, stun_attr::attr, stun_attr::len, stun_addr::port, and STUN_MAPPED_ADDRESS.
Referenced by ast_stun_request().
00611 { 00612 struct stun_addr *addr = (struct stun_addr *)(attr + 1); 00613 struct sockaddr_in *sa = (struct sockaddr_in *)arg; 00614 00615 if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8) 00616 return 1; /* not us. */ 00617 sa->sin_port = addr->port; 00618 sa->sin_addr.s_addr = addr->addr; 00619 return 0; 00620 }
static int stun_handle_packet | ( | int | s, | |
struct sockaddr_in * | src, | |||
unsigned char * | data, | |||
size_t | len, | |||
stun_cb_f * | stun_cb, | |||
void * | arg | |||
) | [static] |
handle an incoming STUN message.
Do some basic sanity checks on packet size and content, try to extract a bit of information, and possibly reply. At the moment this only processes BIND requests, and returns the externally visible address of the request. If a callback is specified, invoke it with the attribute.
Definition at line 512 of file rtp.c.
References append_attr_address(), append_attr_string(), ast_debug, ast_verbose, stun_attr::attr, stun_header::id, stun_header::ies, stun_header::msglen, stun_header::msgtype, 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(), and ast_stun_request().
00514 { 00515 struct stun_header *hdr = (struct stun_header *)data; 00516 struct stun_attr *attr; 00517 struct stun_state st; 00518 int ret = STUN_IGNORE; 00519 int x; 00520 00521 /* On entry, 'len' is the length of the udp payload. After the 00522 * initial checks it becomes the size of unprocessed options, 00523 * while 'data' is advanced accordingly. 00524 */ 00525 if (len < sizeof(struct stun_header)) { 00526 ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header)); 00527 return -1; 00528 } 00529 len -= sizeof(struct stun_header); 00530 data += sizeof(struct stun_header); 00531 x = ntohs(hdr->msglen); /* len as advertised in the message */ 00532 if (stundebug) 00533 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x); 00534 if (x > len) { 00535 ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len); 00536 } else 00537 len = x; 00538 memset(&st, 0, sizeof(st)); 00539 while (len) { 00540 if (len < sizeof(struct stun_attr)) { 00541 ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr)); 00542 break; 00543 } 00544 attr = (struct stun_attr *)data; 00545 /* compute total attribute length */ 00546 x = ntohs(attr->len) + sizeof(struct stun_attr); 00547 if (x > len) { 00548 ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len); 00549 break; 00550 } 00551 if (stun_cb) 00552 stun_cb(attr, arg); 00553 if (stun_process_attr(&st, attr)) { 00554 ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00555 break; 00556 } 00557 /* Clear attribute id: in case previous entry was a string, 00558 * this will act as the terminator for the string. 00559 */ 00560 attr->attr = 0; 00561 data += x; 00562 len -= x; 00563 } 00564 /* Null terminate any string. 00565 * XXX NOTE, we write past the size of the buffer passed by the 00566 * caller, so this is potentially dangerous. The only thing that 00567 * saves us is that usually we read the incoming message in a 00568 * much larger buffer in the struct ast_rtp 00569 */ 00570 *data = '\0'; 00571 00572 /* Now prepare to generate a reply, which at the moment is done 00573 * only for properly formed (len == 0) STUN_BINDREQ messages. 00574 */ 00575 if (len == 0) { 00576 unsigned char respdata[1024]; 00577 struct stun_header *resp = (struct stun_header *)respdata; 00578 int resplen = 0; /* len excluding header */ 00579 int respleft = sizeof(respdata) - sizeof(struct stun_header); 00580 00581 resp->id = hdr->id; 00582 resp->msgtype = 0; 00583 resp->msglen = 0; 00584 attr = (struct stun_attr *)resp->ies; 00585 switch (ntohs(hdr->msgtype)) { 00586 case STUN_BINDREQ: 00587 if (stundebug) 00588 ast_verbose("STUN Bind Request, username: %s\n", 00589 st.username ? st.username : "<none>"); 00590 if (st.username) 00591 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00592 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00593 resp->msglen = htons(resplen); 00594 resp->msgtype = htons(STUN_BINDRESP); 00595 stun_send(s, src, resp); 00596 ret = STUN_ACCEPT; 00597 break; 00598 default: 00599 if (stundebug) 00600 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00601 } 00602 } 00603 return ret; 00604 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
helper function to print message names
Definition at line 373 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00374 { 00375 switch (msg) { 00376 case STUN_BINDREQ: 00377 return "Binding Request"; 00378 case STUN_BINDRESP: 00379 return "Binding Response"; 00380 case STUN_BINDERR: 00381 return "Binding Error Response"; 00382 case STUN_SECREQ: 00383 return "Shared Secret Request"; 00384 case STUN_SECRESP: 00385 return "Shared Secret Response"; 00386 case STUN_SECERR: 00387 return "Shared Secret Error Response"; 00388 } 00389 return "Non-RFC3489 Message"; 00390 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 428 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().
00429 { 00430 if (stundebug) 00431 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00432 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00433 switch (ntohs(attr->attr)) { 00434 case STUN_USERNAME: 00435 state->username = (const char *) (attr->value); 00436 break; 00437 case STUN_PASSWORD: 00438 state->password = (const char *) (attr->value); 00439 break; 00440 default: 00441 if (stundebug) 00442 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00443 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00444 } 00445 return 0; 00446 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
helper function to generate a random request id
Definition at line 489 of file rtp.c.
References ast_random(), stun_trans_id::id, and stun_header::id.
Referenced by ast_stun_request().
00490 { 00491 int x; 00492 for (x = 0; x < 4; x++) 00493 req->id.id[x] = ast_random(); 00494 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
wrapper to send an STUN message
Definition at line 482 of file rtp.c.
References stun_header::msglen.
Referenced by ast_stun_request(), and stun_handle_packet().
00483 { 00484 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00485 (struct sockaddr *)dst, sizeof(*dst)); 00486 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 710 of file rtp.c.
References sec.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00711 { 00712 unsigned int sec, usec, frac; 00713 sec = when.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00714 usec = when.tv_usec; 00715 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00716 *msw = sec; 00717 *lsw = frac; 00718 }
struct ast_cli_entry cli_rtcp_debug_deprecated = { .handler = handle_cli_rtcp_debug_deprecated , .summary = "Enable/Disable RTCP debugging" ,__VA_ARGS__ } [static] |
struct ast_cli_entry cli_rtcp_stats_deprecated = { .handler = handle_cli_rtcp_stats_deprecated , .summary = "Enable/Disable RTCP stats" ,__VA_ARGS__ } [static] |
struct ast_cli_entry cli_rtp[] [static] |
struct ast_cli_entry cli_rtp_debug_deprecated = { .handler = handle_cli_rtp_debug_deprecated , .summary = "Enable/Disable RTP debugging" ,__VA_ARGS__ } [static] |
struct ast_cli_entry cli_stun_debug_deprecated = { .handler = handle_cli_stun_debug_deprecated , .summary = "Enable/Disable STUN debugging" ,__VA_ARGS__ } [static] |
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
struct { ... } mimeTypes[] [static] |
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
struct rtpPayloadType payloadType |
Definition at line 1866 of file rtp.c.
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
struct sockaddr_in rtcpdebugaddr [static] |
int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static] |
struct sockaddr_in rtpdebugaddr [static] |
int rtpend = 31000 [static] |
int rtpstart = 5000 [static] |
struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static] |
Mapping between Asterisk codecs and rtp payload types.
Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s: also, our own choices for dynamic payload types. This is our master table for transmission
See http://www.iana.org/assignments/rtp-parameters for a list of assigned values
Definition at line 1911 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* subtype |
char* type |
Definition at line 1867 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), aji_handle_presence(), amixer_max(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), eventhandler(), g723_len(), h264_decap(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), osp_lookup(), parse_information(), parse_setup(), realtime_require_handler(), require_curl(), require_odbc(), setamixer(), sla_load_config(), and yyparse().