#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 | frame_list |
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 (150 * (8000 / 1000)) |
#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. | |
void | ast_rtp_change_source (struct ast_rtp *rtp) |
Indicate that we need to set the marker bit and change the ssrc. | |
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) |
Indicate that we need to set the marker bit. | |
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_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt) |
set potential alternate source for RTP media | |
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_frame * | create_dtmf_frame (struct ast_rtp *rtp, enum ast_frame_type type) |
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 void | process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct frame_list *frames) |
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 deprecated) |
static int | rtp_get_rate (int subclass) |
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 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 (150 * (8000 / 1000)) |
#define FLAG_3389_WARNING (1 << 0) |
#define FLAG_CALLBACK_MODE (1 << 6) |
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 224 of file rtp.c.
Referenced by ast_rtp_setdtmfcompensate(), create_dtmf_frame(), process_cisco_dtmf(), and process_rfc2833().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 220 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 217 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 218 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 219 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 221 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 355 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 365 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 370 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 2789 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().
02790 { 02791 *found = 1; 02792 02793 if (!strcasecmp(qos, "remote_maxjitter")) 02794 return rtp->rtcp->reported_maxjitter * 1000.0; 02795 if (!strcasecmp(qos, "remote_minjitter")) 02796 return rtp->rtcp->reported_minjitter * 1000.0; 02797 if (!strcasecmp(qos, "remote_normdevjitter")) 02798 return rtp->rtcp->reported_normdev_jitter * 1000.0; 02799 if (!strcasecmp(qos, "remote_stdevjitter")) 02800 return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0; 02801 02802 if (!strcasecmp(qos, "local_maxjitter")) 02803 return rtp->rtcp->maxrxjitter * 1000.0; 02804 if (!strcasecmp(qos, "local_minjitter")) 02805 return rtp->rtcp->minrxjitter * 1000.0; 02806 if (!strcasecmp(qos, "local_normdevjitter")) 02807 return rtp->rtcp->normdev_rxjitter * 1000.0; 02808 if (!strcasecmp(qos, "local_stdevjitter")) 02809 return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0; 02810 02811 if (!strcasecmp(qos, "maxrtt")) 02812 return rtp->rtcp->maxrtt * 1000.0; 02813 if (!strcasecmp(qos, "minrtt")) 02814 return rtp->rtcp->minrtt * 1000.0; 02815 if (!strcasecmp(qos, "normdevrtt")) 02816 return rtp->rtcp->normdevrtt * 1000.0; 02817 if (!strcasecmp(qos, "stdevrtt")) 02818 return sqrt(rtp->rtcp->stdevrtt) * 1000.0; 02819 02820 *found = 0; 02821 02822 return 0.0; 02823 }
static char* __ast_rtp_get_quality | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2992 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().
02993 { 02994 /* 02995 *ssrc our ssrc 02996 *themssrc their ssrc 02997 *lp lost packets 02998 *rxjitter our calculated jitter(rx) 02999 *rxcount no. received packets 03000 *txjitter reported jitter of the other end 03001 *txcount transmitted packets 03002 *rlp remote lost packets 03003 *rtt round trip time 03004 */ 03005 03006 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 03007 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 03008 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 03009 rtp->ssrc, 03010 rtp->themssrc, 03011 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 03012 rtp->rxjitter, 03013 rtp->rxcount, 03014 (double)rtp->rtcp->reported_jitter / 65536.0, 03015 rtp->txcount, 03016 rtp->rtcp->reported_lost, 03017 rtp->rtcp->rtt 03018 ); 03019 } else { 03020 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;", 03021 rtp->ssrc, 03022 rtp->themssrc, 03023 rtp->rxjitter, 03024 rtp->rxcount, 03025 rtp->txcount 03026 ); 03027 } 03028 03029 return rtp->rtcp->quality; 03030 }
static char* __ast_rtp_get_quality_jitter | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2871 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().
02872 { 02873 /* 02874 *ssrc our ssrc 02875 *themssrc their ssrc 02876 *lp lost packets 02877 *rxjitter our calculated jitter(rx) 02878 *rxcount no. received packets 02879 *txjitter reported jitter of the other end 02880 *txcount transmitted packets 02881 *rlp remote lost packets 02882 *rtt round trip time 02883 */ 02884 #define RTCP_JITTER_FORMAT1 \ 02885 "minrxjitter=%f;" \ 02886 "maxrxjitter=%f;" \ 02887 "avgrxjitter=%f;" \ 02888 "stdevrxjitter=%f;" \ 02889 "reported_minjitter=%f;" \ 02890 "reported_maxjitter=%f;" \ 02891 "reported_avgjitter=%f;" \ 02892 "reported_stdevjitter=%f;" 02893 02894 #define RTCP_JITTER_FORMAT2 \ 02895 "rxjitter=%f;" 02896 02897 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 02898 snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1, 02899 rtp->rtcp->minrxjitter, 02900 rtp->rtcp->maxrxjitter, 02901 rtp->rtcp->normdev_rxjitter, 02902 sqrt(rtp->rtcp->stdev_rxjitter), 02903 rtp->rtcp->reported_minjitter, 02904 rtp->rtcp->reported_maxjitter, 02905 rtp->rtcp->reported_normdev_jitter, 02906 sqrt(rtp->rtcp->reported_stdev_jitter) 02907 ); 02908 } else { 02909 snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2, 02910 rtp->rxjitter 02911 ); 02912 } 02913 02914 return rtp->rtcp->quality_jitter; 02915 02916 #undef RTCP_JITTER_FORMAT1 02917 #undef RTCP_JITTER_FORMAT2 02918 }
static char* __ast_rtp_get_quality_loss | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2920 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().
02921 { 02922 unsigned int lost; 02923 unsigned int extended; 02924 unsigned int expected; 02925 int fraction; 02926 02927 #define RTCP_LOSS_FORMAT1 \ 02928 "minrxlost=%f;" \ 02929 "maxrxlost=%f;" \ 02930 "avgrxlostr=%f;" \ 02931 "stdevrxlost=%f;" \ 02932 "reported_minlost=%f;" \ 02933 "reported_maxlost=%f;" \ 02934 "reported_avglost=%f;" \ 02935 "reported_stdevlost=%f;" 02936 02937 #define RTCP_LOSS_FORMAT2 \ 02938 "lost=%d;" \ 02939 "expected=%d;" 02940 02941 if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) { 02942 snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1, 02943 rtp->rtcp->minrxlost, 02944 rtp->rtcp->maxrxlost, 02945 rtp->rtcp->normdev_rxlost, 02946 sqrt(rtp->rtcp->stdev_rxlost), 02947 rtp->rtcp->reported_minlost, 02948 rtp->rtcp->reported_maxlost, 02949 rtp->rtcp->reported_normdev_lost, 02950 sqrt(rtp->rtcp->reported_stdev_lost) 02951 ); 02952 } else { 02953 extended = rtp->cycles + rtp->lastrxseqno; 02954 expected = extended - rtp->seedrxseqno + 1; 02955 if (rtp->rxcount > expected) 02956 expected += rtp->rxcount - expected; 02957 lost = expected - rtp->rxcount; 02958 02959 if (!expected || lost <= 0) 02960 fraction = 0; 02961 else 02962 fraction = (lost << 8) / expected; 02963 02964 snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2, 02965 lost, 02966 expected 02967 ); 02968 } 02969 02970 return rtp->rtcp->quality_loss; 02971 02972 #undef RTCP_LOSS_FORMAT1 02973 #undef RTCP_LOSS_FORMAT2 02974 }
static char* __ast_rtp_get_quality_rtt | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2976 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().
02977 { 02978 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 02979 snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;", 02980 rtp->rtcp->minrtt, 02981 rtp->rtcp->maxrtt, 02982 rtp->rtcp->normdevrtt, 02983 sqrt(rtp->rtcp->stdevrtt) 02984 ); 02985 } else { 02986 snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available"); 02987 } 02988 02989 return rtp->rtcp->quality_rtt; 02990 }
static int __ast_rtp_reload | ( | int | reload | ) | [static] |
Definition at line 4859 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().
04860 { 04861 struct ast_config *cfg; 04862 const char *s; 04863 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04864 04865 if ((cfg = ast_config_load2("rtp.conf", "rtp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 04866 return 0; 04867 04868 rtpstart = 5000; 04869 rtpend = 31000; 04870 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04871 strictrtp = STRICT_RTP_OPEN; 04872 if (cfg) { 04873 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 04874 rtpstart = atoi(s); 04875 if (rtpstart < 1024) 04876 rtpstart = 1024; 04877 if (rtpstart > 65535) 04878 rtpstart = 65535; 04879 } 04880 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 04881 rtpend = atoi(s); 04882 if (rtpend < 1024) 04883 rtpend = 1024; 04884 if (rtpend > 65535) 04885 rtpend = 65535; 04886 } 04887 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 04888 rtcpinterval = atoi(s); 04889 if (rtcpinterval == 0) 04890 rtcpinterval = 0; /* Just so we're clear... it's zero */ 04891 if (rtcpinterval < RTCP_MIN_INTERVALMS) 04892 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 04893 if (rtcpinterval > RTCP_MAX_INTERVALMS) 04894 rtcpinterval = RTCP_MAX_INTERVALMS; 04895 } 04896 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 04897 #ifdef SO_NO_CHECK 04898 if (ast_false(s)) 04899 nochecksums = 1; 04900 else 04901 nochecksums = 0; 04902 #else 04903 if (ast_false(s)) 04904 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 04905 #endif 04906 } 04907 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 04908 dtmftimeout = atoi(s); 04909 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) { 04910 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 04911 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 04912 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04913 }; 04914 } 04915 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) { 04916 strictrtp = ast_true(s); 04917 } 04918 ast_config_destroy(cfg); 04919 } 04920 if (rtpstart >= rtpend) { 04921 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 04922 rtpstart = 5000; 04923 rtpend = 31000; 04924 } 04925 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 04926 return 0; 04927 }
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 468 of file rtp.c.
References stun_addr::addr.
Referenced by stun_handle_packet().
00469 { 00470 int size = sizeof(**attr) + 8; 00471 struct stun_addr *addr; 00472 if (*left > size) { 00473 (*attr)->attr = htons(attrval); 00474 (*attr)->len = htons(8); 00475 addr = (struct stun_addr *)((*attr)->value); 00476 addr->unused = 0; 00477 addr->family = 0x01; 00478 addr->port = sock_in->sin_port; 00479 addr->addr = sock_in->sin_addr.s_addr; 00480 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00481 *len += size; 00482 *left -= size; 00483 } 00484 }
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 454 of file rtp.c.
Referenced by ast_stun_request(), and stun_handle_packet().
00455 { 00456 int size = sizeof(**attr) + strlen(s); 00457 if (*left > size) { 00458 (*attr)->attr = htons(attrval); 00459 (*attr)->len = htons(strlen(s)); 00460 memcpy((*attr)->value, s, strlen(s)); 00461 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00462 *len += size; 00463 *left -= size; 00464 } 00465 }
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 742 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00743 { 00744 unsigned int interval; 00745 /*! \todo XXX Do a more reasonable calculation on this one 00746 * Look in RFC 3550 Section A.7 for an example*/ 00747 interval = rtcpinterval; 00748 return interval; 00749 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 730 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 2497 of file rtp.c.
References ast_calloc, ast_free, rtp_socket(), and ast_rtcp::s.
Referenced by ast_rtp_new_with_bindaddr().
02498 { 02499 struct ast_rtcp *rtcp; 02500 02501 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 02502 return NULL; 02503 rtcp->s = rtp_socket("RTCP"); 02504 rtcp->us.sin_family = AF_INET; 02505 rtcp->them.sin_family = AF_INET; 02506 rtcp->schedid = -1; 02507 02508 if (rtcp->s < 0) { 02509 ast_free(rtcp); 02510 return NULL; 02511 } 02512 02513 return rtcp; 02514 }
Definition at line 1187 of file rtp.c.
References ast_rtcp::accumulated_transit, ast_rtcp::altthem, 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().
01188 { 01189 socklen_t len; 01190 int position, i, packetwords; 01191 int res; 01192 struct sockaddr_in sock_in; 01193 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 01194 unsigned int *rtcpheader; 01195 int pt; 01196 struct timeval now; 01197 unsigned int length; 01198 int rc; 01199 double rttsec; 01200 uint64_t rtt = 0; 01201 unsigned int dlsr; 01202 unsigned int lsr; 01203 unsigned int msw; 01204 unsigned int lsw; 01205 unsigned int comp; 01206 struct ast_frame *f = &ast_null_frame; 01207 01208 double reported_jitter; 01209 double reported_normdev_jitter_current; 01210 double normdevrtt_current; 01211 double reported_lost; 01212 double reported_normdev_lost_current; 01213 01214 if (!rtp || !rtp->rtcp) 01215 return &ast_null_frame; 01216 01217 len = sizeof(sock_in); 01218 01219 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 01220 0, (struct sockaddr *)&sock_in, &len); 01221 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 01222 01223 if (res < 0) { 01224 ast_assert(errno != EBADF); 01225 if (errno != EAGAIN) { 01226 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 01227 return NULL; 01228 } 01229 return &ast_null_frame; 01230 } 01231 01232 packetwords = res / 4; 01233 01234 if (rtp->nat) { 01235 /* Send to whoever sent to us */ 01236 if (((rtp->rtcp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01237 (rtp->rtcp->them.sin_port != sock_in.sin_port)) && 01238 ((rtp->rtcp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01239 (rtp->rtcp->altthem.sin_port != sock_in.sin_port))) { 01240 memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them)); 01241 if (option_debug || rtpdebug) 01242 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)); 01243 } 01244 } 01245 01246 ast_debug(1, "Got RTCP report of %d bytes\n", res); 01247 01248 /* Process a compound packet */ 01249 position = 0; 01250 while (position < packetwords) { 01251 i = position; 01252 length = ntohl(rtcpheader[i]); 01253 pt = (length & 0xff0000) >> 16; 01254 rc = (length & 0x1f000000) >> 24; 01255 length &= 0xffff; 01256 01257 if ((i + length) > packetwords) { 01258 if (option_debug || rtpdebug) 01259 ast_log(LOG_DEBUG, "RTCP Read too short\n"); 01260 return &ast_null_frame; 01261 } 01262 01263 if (rtcp_debug_test_addr(&sock_in)) { 01264 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port)); 01265 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 01266 ast_verbose("Reception reports: %d\n", rc); 01267 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 01268 } 01269 01270 i += 2; /* Advance past header and ssrc */ 01271 01272 switch (pt) { 01273 case RTCP_PT_SR: 01274 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 01275 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 01276 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 01277 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 01278 01279 if (rtcp_debug_test_addr(&sock_in)) { 01280 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 01281 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 01282 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 01283 } 01284 i += 5; 01285 if (rc < 1) 01286 break; 01287 /* Intentional fall through */ 01288 case RTCP_PT_RR: 01289 /* Don't handle multiple reception reports (rc > 1) yet */ 01290 /* Calculate RTT per RFC */ 01291 gettimeofday(&now, NULL); 01292 timeval2ntp(now, &msw, &lsw); 01293 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 01294 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 01295 lsr = ntohl(rtcpheader[i + 4]); 01296 dlsr = ntohl(rtcpheader[i + 5]); 01297 rtt = comp - lsr - dlsr; 01298 01299 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 01300 sess->ee_delay = (eedelay * 1000) / 65536; */ 01301 if (rtt < 4294) { 01302 rtt = (rtt * 1000000) >> 16; 01303 } else { 01304 rtt = (rtt * 1000) >> 16; 01305 rtt *= 1000; 01306 } 01307 rtt = rtt / 1000.; 01308 rttsec = rtt / 1000.; 01309 rtp->rtcp->rtt = rttsec; 01310 01311 if (comp - dlsr >= lsr) { 01312 rtp->rtcp->accumulated_transit += rttsec; 01313 01314 if (rtp->rtcp->rtt_count == 0) 01315 rtp->rtcp->minrtt = rttsec; 01316 01317 if (rtp->rtcp->maxrtt<rttsec) 01318 rtp->rtcp->maxrtt = rttsec; 01319 01320 if (rtp->rtcp->minrtt>rttsec) 01321 rtp->rtcp->minrtt = rttsec; 01322 01323 normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count); 01324 01325 rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count); 01326 01327 rtp->rtcp->normdevrtt = normdevrtt_current; 01328 01329 rtp->rtcp->rtt_count++; 01330 } else if (rtcp_debug_test_addr(&sock_in)) { 01331 ast_verbose("Internal RTCP NTP clock skew detected: " 01332 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 01333 "diff=%d\n", 01334 lsr, comp, dlsr, dlsr / 65536, 01335 (dlsr % 65536) * 1000 / 65536, 01336 dlsr - (comp - lsr)); 01337 } 01338 } 01339 01340 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 01341 reported_jitter = (double) rtp->rtcp->reported_jitter; 01342 01343 if (rtp->rtcp->reported_jitter_count == 0) 01344 rtp->rtcp->reported_minjitter = reported_jitter; 01345 01346 if (reported_jitter < rtp->rtcp->reported_minjitter) 01347 rtp->rtcp->reported_minjitter = reported_jitter; 01348 01349 if (reported_jitter > rtp->rtcp->reported_maxjitter) 01350 rtp->rtcp->reported_maxjitter = reported_jitter; 01351 01352 reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count); 01353 01354 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); 01355 01356 rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current; 01357 01358 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 01359 01360 reported_lost = (double) rtp->rtcp->reported_lost; 01361 01362 /* using same counter as for jitter */ 01363 if (rtp->rtcp->reported_jitter_count == 0) 01364 rtp->rtcp->reported_minlost = reported_lost; 01365 01366 if (reported_lost < rtp->rtcp->reported_minlost) 01367 rtp->rtcp->reported_minlost = reported_lost; 01368 01369 if (reported_lost > rtp->rtcp->reported_maxlost) 01370 rtp->rtcp->reported_maxlost = reported_lost; 01371 01372 reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count); 01373 01374 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); 01375 01376 rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current; 01377 01378 rtp->rtcp->reported_jitter_count++; 01379 01380 if (rtcp_debug_test_addr(&sock_in)) { 01381 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 01382 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 01383 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 01384 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 01385 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 01386 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 01387 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 01388 if (rtt) 01389 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 01390 } 01391 01392 if (rtt) { 01393 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n" 01394 "PT: %d(%s)\r\n" 01395 "ReceptionReports: %d\r\n" 01396 "SenderSSRC: %u\r\n" 01397 "FractionLost: %ld\r\n" 01398 "PacketsLost: %d\r\n" 01399 "HighestSequence: %ld\r\n" 01400 "SequenceNumberCycles: %ld\r\n" 01401 "IAJitter: %u\r\n" 01402 "LastSR: %lu.%010lu\r\n" 01403 "DLSR: %4.4f(sec)\r\n" 01404 "RTT: %llu(sec)\r\n", 01405 ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), 01406 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01407 rc, 01408 rtcpheader[i + 1], 01409 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01410 rtp->rtcp->reported_lost, 01411 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01412 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01413 rtp->rtcp->reported_jitter, 01414 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01415 ntohl(rtcpheader[i + 5])/65536.0, 01416 (unsigned long long)rtt); 01417 } else { 01418 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n" 01419 "PT: %d(%s)\r\n" 01420 "ReceptionReports: %d\r\n" 01421 "SenderSSRC: %u\r\n" 01422 "FractionLost: %ld\r\n" 01423 "PacketsLost: %d\r\n" 01424 "HighestSequence: %ld\r\n" 01425 "SequenceNumberCycles: %ld\r\n" 01426 "IAJitter: %u\r\n" 01427 "LastSR: %lu.%010lu\r\n" 01428 "DLSR: %4.4f(sec)\r\n", 01429 ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), 01430 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01431 rc, 01432 rtcpheader[i + 1], 01433 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01434 rtp->rtcp->reported_lost, 01435 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01436 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01437 rtp->rtcp->reported_jitter, 01438 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, 01439 ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01440 ntohl(rtcpheader[i + 5])/65536.0); 01441 } 01442 break; 01443 case RTCP_PT_FUR: 01444 if (rtcp_debug_test_addr(&sock_in)) 01445 ast_verbose("Received an RTCP Fast Update Request\n"); 01446 rtp->f.frametype = AST_FRAME_CONTROL; 01447 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 01448 rtp->f.datalen = 0; 01449 rtp->f.samples = 0; 01450 rtp->f.mallocd = 0; 01451 rtp->f.src = "RTP"; 01452 f = &rtp->f; 01453 break; 01454 case RTCP_PT_SDES: 01455 if (rtcp_debug_test_addr(&sock_in)) 01456 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01457 break; 01458 case RTCP_PT_BYE: 01459 if (rtcp_debug_test_addr(&sock_in)) 01460 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01461 break; 01462 default: 01463 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)); 01464 break; 01465 } 01466 position += (length + 1); 01467 } 01468 rtp->rtcp->rtcp_info = 1; 01469 return f; 01470 }
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 3304 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
03305 { 03306 struct ast_rtp *rtp = data; 03307 int res; 03308 03309 rtp->rtcp->sendfur = 1; 03310 res = ast_rtcp_write(data); 03311 03312 return res; 03313 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 3562 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().
03563 { 03564 struct ast_rtp *rtp = (struct ast_rtp *)data; 03565 int res; 03566 03567 if (!rtp || !rtp->rtcp) 03568 return 0; 03569 03570 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 03571 res = ast_rtcp_write_sr(data); 03572 else 03573 res = ast_rtcp_write_rr(data); 03574 03575 return res; 03576 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recipient's report.
Definition at line 3449 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().
03450 { 03451 struct ast_rtp *rtp = (struct ast_rtp *)data; 03452 int res; 03453 int len = 32; 03454 unsigned int lost; 03455 unsigned int extended; 03456 unsigned int expected; 03457 unsigned int expected_interval; 03458 unsigned int received_interval; 03459 int lost_interval; 03460 struct timeval now; 03461 unsigned int *rtcpheader; 03462 char bdata[1024]; 03463 struct timeval dlsr; 03464 int fraction; 03465 03466 double rxlost_current; 03467 03468 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 03469 return 0; 03470 03471 if (!rtp->rtcp->them.sin_addr.s_addr) { 03472 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 03473 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03474 return 0; 03475 } 03476 03477 extended = rtp->cycles + rtp->lastrxseqno; 03478 expected = extended - rtp->seedrxseqno + 1; 03479 lost = expected - rtp->rxcount; 03480 expected_interval = expected - rtp->rtcp->expected_prior; 03481 rtp->rtcp->expected_prior = expected; 03482 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 03483 rtp->rtcp->received_prior = rtp->rxcount; 03484 lost_interval = expected_interval - received_interval; 03485 03486 if (lost_interval <= 0) 03487 rtp->rtcp->rxlost = 0; 03488 else rtp->rtcp->rxlost = rtp->rtcp->rxlost; 03489 if (rtp->rtcp->rxlost_count == 0) 03490 rtp->rtcp->minrxlost = rtp->rtcp->rxlost; 03491 if (lost_interval < rtp->rtcp->minrxlost) 03492 rtp->rtcp->minrxlost = rtp->rtcp->rxlost; 03493 if (lost_interval > rtp->rtcp->maxrxlost) 03494 rtp->rtcp->maxrxlost = rtp->rtcp->rxlost; 03495 03496 rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count); 03497 rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count); 03498 rtp->rtcp->normdev_rxlost = rxlost_current; 03499 rtp->rtcp->rxlost_count++; 03500 03501 if (expected_interval == 0 || lost_interval <= 0) 03502 fraction = 0; 03503 else 03504 fraction = (lost_interval << 8) / expected_interval; 03505 gettimeofday(&now, NULL); 03506 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 03507 rtcpheader = (unsigned int *)bdata; 03508 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 03509 rtcpheader[1] = htonl(rtp->ssrc); 03510 rtcpheader[2] = htonl(rtp->themssrc); 03511 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 03512 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 03513 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 03514 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 03515 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 03516 03517 if (rtp->rtcp->sendfur) { 03518 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 03519 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 03520 len += 8; 03521 rtp->rtcp->sendfur = 0; 03522 } 03523 03524 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 03525 it can change mid call, and SDES can't) */ 03526 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 03527 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 03528 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 03529 len += 12; 03530 03531 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 03532 03533 if (res < 0) { 03534 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 03535 /* Remove the scheduler */ 03536 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03537 return 0; 03538 } 03539 03540 rtp->rtcp->rr_count++; 03541 03542 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 03543 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 03544 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 03545 " IA jitter: %.4f\n" 03546 " Their last SR: %u\n" 03547 " DLSR: %4.4f (sec)\n\n", 03548 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 03549 ntohs(rtp->rtcp->them.sin_port), 03550 rtp->ssrc, rtp->themssrc, fraction, lost, 03551 rtp->rxjitter, 03552 rtp->rtcp->themrxlsr, 03553 (double)(ntohl(rtcpheader[7])/65536.0)); 03554 } 03555 03556 return res; 03557 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 3316 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().
03317 { 03318 struct ast_rtp *rtp = (struct ast_rtp *)data; 03319 int res; 03320 int len = 0; 03321 struct timeval now; 03322 unsigned int now_lsw; 03323 unsigned int now_msw; 03324 unsigned int *rtcpheader; 03325 unsigned int lost; 03326 unsigned int extended; 03327 unsigned int expected; 03328 unsigned int expected_interval; 03329 unsigned int received_interval; 03330 int lost_interval; 03331 int fraction; 03332 struct timeval dlsr; 03333 char bdata[512]; 03334 03335 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 03336 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 03337 return 0; 03338 03339 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 03340 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 03341 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03342 return 0; 03343 } 03344 03345 gettimeofday(&now, NULL); 03346 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 03347 rtcpheader = (unsigned int *)bdata; 03348 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 03349 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 03350 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 03351 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 03352 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 03353 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 03354 len += 28; 03355 03356 extended = rtp->cycles + rtp->lastrxseqno; 03357 expected = extended - rtp->seedrxseqno + 1; 03358 if (rtp->rxcount > expected) 03359 expected += rtp->rxcount - expected; 03360 lost = expected - rtp->rxcount; 03361 expected_interval = expected - rtp->rtcp->expected_prior; 03362 rtp->rtcp->expected_prior = expected; 03363 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 03364 rtp->rtcp->received_prior = rtp->rxcount; 03365 lost_interval = expected_interval - received_interval; 03366 if (expected_interval == 0 || lost_interval <= 0) 03367 fraction = 0; 03368 else 03369 fraction = (lost_interval << 8) / expected_interval; 03370 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 03371 rtcpheader[7] = htonl(rtp->themssrc); 03372 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 03373 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 03374 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 03375 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 03376 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 03377 len += 24; 03378 03379 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 03380 03381 if (rtp->rtcp->sendfur) { 03382 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 03383 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 03384 len += 8; 03385 rtp->rtcp->sendfur = 0; 03386 } 03387 03388 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 03389 /* it can change mid call, and SDES can't) */ 03390 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 03391 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 03392 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 03393 len += 12; 03394 03395 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 03396 if (res < 0) { 03397 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)); 03398 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03399 return 0; 03400 } 03401 03402 /* FIXME Don't need to get a new one */ 03403 gettimeofday(&rtp->rtcp->txlsr, NULL); 03404 rtp->rtcp->sr_count++; 03405 03406 rtp->rtcp->lastsrtxcount = rtp->txcount; 03407 03408 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 03409 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 03410 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 03411 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 03412 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 03413 ast_verbose(" Sent packets: %u\n", rtp->txcount); 03414 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 03415 ast_verbose(" Report block:\n"); 03416 ast_verbose(" Fraction lost: %u\n", fraction); 03417 ast_verbose(" Cumulative loss: %u\n", lost); 03418 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 03419 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 03420 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 03421 } 03422 manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n" 03423 "OurSSRC: %u\r\n" 03424 "SentNTP: %u.%010u\r\n" 03425 "SentRTP: %u\r\n" 03426 "SentPackets: %u\r\n" 03427 "SentOctets: %u\r\n" 03428 "ReportBlock:\r\n" 03429 "FractionLost: %u\r\n" 03430 "CumulativeLoss: %u\r\n" 03431 "IAJitter: %.4f\r\n" 03432 "TheirLastSR: %u\r\n" 03433 "DLSR: %4.4f (sec)\r\n", 03434 ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), 03435 rtp->ssrc, 03436 (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096, 03437 rtp->lastts, 03438 rtp->txcount, 03439 rtp->txoctetcount, 03440 fraction, 03441 lost, 03442 rtp->rxjitter, 03443 rtp->rtcp->themrxlsr, 03444 (double)(ntohl(rtcpheader[12])/65536.0)); 03445 return res; 03446 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 501 of file rtp.c.
Referenced by process_sdp().
00502 { 00503 return sizeof(struct ast_rtp); 00504 }
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 4392 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.
04393 { 04394 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 04395 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 04396 struct ast_rtp *tp0 = NULL, *tp1 = NULL; /* Text RTP channels */ 04397 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 04398 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; 04399 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; 04400 enum ast_bridge_result res = AST_BRIDGE_FAILED; 04401 int codec0 = 0, codec1 = 0; 04402 void *pvt0 = NULL, *pvt1 = NULL; 04403 04404 /* Lock channels */ 04405 ast_channel_lock(c0); 04406 while (ast_channel_trylock(c1)) { 04407 ast_channel_unlock(c0); 04408 usleep(1); 04409 ast_channel_lock(c0); 04410 } 04411 04412 /* Ensure neither channel got hungup during lock avoidance */ 04413 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 04414 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 04415 ast_channel_unlock(c0); 04416 ast_channel_unlock(c1); 04417 return AST_BRIDGE_FAILED; 04418 } 04419 04420 /* Find channel driver interfaces */ 04421 if (!(pr0 = get_proto(c0))) { 04422 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 04423 ast_channel_unlock(c0); 04424 ast_channel_unlock(c1); 04425 return AST_BRIDGE_FAILED; 04426 } 04427 if (!(pr1 = get_proto(c1))) { 04428 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 04429 ast_channel_unlock(c0); 04430 ast_channel_unlock(c1); 04431 return AST_BRIDGE_FAILED; 04432 } 04433 04434 /* Get channel specific interface structures */ 04435 pvt0 = c0->tech_pvt; 04436 pvt1 = c1->tech_pvt; 04437 04438 /* Get audio and video interface (if native bridge is possible) */ 04439 audio_p0_res = pr0->get_rtp_info(c0, &p0); 04440 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 04441 text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 04442 audio_p1_res = pr1->get_rtp_info(c1, &p1); 04443 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 04444 text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 04445 04446 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 04447 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 04448 audio_p0_res = AST_RTP_GET_FAILED; 04449 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 04450 audio_p1_res = AST_RTP_GET_FAILED; 04451 04452 /* Check if a bridge is possible (partial/native) */ 04453 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 04454 /* Somebody doesn't want to play... */ 04455 ast_channel_unlock(c0); 04456 ast_channel_unlock(c1); 04457 return AST_BRIDGE_FAILED_NOWARN; 04458 } 04459 04460 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 04461 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 04462 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 04463 audio_p0_res = AST_RTP_TRY_PARTIAL; 04464 } 04465 04466 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 04467 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 04468 audio_p1_res = AST_RTP_TRY_PARTIAL; 04469 } 04470 04471 /* If both sides are not using the same method of DTMF transmission 04472 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 04473 * -------------------------------------------------- 04474 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 04475 * |-----------|------------|-----------------------| 04476 * | Inband | False | True | 04477 * | RFC2833 | True | True | 04478 * | SIP INFO | False | False | 04479 * -------------------------------------------------- 04480 * However, if DTMF from both channels is being monitored by the core, then 04481 * we can still do packet-to-packet bridging, because passing through the 04482 * core will handle DTMF mode translation. 04483 */ 04484 if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 04485 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 04486 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 04487 ast_channel_unlock(c0); 04488 ast_channel_unlock(c1); 04489 return AST_BRIDGE_FAILED_NOWARN; 04490 } 04491 audio_p0_res = AST_RTP_TRY_PARTIAL; 04492 audio_p1_res = AST_RTP_TRY_PARTIAL; 04493 } 04494 04495 /* If we need to feed frames into the core don't do a P2P bridge */ 04496 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 04497 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 04498 ast_channel_unlock(c0); 04499 ast_channel_unlock(c1); 04500 return AST_BRIDGE_FAILED_NOWARN; 04501 } 04502 04503 /* Get codecs from both sides */ 04504 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 04505 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 04506 if (codec0 && codec1 && !(codec0 & codec1)) { 04507 /* Hey, we can't do native bridging if both parties speak different codecs */ 04508 ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 04509 ast_channel_unlock(c0); 04510 ast_channel_unlock(c1); 04511 return AST_BRIDGE_FAILED_NOWARN; 04512 } 04513 04514 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 04515 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 04516 struct ast_format_list fmt0, fmt1; 04517 04518 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 04519 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 04520 ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n"); 04521 ast_channel_unlock(c0); 04522 ast_channel_unlock(c1); 04523 return AST_BRIDGE_FAILED_NOWARN; 04524 } 04525 /* They must also be using the same packetization */ 04526 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 04527 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 04528 if (fmt0.cur_ms != fmt1.cur_ms) { 04529 ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n"); 04530 ast_channel_unlock(c0); 04531 ast_channel_unlock(c1); 04532 return AST_BRIDGE_FAILED_NOWARN; 04533 } 04534 04535 ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 04536 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 04537 } else { 04538 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04539 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 04540 } 04541 04542 return res; 04543 }
void ast_rtp_change_source | ( | struct ast_rtp * | rtp | ) |
Indicate that we need to set the marker bit and change the ssrc.
Definition at line 2650 of file rtp.c.
References ast_debug, ast_random(), ast_rtp::set_marker_bit, and ast_rtp::ssrc.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), and skinny_indicate().
02651 { 02652 if (rtp) { 02653 unsigned int ssrc = ast_random(); 02654 02655 rtp->set_marker_bit = 1; 02656 ast_debug(3, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc); 02657 rtp->ssrc = ssrc; 02658 } 02659 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
get format from predefined dynamic payload format
Definition at line 3784 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp_a_audio().
03785 { 03786 if (pt < 0 || pt >= MAX_RTP_PT) 03787 return 0; /* bogus payload type */ 03788 03789 if (static_RTP_PT[pt].isAstFormat) 03790 return static_RTP_PT[pt].code; 03791 else 03792 return 0; 03793 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Get codec preference.
Definition at line 3779 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp_a_audio().
03780 { 03781 return &rtp->pref; 03782 }
void ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Set codec preference.
Definition at line 3733 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_a_audio(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().
03734 { 03735 struct ast_format_list current_format_old, current_format_new; 03736 03737 /* if no packets have been sent through this session yet, then 03738 * changing preferences does not require any extra work 03739 */ 03740 if (rtp->lasttxformat == 0) { 03741 rtp->pref = *prefs; 03742 return; 03743 } 03744 03745 current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 03746 03747 rtp->pref = *prefs; 03748 03749 current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 03750 03751 /* if the framing desired for the current format has changed, we may have to create 03752 * or adjust the smoother for this session 03753 */ 03754 if ((current_format_new.inc_ms != 0) && 03755 (current_format_new.cur_ms != current_format_old.cur_ms)) { 03756 int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms; 03757 03758 if (rtp->smoother) { 03759 ast_smoother_reconfigure(rtp->smoother, new_size); 03760 if (option_debug) { 03761 ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size); 03762 } 03763 } else { 03764 if (!(rtp->smoother = ast_smoother_new(new_size))) { 03765 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 03766 return; 03767 } 03768 if (current_format_new.flags) { 03769 ast_smoother_set_flags(rtp->smoother, current_format_new.flags); 03770 } 03771 if (option_debug) { 03772 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 03773 } 03774 } 03775 } 03776 03777 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Destroy RTP session
Definition at line 3063 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().
03064 { 03065 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 03066 /*Print some info on the call here */ 03067 ast_verbose(" RTP-stats\n"); 03068 ast_verbose("* Our Receiver:\n"); 03069 ast_verbose(" SSRC: %u\n", rtp->themssrc); 03070 ast_verbose(" Received packets: %u\n", rtp->rxcount); 03071 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0); 03072 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 03073 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 03074 ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0); 03075 ast_verbose("* Our Sender:\n"); 03076 ast_verbose(" SSRC: %u\n", rtp->ssrc); 03077 ast_verbose(" Sent packets: %u\n", rtp->txcount); 03078 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0); 03079 ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0); 03080 ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0); 03081 ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0); 03082 } 03083 03084 manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n" 03085 "ReceivedPackets: %u\r\n" 03086 "LostPackets: %u\r\n" 03087 "Jitter: %.4f\r\n" 03088 "Transit: %.4f\r\n" 03089 "RRCount: %u\r\n", 03090 rtp->themssrc, 03091 rtp->rxcount, 03092 rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0, 03093 rtp->rxjitter, 03094 rtp->rxtransit, 03095 rtp->rtcp ? rtp->rtcp->rr_count : 0); 03096 manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n" 03097 "SentPackets: %u\r\n" 03098 "LostPackets: %u\r\n" 03099 "Jitter: %u\r\n" 03100 "SRCount: %u\r\n" 03101 "RTT: %f\r\n", 03102 rtp->ssrc, 03103 rtp->txcount, 03104 rtp->rtcp ? rtp->rtcp->reported_lost : 0, 03105 rtp->rtcp ? rtp->rtcp->reported_jitter : 0, 03106 rtp->rtcp ? rtp->rtcp->sr_count : 0, 03107 rtp->rtcp ? rtp->rtcp->rtt : 0); 03108 if (rtp->smoother) 03109 ast_smoother_free(rtp->smoother); 03110 if (rtp->ioid) 03111 ast_io_remove(rtp->io, rtp->ioid); 03112 if (rtp->s > -1) 03113 close(rtp->s); 03114 if (rtp->rtcp) { 03115 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03116 close(rtp->rtcp->s); 03117 ast_free(rtp->rtcp); 03118 rtp->rtcp=NULL; 03119 } 03120 #ifdef P2P_INTENSE 03121 ast_mutex_destroy(&rtp->bridge_lock); 03122 #endif 03123 ast_free(rtp); 03124 }
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 2111 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.
02112 { 02113 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 02114 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 02115 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 02116 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 02117 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; 02118 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; 02119 int srccodec, destcodec, nat_active = 0; 02120 02121 /* Lock channels */ 02122 ast_channel_lock(c0); 02123 if (c1) { 02124 while (ast_channel_trylock(c1)) { 02125 ast_channel_unlock(c0); 02126 usleep(1); 02127 ast_channel_lock(c0); 02128 } 02129 } 02130 02131 /* Find channel driver interfaces */ 02132 destpr = get_proto(c0); 02133 if (c1) 02134 srcpr = get_proto(c1); 02135 if (!destpr) { 02136 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name); 02137 ast_channel_unlock(c0); 02138 if (c1) 02139 ast_channel_unlock(c1); 02140 return -1; 02141 } 02142 if (!srcpr) { 02143 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>"); 02144 ast_channel_unlock(c0); 02145 if (c1) 02146 ast_channel_unlock(c1); 02147 return -1; 02148 } 02149 02150 /* Get audio, video and text interface (if native bridge is possible) */ 02151 audio_dest_res = destpr->get_rtp_info(c0, &destp); 02152 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED; 02153 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED; 02154 if (srcpr) { 02155 audio_src_res = srcpr->get_rtp_info(c1, &srcp); 02156 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED; 02157 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED; 02158 } 02159 02160 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 02161 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) { 02162 /* Somebody doesn't want to play... */ 02163 ast_channel_unlock(c0); 02164 if (c1) 02165 ast_channel_unlock(c1); 02166 return -1; 02167 } 02168 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) 02169 srccodec = srcpr->get_codec(c1); 02170 else 02171 srccodec = 0; 02172 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) 02173 destcodec = destpr->get_codec(c0); 02174 else 02175 destcodec = 0; 02176 /* Ensure we have at least one matching codec */ 02177 if (srcp && !(srccodec & destcodec)) { 02178 ast_channel_unlock(c0); 02179 ast_channel_unlock(c1); 02180 return 0; 02181 } 02182 /* Consider empty media as non-existent */ 02183 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 02184 srcp = NULL; 02185 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02186 nat_active = 1; 02187 /* Bridge media early */ 02188 if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active)) 02189 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 02190 ast_channel_unlock(c0); 02191 if (c1) 02192 ast_channel_unlock(c1); 02193 ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 02194 return 0; 02195 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 725 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().
00726 { 00727 return rtp->s; 00728 }
Definition at line 2704 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().
02705 { 02706 struct ast_rtp *bridged = NULL; 02707 02708 rtp_bridge_lock(rtp); 02709 bridged = rtp->bridged; 02710 rtp_bridge_unlock(rtp); 02711 02712 return bridged; 02713 }
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 2333 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().
02335 { 02336 int pt; 02337 02338 rtp_bridge_lock(rtp); 02339 02340 *astFormats = *nonAstFormats = 0; 02341 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02342 if (rtp->current_RTP_PT[pt].isAstFormat) { 02343 *astFormats |= rtp->current_RTP_PT[pt].code; 02344 } else { 02345 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 02346 } 02347 } 02348 02349 rtp_bridge_unlock(rtp); 02350 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2686 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().
02687 { 02688 if ((them->sin_family != AF_INET) || 02689 (them->sin_port != rtp->them.sin_port) || 02690 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02691 them->sin_family = AF_INET; 02692 them->sin_port = rtp->them.sin_port; 02693 them->sin_addr = rtp->them.sin_addr; 02694 return 1; 02695 } 02696 return 0; 02697 }
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 2825 of file rtp.c.
References __ast_rtp_get_qos().
Referenced by acf_channel_read().
02826 { 02827 double value; 02828 int found; 02829 02830 value = __ast_rtp_get_qos(rtp, qos, &found); 02831 02832 if (!found) 02833 return -1; 02834 02835 snprintf(buf, buflen, "%.0lf", value); 02836 02837 return 0; 02838 }
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 2759 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().
02760 { 02761 if (rtp == NULL) { 02762 if (option_debug > 1) 02763 ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n"); 02764 return 0; 02765 } 02766 if (option_debug > 1 && rtp->rtcp == NULL) { 02767 ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n"); 02768 } 02769 02770 switch (value) { 02771 case AST_RTP_TXCOUNT: 02772 return (unsigned int) rtp->txcount; 02773 case AST_RTP_RXCOUNT: 02774 return (unsigned int) rtp->rxcount; 02775 case AST_RTP_TXJITTER: 02776 return (unsigned int) (rtp->rxjitter * 100.0); 02777 case AST_RTP_RXJITTER: 02778 return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0); 02779 case AST_RTP_RXPLOSS: 02780 return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0; 02781 case AST_RTP_TXPLOSS: 02782 return rtp->rtcp ? rtp->rtcp->reported_lost : 0; 02783 case AST_RTP_RTT: 02784 return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0); 02785 } 02786 return 0; /* To make the compiler happy */ 02787 }
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 3032 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().
03033 { 03034 if (qual && rtp) { 03035 qual->local_ssrc = rtp->ssrc; 03036 qual->local_jitter = rtp->rxjitter; 03037 qual->local_count = rtp->rxcount; 03038 qual->remote_ssrc = rtp->themssrc; 03039 qual->remote_count = rtp->txcount; 03040 03041 if (rtp->rtcp) { 03042 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 03043 qual->remote_lostpackets = rtp->rtcp->reported_lost; 03044 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 03045 qual->rtt = rtp->rtcp->rtt; 03046 } 03047 } 03048 03049 switch (qtype) { 03050 case RTPQOS_SUMMARY: 03051 return __ast_rtp_get_quality(rtp); 03052 case RTPQOS_JITTER: 03053 return __ast_rtp_get_quality_jitter(rtp); 03054 case RTPQOS_LOSS: 03055 return __ast_rtp_get_quality_loss(rtp); 03056 case RTPQOS_RTT: 03057 return __ast_rtp_get_quality_rtt(rtp); 03058 } 03059 03060 return NULL; 03061 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 785 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by check_rtp_timeout().
00786 { 00787 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00788 return 0; 00789 return rtp->rtpholdtimeout; 00790 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 793 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by check_rtp_timeout().
00794 { 00795 return rtp->rtpkeepalive; 00796 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 777 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by check_rtp_timeout().
00778 { 00779 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00780 return 0; 00781 return rtp->rtptimeout; 00782 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2699 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 813 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00814 { 00815 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00816 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 4935 of file rtp.c.
References __ast_rtp_reload(), ast_cli_register_multiple(), and cli_rtp.
Referenced by main().
04936 { 04937 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 04938 __ast_rtp_reload(0); 04939 }
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 2374 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().
02375 { 02376 int pt = 0; 02377 02378 rtp_bridge_lock(rtp); 02379 02380 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 02381 code == rtp->rtp_lookup_code_cache_code) { 02382 /* Use our cached mapping, to avoid the overhead of the loop below */ 02383 pt = rtp->rtp_lookup_code_cache_result; 02384 rtp_bridge_unlock(rtp); 02385 return pt; 02386 } 02387 02388 /* Check the dynamic list first */ 02389 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02390 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 02391 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02392 rtp->rtp_lookup_code_cache_code = code; 02393 rtp->rtp_lookup_code_cache_result = pt; 02394 rtp_bridge_unlock(rtp); 02395 return pt; 02396 } 02397 } 02398 02399 /* Then the static list */ 02400 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02401 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 02402 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02403 rtp->rtp_lookup_code_cache_code = code; 02404 rtp->rtp_lookup_code_cache_result = pt; 02405 rtp_bridge_unlock(rtp); 02406 return pt; 02407 } 02408 } 02409 02410 rtp_bridge_unlock(rtp); 02411 02412 return -1; 02413 }
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 2434 of file rtp.c.
References ast_copy_string(), ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.
Referenced by process_sdp().
02436 { 02437 int format; 02438 unsigned len; 02439 char *end = buf; 02440 char *start = buf; 02441 02442 if (!buf || !size) 02443 return NULL; 02444 02445 snprintf(end, size, "0x%x (", capability); 02446 02447 len = strlen(end); 02448 end += len; 02449 size -= len; 02450 start = end; 02451 02452 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 02453 if (capability & format) { 02454 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 02455 02456 snprintf(end, size, "%s|", name); 02457 len = strlen(end); 02458 end += len; 02459 size -= len; 02460 } 02461 } 02462 02463 if (start == end) 02464 ast_copy_string(start, "nothing)", size); 02465 else if (size > 1) 02466 *(end -1) = ')'; 02467 02468 return buf; 02469 }
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 2415 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().
02417 { 02418 unsigned int i; 02419 02420 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02421 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 02422 if (isAstFormat && 02423 (code == AST_FORMAT_G726_AAL2) && 02424 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02425 return "G726-32"; 02426 else 02427 return mimeTypes[i].subtype; 02428 } 02429 } 02430 02431 return ""; 02432 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 2352 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().
02353 { 02354 struct rtpPayloadType result; 02355 02356 result.isAstFormat = result.code = 0; 02357 02358 if (pt < 0 || pt >= MAX_RTP_PT) 02359 return result; /* bogus payload type */ 02360 02361 /* Start with negotiated codecs */ 02362 rtp_bridge_lock(rtp); 02363 result = rtp->current_RTP_PT[pt]; 02364 rtp_bridge_unlock(rtp); 02365 02366 /* If it doesn't exist, check our static RTP type list, just in case */ 02367 if (!result.code) 02368 result = static_RTP_PT[pt]; 02369 02370 return result; 02371 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 2197 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().
02198 { 02199 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 02200 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 02201 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 02202 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 02203 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; 02204 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; 02205 int srccodec, destcodec; 02206 02207 /* Lock channels */ 02208 ast_channel_lock(dest); 02209 while (ast_channel_trylock(src)) { 02210 ast_channel_unlock(dest); 02211 usleep(1); 02212 ast_channel_lock(dest); 02213 } 02214 02215 /* Find channel driver interfaces */ 02216 if (!(destpr = get_proto(dest))) { 02217 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name); 02218 ast_channel_unlock(dest); 02219 ast_channel_unlock(src); 02220 return 0; 02221 } 02222 if (!(srcpr = get_proto(src))) { 02223 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name); 02224 ast_channel_unlock(dest); 02225 ast_channel_unlock(src); 02226 return 0; 02227 } 02228 02229 /* Get audio and video interface (if native bridge is possible) */ 02230 audio_dest_res = destpr->get_rtp_info(dest, &destp); 02231 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 02232 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED; 02233 audio_src_res = srcpr->get_rtp_info(src, &srcp); 02234 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 02235 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED; 02236 02237 /* Ensure we have at least one matching codec */ 02238 if (srcpr->get_codec) 02239 srccodec = srcpr->get_codec(src); 02240 else 02241 srccodec = 0; 02242 if (destpr->get_codec) 02243 destcodec = destpr->get_codec(dest); 02244 else 02245 destcodec = 0; 02246 02247 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 02248 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)) { 02249 /* Somebody doesn't want to play... */ 02250 ast_channel_unlock(dest); 02251 ast_channel_unlock(src); 02252 return 0; 02253 } 02254 ast_rtp_pt_copy(destp, srcp); 02255 if (vdestp && vsrcp) 02256 ast_rtp_pt_copy(vdestp, vsrcp); 02257 if (tdestp && tsrcp) 02258 ast_rtp_pt_copy(tdestp, tsrcp); 02259 if (media) { 02260 /* Bridge early */ 02261 if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02262 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 02263 } 02264 ast_channel_unlock(dest); 02265 ast_channel_unlock(src); 02266 ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 02267 return 1; 02268 }
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 2629 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
02630 { 02631 struct in_addr ia; 02632 02633 memset(&ia, 0, sizeof(ia)); 02634 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02635 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
reload rtp configuration
Definition at line 2520 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().
02521 { 02522 #ifdef P2P_INTENSE 02523 ast_mutex_init(&rtp->bridge_lock); 02524 #endif 02525 02526 rtp->them.sin_family = AF_INET; 02527 rtp->us.sin_family = AF_INET; 02528 rtp->ssrc = ast_random(); 02529 rtp->seqno = ast_random() & 0xffff; 02530 ast_set_flag(rtp, FLAG_HAS_DTMF); 02531 rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN); 02532 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Indicate that we need to set the marker bit.
Definition at line 2642 of file rtp.c.
References ast_debug, and ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_answer(), sip_indicate(), sip_write(), and skinny_indicate().
02643 { 02644 if (rtp) { 02645 rtp->set_marker_bit = 1; 02646 ast_debug(3, "Setting the marker bit due to a source update\n"); 02647 } 02648 }
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 2534 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().
02535 { 02536 struct ast_rtp *rtp; 02537 int x; 02538 int startplace; 02539 02540 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 02541 return NULL; 02542 02543 ast_rtp_new_init(rtp); 02544 02545 rtp->s = rtp_socket("RTP"); 02546 if (rtp->s < 0) 02547 goto fail; 02548 if (sched && rtcpenable) { 02549 rtp->sched = sched; 02550 rtp->rtcp = ast_rtcp_new(); 02551 } 02552 02553 /* 02554 * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well. 02555 * Start from a random (even, by RTP spec) port number, and 02556 * iterate until success or no ports are available. 02557 * Note that the requirement of RTP port being even, or RTCP being the 02558 * next one, cannot be enforced in presence of a NAT box because the 02559 * mapping is not under our control. 02560 */ 02561 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 02562 x = x & ~1; /* make it an even number */ 02563 startplace = x; /* remember the starting point */ 02564 /* this is constant across the loop */ 02565 rtp->us.sin_addr = addr; 02566 if (rtp->rtcp) 02567 rtp->rtcp->us.sin_addr = addr; 02568 for (;;) { 02569 rtp->us.sin_port = htons(x); 02570 if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) { 02571 /* bind succeeded, if no rtcp then we are done */ 02572 if (!rtp->rtcp) 02573 break; 02574 /* have rtcp, try to bind it */ 02575 rtp->rtcp->us.sin_port = htons(x + 1); 02576 if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) 02577 break; /* success again, we are really done */ 02578 /* 02579 * RTCP bind failed, so close and recreate the 02580 * already bound RTP socket for the next round. 02581 */ 02582 close(rtp->s); 02583 rtp->s = rtp_socket("RTP"); 02584 if (rtp->s < 0) 02585 goto fail; 02586 } 02587 /* 02588 * If we get here, there was an error in one of the bind() 02589 * calls, so make sure it is nothing unexpected. 02590 */ 02591 if (errno != EADDRINUSE) { 02592 /* We got an error that wasn't expected, abort! */ 02593 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 02594 goto fail; 02595 } 02596 /* 02597 * One of the ports is in use. For the next iteration, 02598 * increment by two and handle wraparound. 02599 * If we reach the starting point, then declare failure. 02600 */ 02601 x += 2; 02602 if (x > rtpend) 02603 x = (rtpstart + 1) & ~1; 02604 if (x == startplace) { 02605 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 02606 goto fail; 02607 } 02608 } 02609 rtp->sched = sched; 02610 rtp->io = io; 02611 if (callbackmode) { 02612 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 02613 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 02614 } 02615 ast_rtp_pt_default(rtp); 02616 return rtp; 02617 02618 fail: 02619 if (rtp->s >= 0) 02620 close(rtp->s); 02621 if (rtp->rtcp) { 02622 close(rtp->rtcp->s); 02623 ast_free(rtp->rtcp); 02624 } 02625 ast_free(rtp); 02626 return NULL; 02627 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register an RTP channel client.
Definition at line 3890 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().
03891 { 03892 struct ast_rtp_protocol *cur; 03893 03894 AST_RWLIST_WRLOCK(&protos); 03895 AST_RWLIST_TRAVERSE(&protos, cur, list) { 03896 if (!strcmp(cur->type, proto->type)) { 03897 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 03898 AST_RWLIST_UNLOCK(&protos); 03899 return -1; 03900 } 03901 } 03902 AST_RWLIST_INSERT_HEAD(&protos, proto, list); 03903 AST_RWLIST_UNLOCK(&protos); 03904 03905 return 0; 03906 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister an RTP channel client.
Definition at line 3882 of file rtp.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by load_module(), and unload_module().
03883 { 03884 AST_RWLIST_WRLOCK(&protos); 03885 AST_RWLIST_REMOVE(&protos, proto, list); 03886 AST_RWLIST_UNLOCK(&protos); 03887 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 2035 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().
02036 { 02037 int i; 02038 02039 if (!rtp) 02040 return; 02041 02042 rtp_bridge_lock(rtp); 02043 02044 for (i = 0; i < MAX_RTP_PT; ++i) { 02045 rtp->current_RTP_PT[i].isAstFormat = 0; 02046 rtp->current_RTP_PT[i].code = 0; 02047 } 02048 02049 rtp->rtp_lookup_code_cache_isAstFormat = 0; 02050 rtp->rtp_lookup_code_cache_code = 0; 02051 rtp->rtp_lookup_code_cache_result = 0; 02052 02053 rtp_bridge_unlock(rtp); 02054 }
Copy payload types between RTP structures.
Definition at line 2075 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().
02076 { 02077 unsigned int i; 02078 02079 rtp_bridge_lock(dest); 02080 rtp_bridge_lock(src); 02081 02082 for (i = 0; i < MAX_RTP_PT; ++i) { 02083 dest->current_RTP_PT[i].isAstFormat = 02084 src->current_RTP_PT[i].isAstFormat; 02085 dest->current_RTP_PT[i].code = 02086 src->current_RTP_PT[i].code; 02087 } 02088 dest->rtp_lookup_code_cache_isAstFormat = 0; 02089 dest->rtp_lookup_code_cache_code = 0; 02090 dest->rtp_lookup_code_cache_result = 0; 02091 02092 rtp_bridge_unlock(src); 02093 rtp_bridge_unlock(dest); 02094 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 2056 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.
02057 { 02058 int i; 02059 02060 rtp_bridge_lock(rtp); 02061 02062 /* Initialize to default payload types */ 02063 for (i = 0; i < MAX_RTP_PT; ++i) { 02064 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 02065 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 02066 } 02067 02068 rtp->rtp_lookup_code_cache_isAstFormat = 0; 02069 rtp->rtp_lookup_code_cache_code = 0; 02070 rtp->rtp_lookup_code_cache_result = 0; 02071 02072 rtp_bridge_unlock(rtp); 02073 }
Write RTP packet with audio or video media frames into UDP packet.
Definition at line 3614 of file rtp.c.
References ast_debug, AST_FORMAT_G722, 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(), rtp_get_rate(), 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().
03615 { 03616 unsigned char *rtpheader; 03617 int hdrlen = 12; 03618 int res; 03619 unsigned int ms; 03620 int pred; 03621 int mark = 0; 03622 int rate = rtp_get_rate(f->subclass) / 1000; 03623 03624 if (f->subclass == AST_FORMAT_G722) { 03625 f->samples /= 2; 03626 } 03627 03628 if (rtp->sending_digit) { 03629 return 0; 03630 } 03631 03632 ms = calc_txstamp(rtp, &f->delivery); 03633 /* Default prediction */ 03634 if (f->frametype == AST_FRAME_VOICE) { 03635 pred = rtp->lastts + f->samples; 03636 03637 /* Re-calculate last TS */ 03638 rtp->lastts = rtp->lastts + ms * rate; 03639 if (ast_tvzero(f->delivery)) { 03640 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 03641 and if so, go with our prediction */ 03642 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 03643 rtp->lastts = pred; 03644 else { 03645 ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 03646 mark = 1; 03647 } 03648 } 03649 } else if (f->frametype == AST_FRAME_VIDEO) { 03650 mark = f->subclass & 0x1; 03651 pred = rtp->lastovidtimestamp + f->samples; 03652 /* Re-calculate last TS */ 03653 rtp->lastts = rtp->lastts + ms * 90; 03654 /* If it's close to our prediction, go for it */ 03655 if (ast_tvzero(f->delivery)) { 03656 if (abs(rtp->lastts - pred) < 7200) { 03657 rtp->lastts = pred; 03658 rtp->lastovidtimestamp += f->samples; 03659 } else { 03660 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); 03661 rtp->lastovidtimestamp = rtp->lastts; 03662 } 03663 } 03664 } else { 03665 pred = rtp->lastotexttimestamp + f->samples; 03666 /* Re-calculate last TS */ 03667 rtp->lastts = rtp->lastts + ms; 03668 /* If it's close to our prediction, go for it */ 03669 if (ast_tvzero(f->delivery)) { 03670 if (abs(rtp->lastts - pred) < 7200) { 03671 rtp->lastts = pred; 03672 rtp->lastotexttimestamp += f->samples; 03673 } else { 03674 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); 03675 rtp->lastotexttimestamp = rtp->lastts; 03676 } 03677 } 03678 } 03679 03680 /* If we have been explicitly told to set the marker bit do so */ 03681 if (rtp->set_marker_bit) { 03682 mark = 1; 03683 rtp->set_marker_bit = 0; 03684 } 03685 03686 /* If the timestamp for non-digit packets has moved beyond the timestamp 03687 for digits, update the digit timestamp. 03688 */ 03689 if (rtp->lastts > rtp->lastdigitts) 03690 rtp->lastdigitts = rtp->lastts; 03691 03692 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 03693 rtp->lastts = f->ts * rate; 03694 03695 /* Get a pointer to the header */ 03696 rtpheader = (unsigned char *)(f->data.ptr - hdrlen); 03697 03698 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 03699 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 03700 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 03701 03702 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 03703 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 03704 if (res < 0) { 03705 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 03706 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)); 03707 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 03708 /* Only give this error message once if we are not RTP debugging */ 03709 if (option_debug || rtpdebug) 03710 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)); 03711 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 03712 } 03713 } else { 03714 rtp->txcount++; 03715 rtp->txoctetcount +=(res - hdrlen); 03716 03717 /* Do not schedule RR if RTCP isn't run */ 03718 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 03719 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 03720 } 03721 } 03722 03723 if (rtp_debug_test_addr(&rtp->them)) 03724 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03725 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 03726 } 03727 03728 rtp->seqno++; 03729 03730 return 0; 03731 }
Definition at line 1581 of file rtp.c.
References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, 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_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, 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_samp2tv(), ast_sched_add(), ast_set_flag, ast_tv(), ast_tvdiff_ms(), ast_verbose, bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, create_dtmf_frame(), ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, f, ast_rtp::f, FLAG_NAT_ACTIVE, frames, 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_get_rate(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_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().
01582 { 01583 int res; 01584 struct sockaddr_in sock_in; 01585 socklen_t len; 01586 unsigned int seqno; 01587 int version; 01588 int payloadtype; 01589 int hdrlen = 12; 01590 int padding; 01591 int mark; 01592 int ext; 01593 int cc; 01594 unsigned int ssrc; 01595 unsigned int timestamp; 01596 unsigned int *rtpheader; 01597 struct rtpPayloadType rtpPT; 01598 struct ast_rtp *bridged = NULL; 01599 int prev_seqno; 01600 struct frame_list frames; 01601 01602 /* If time is up, kill it */ 01603 if (rtp->sending_digit) 01604 ast_rtp_senddigit_continuation(rtp); 01605 01606 len = sizeof(sock_in); 01607 01608 /* Cache where the header will go */ 01609 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01610 0, (struct sockaddr *)&sock_in, &len); 01611 01612 /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */ 01613 if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { 01614 /* Copy over address that this packet was received on */ 01615 memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address)); 01616 /* Now move over to actually protecting the RTP port */ 01617 rtp->strict_rtp_state = STRICT_RTP_CLOSED; 01618 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)); 01619 } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { 01620 /* If the address we previously learned doesn't match the address this packet came in on simply drop it */ 01621 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)) { 01622 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)); 01623 return &ast_null_frame; 01624 } 01625 } 01626 01627 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01628 if (res < 0) { 01629 ast_assert(errno != EBADF); 01630 if (errno != EAGAIN) { 01631 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01632 return NULL; 01633 } 01634 return &ast_null_frame; 01635 } 01636 01637 if (res < hdrlen) { 01638 ast_log(LOG_WARNING, "RTP Read too short\n"); 01639 return &ast_null_frame; 01640 } 01641 01642 /* Get fields */ 01643 seqno = ntohl(rtpheader[0]); 01644 01645 /* Check RTP version */ 01646 version = (seqno & 0xC0000000) >> 30; 01647 if (!version) { 01648 /* If the two high bits are 0, this might be a 01649 * STUN message, so process it. stun_handle_packet() 01650 * answers to requests, and it returns STUN_ACCEPT 01651 * if the request is valid. 01652 */ 01653 if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) && 01654 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01655 memcpy(&rtp->them, &sock_in, sizeof(rtp->them)); 01656 } 01657 return &ast_null_frame; 01658 } 01659 01660 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01661 /* If we don't have the other side's address, then ignore this */ 01662 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01663 return &ast_null_frame; 01664 #endif 01665 01666 /* Send to whoever send to us if NAT is turned on */ 01667 if (rtp->nat) { 01668 if (((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01669 (rtp->them.sin_port != sock_in.sin_port)) && 01670 ((rtp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01671 (rtp->altthem.sin_port != sock_in.sin_port))) { 01672 rtp->them = sock_in; 01673 if (rtp->rtcp) { 01674 int h = 0; 01675 memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them)); 01676 h = ntohs(rtp->them.sin_port); 01677 rtp->rtcp->them.sin_port = htons(h + 1); 01678 } 01679 rtp->rxseqno = 0; 01680 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01681 if (option_debug || rtpdebug) 01682 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)); 01683 } 01684 } 01685 01686 /* If we are bridged to another RTP stream, send direct */ 01687 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01688 return &ast_null_frame; 01689 01690 if (version != 2) 01691 return &ast_null_frame; 01692 01693 payloadtype = (seqno & 0x7f0000) >> 16; 01694 padding = seqno & (1 << 29); 01695 mark = seqno & (1 << 23); 01696 ext = seqno & (1 << 28); 01697 cc = (seqno & 0xF000000) >> 24; 01698 seqno &= 0xffff; 01699 timestamp = ntohl(rtpheader[1]); 01700 ssrc = ntohl(rtpheader[2]); 01701 01702 AST_LIST_HEAD_INIT_NOLOCK(&frames); 01703 /* Force a marker bit and change SSRC if the SSRC changes */ 01704 if (rtp->rxssrc && rtp->rxssrc != ssrc) { 01705 struct ast_frame *f, srcupdate = { 01706 AST_FRAME_CONTROL, 01707 .subclass = AST_CONTROL_SRCCHANGE, 01708 }; 01709 01710 if (!mark) { 01711 if (option_debug || rtpdebug) { 01712 ast_debug(0, "Forcing Marker bit, because SSRC has changed\n"); 01713 } 01714 mark = 1; 01715 } 01716 f = ast_frisolate(&srcupdate); 01717 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01718 } 01719 01720 rtp->rxssrc = ssrc; 01721 01722 if (padding) { 01723 /* Remove padding bytes */ 01724 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01725 } 01726 01727 if (cc) { 01728 /* CSRC fields present */ 01729 hdrlen += cc*4; 01730 } 01731 01732 if (ext) { 01733 /* RTP Extension present */ 01734 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01735 hdrlen += 4; 01736 if (option_debug) { 01737 int profile; 01738 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01739 if (profile == 0x505a) 01740 ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01741 else 01742 ast_debug(1, "Found unknown RTP Extensions %x\n", profile); 01743 } 01744 } 01745 01746 if (res < hdrlen) { 01747 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01748 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 01749 } 01750 01751 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01752 01753 if (rtp->rxcount==1) { 01754 /* This is the first RTP packet successfully received from source */ 01755 rtp->seedrxseqno = seqno; 01756 } 01757 01758 /* Do not schedule RR if RTCP isn't run */ 01759 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01760 /* Schedule transmission of Receiver Report */ 01761 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01762 } 01763 if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01764 rtp->cycles += RTP_SEQ_MOD; 01765 01766 prev_seqno = rtp->lastrxseqno; 01767 01768 rtp->lastrxseqno = seqno; 01769 01770 if (!rtp->themssrc) 01771 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01772 01773 if (rtp_debug_test_addr(&sock_in)) 01774 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01775 ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01776 01777 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01778 if (!rtpPT.isAstFormat) { 01779 struct ast_frame *f = NULL; 01780 01781 /* This is special in-band data that's not one of our codecs */ 01782 if (rtpPT.code == AST_RTP_DTMF) { 01783 /* It's special -- rfc2833 process it */ 01784 if (rtp_debug_test_addr(&sock_in)) { 01785 unsigned char *data; 01786 unsigned int event; 01787 unsigned int event_end; 01788 unsigned int duration; 01789 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01790 event = ntohl(*((unsigned int *)(data))); 01791 event >>= 24; 01792 event_end = ntohl(*((unsigned int *)(data))); 01793 event_end <<= 8; 01794 event_end >>= 24; 01795 duration = ntohl(*((unsigned int *)(data))); 01796 duration &= 0xFFFF; 01797 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); 01798 } 01799 /* process_rfc2833 may need to return multiple frames. We do this 01800 * by passing the pointer to the frame list to it so that the method 01801 * can append frames to the list as needed 01802 */ 01803 process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &frames); 01804 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01805 /* It's really special -- process it the Cisco way */ 01806 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01807 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01808 rtp->lastevent = seqno; 01809 } 01810 } else if (rtpPT.code == AST_RTP_CN) { 01811 /* Comfort Noise */ 01812 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01813 } else { 01814 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01815 } 01816 if (f) { 01817 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01818 } 01819 /* Even if no frame was returned by one of the above methods, 01820 * we may have a frame to return in our frame list 01821 */ 01822 if (!AST_LIST_EMPTY(&frames)) { 01823 return AST_LIST_FIRST(&frames); 01824 } 01825 return &ast_null_frame; 01826 } 01827 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01828 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; 01829 01830 rtp->rxseqno = seqno; 01831 01832 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) { 01833 rtp->dtmf_timeout = 0; 01834 01835 if (rtp->resp) { 01836 struct ast_frame *f; 01837 f = create_dtmf_frame(rtp, AST_FRAME_DTMF_END); 01838 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01839 rtp->resp = 0; 01840 rtp->dtmf_timeout = rtp->dtmf_duration = 0; 01841 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01842 return AST_LIST_FIRST(&frames); 01843 } 01844 } 01845 01846 /* Record received timestamp as last received now */ 01847 rtp->lastrxts = timestamp; 01848 01849 rtp->f.mallocd = 0; 01850 rtp->f.datalen = res - hdrlen; 01851 rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01852 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01853 rtp->f.seqno = seqno; 01854 01855 if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) { 01856 unsigned char *data = rtp->f.data.ptr; 01857 01858 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen); 01859 rtp->f.datalen +=3; 01860 *data++ = 0xEF; 01861 *data++ = 0xBF; 01862 *data = 0xBD; 01863 } 01864 01865 if (rtp->f.subclass == AST_FORMAT_T140RED) { 01866 unsigned char *data = rtp->f.data.ptr; 01867 unsigned char *header_end; 01868 int num_generations; 01869 int header_length; 01870 int length; 01871 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/ 01872 int x; 01873 01874 rtp->f.subclass = AST_FORMAT_T140; 01875 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); 01876 if (header_end == NULL) { 01877 return &ast_null_frame; 01878 } 01879 header_end++; 01880 01881 header_length = header_end - data; 01882 num_generations = header_length / 4; 01883 length = header_length; 01884 01885 if (!diff) { 01886 for (x = 0; x < num_generations; x++) 01887 length += data[x * 4 + 3]; 01888 01889 if (!(rtp->f.datalen - length)) 01890 return &ast_null_frame; 01891 01892 rtp->f.data.ptr += length; 01893 rtp->f.datalen -= length; 01894 } else if (diff > num_generations && diff < 10) { 01895 length -= 3; 01896 rtp->f.data.ptr += length; 01897 rtp->f.datalen -= length; 01898 01899 data = rtp->f.data.ptr; 01900 *data++ = 0xEF; 01901 *data++ = 0xBF; 01902 *data = 0xBD; 01903 } else { 01904 for ( x = 0; x < num_generations - diff; x++) 01905 length += data[x * 4 + 3]; 01906 01907 rtp->f.data.ptr += length; 01908 rtp->f.datalen -= length; 01909 } 01910 } 01911 01912 if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) { 01913 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01914 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01915 ast_frame_byteswap_be(&rtp->f); 01916 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01917 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01918 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01919 rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000); 01920 rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 ); 01921 } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) { 01922 /* Video -- samples is # of samples vs. 90000 */ 01923 if (!rtp->lastividtimestamp) 01924 rtp->lastividtimestamp = timestamp; 01925 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01926 rtp->lastividtimestamp = timestamp; 01927 rtp->f.delivery.tv_sec = 0; 01928 rtp->f.delivery.tv_usec = 0; 01929 /* Pass the RTP marker bit as bit 0 in the subclass field. 01930 * This is ok because subclass is actually a bitmask, and 01931 * the low bits represent audio formats, that are not 01932 * involved here since we deal with video. 01933 */ 01934 if (mark) 01935 rtp->f.subclass |= 0x1; 01936 } else { 01937 /* TEXT -- samples is # of samples vs. 1000 */ 01938 if (!rtp->lastitexttimestamp) 01939 rtp->lastitexttimestamp = timestamp; 01940 rtp->f.samples = timestamp - rtp->lastitexttimestamp; 01941 rtp->lastitexttimestamp = timestamp; 01942 rtp->f.delivery.tv_sec = 0; 01943 rtp->f.delivery.tv_usec = 0; 01944 } 01945 rtp->f.src = "RTP"; 01946 01947 AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list); 01948 return AST_LIST_FIRST(&frames); 01949 }
int ast_rtp_reload | ( | void | ) |
Initialize RTP subsystem
Definition at line 4929 of file rtp.c.
References __ast_rtp_reload().
04930 { 04931 return __ast_rtp_reload(1); 04932 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2736 of file rtp.c.
References ast_rtp::dtmf_timeout, 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.
02737 { 02738 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02739 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02740 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02741 rtp->lastts = 0; 02742 rtp->lastdigitts = 0; 02743 rtp->lastrxts = 0; 02744 rtp->lastividtimestamp = 0; 02745 rtp->lastovidtimestamp = 0; 02746 rtp->lastitexttimestamp = 0; 02747 rtp->lastotexttimestamp = 0; 02748 rtp->lasteventseqn = 0; 02749 rtp->lastevent = 0; 02750 rtp->lasttxformat = 0; 02751 rtp->lastrxformat = 0; 02752 rtp->dtmf_timeout = 0; 02753 rtp->dtmfsamples = 0; 02754 rtp->seqno = 0; 02755 rtp->rxseqno = 0; 02756 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 3579 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().
03580 { 03581 unsigned int *rtpheader; 03582 int hdrlen = 12; 03583 int res; 03584 int payload; 03585 char data[256]; 03586 level = 127 - (level & 0x7f); 03587 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 03588 03589 /* If we have no peer, return immediately */ 03590 if (!rtp->them.sin_addr.s_addr) 03591 return 0; 03592 03593 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03594 03595 /* Get a pointer to the header */ 03596 rtpheader = (unsigned int *)data; 03597 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 03598 rtpheader[1] = htonl(rtp->lastts); 03599 rtpheader[2] = htonl(rtp->ssrc); 03600 data[12] = level; 03601 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 03602 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 03603 if (res <0) 03604 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)); 03605 if (rtp_debug_test_addr(&rtp->them)) 03606 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 03607 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 03608 03609 } 03610 return 0; 03611 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 3146 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().
03147 { 03148 unsigned int *rtpheader; 03149 int hdrlen = 12, res = 0, i = 0, payload = 0; 03150 char data[256]; 03151 03152 if ((digit <= '9') && (digit >= '0')) 03153 digit -= '0'; 03154 else if (digit == '*') 03155 digit = 10; 03156 else if (digit == '#') 03157 digit = 11; 03158 else if ((digit >= 'A') && (digit <= 'D')) 03159 digit = digit - 'A' + 12; 03160 else if ((digit >= 'a') && (digit <= 'd')) 03161 digit = digit - 'a' + 12; 03162 else { 03163 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 03164 return 0; 03165 } 03166 03167 /* If we have no peer, return immediately */ 03168 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03169 return 0; 03170 03171 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 03172 03173 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03174 rtp->send_duration = 160; 03175 rtp->lastdigitts = rtp->lastts + rtp->send_duration; 03176 03177 /* Get a pointer to the header */ 03178 rtpheader = (unsigned int *)data; 03179 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 03180 rtpheader[1] = htonl(rtp->lastdigitts); 03181 rtpheader[2] = htonl(rtp->ssrc); 03182 03183 for (i = 0; i < 2; i++) { 03184 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 03185 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03186 if (res < 0) 03187 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 03188 ast_inet_ntoa(rtp->them.sin_addr), 03189 ntohs(rtp->them.sin_port), strerror(errno)); 03190 if (rtp_debug_test_addr(&rtp->them)) 03191 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03192 ast_inet_ntoa(rtp->them.sin_addr), 03193 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03194 /* Increment sequence number */ 03195 rtp->seqno++; 03196 /* Increment duration */ 03197 rtp->send_duration += 160; 03198 /* Clear marker bit and set seqno */ 03199 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 03200 } 03201 03202 /* Since we received a begin, we can safely store the digit and disable any compensation */ 03203 rtp->sending_digit = 1; 03204 rtp->send_digit = digit; 03205 rtp->send_payload = payload; 03206 03207 return 0; 03208 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 3211 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().
03212 { 03213 unsigned int *rtpheader; 03214 int hdrlen = 12, res = 0; 03215 char data[256]; 03216 03217 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03218 return 0; 03219 03220 /* Setup packet to send */ 03221 rtpheader = (unsigned int *)data; 03222 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 03223 rtpheader[1] = htonl(rtp->lastdigitts); 03224 rtpheader[2] = htonl(rtp->ssrc); 03225 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 03226 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 03227 03228 /* Transmit */ 03229 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03230 if (res < 0) 03231 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 03232 ast_inet_ntoa(rtp->them.sin_addr), 03233 ntohs(rtp->them.sin_port), strerror(errno)); 03234 if (rtp_debug_test_addr(&rtp->them)) 03235 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03236 ast_inet_ntoa(rtp->them.sin_addr), 03237 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03238 03239 /* Increment sequence number */ 03240 rtp->seqno++; 03241 /* Increment duration */ 03242 rtp->send_duration += 160; 03243 03244 return 0; 03245 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 3248 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().
03249 { 03250 unsigned int *rtpheader; 03251 int hdrlen = 12, res = 0, i = 0; 03252 char data[256]; 03253 03254 /* If no address, then bail out */ 03255 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03256 return 0; 03257 03258 if ((digit <= '9') && (digit >= '0')) 03259 digit -= '0'; 03260 else if (digit == '*') 03261 digit = 10; 03262 else if (digit == '#') 03263 digit = 11; 03264 else if ((digit >= 'A') && (digit <= 'D')) 03265 digit = digit - 'A' + 12; 03266 else if ((digit >= 'a') && (digit <= 'd')) 03267 digit = digit - 'a' + 12; 03268 else { 03269 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 03270 return 0; 03271 } 03272 03273 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03274 03275 rtpheader = (unsigned int *)data; 03276 rtpheader[1] = htonl(rtp->lastdigitts); 03277 rtpheader[2] = htonl(rtp->ssrc); 03278 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 03279 /* Set end bit */ 03280 rtpheader[3] |= htonl((1 << 23)); 03281 03282 /* Send 3 termination packets */ 03283 for (i = 0; i < 3; i++) { 03284 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 03285 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03286 rtp->seqno++; 03287 if (res < 0) 03288 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 03289 ast_inet_ntoa(rtp->them.sin_addr), 03290 ntohs(rtp->them.sin_port), strerror(errno)); 03291 if (rtp_debug_test_addr(&rtp->them)) 03292 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03293 ast_inet_ntoa(rtp->them.sin_addr), 03294 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03295 } 03296 rtp->lastts += rtp->send_duration; 03297 rtp->sending_digit = 0; 03298 rtp->send_digit = 0; 03299 03300 return res; 03301 }
void ast_rtp_set_alt_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | alt | |||
) |
set potential alternate source for RTP media
rtp | The RTP structure we wish to set up an alternate host/port on | |
alt | The address information for the alternate media source |
void |
Definition at line 2676 of file rtp.c.
References ast_rtp::altthem, ast_rtcp::altthem, and ast_rtp::rtcp.
Referenced by handle_request_invite().
02677 { 02678 rtp->altthem.sin_port = alt->sin_port; 02679 rtp->altthem.sin_addr = alt->sin_addr; 02680 if (rtp->rtcp) { 02681 rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1); 02682 rtp->rtcp->altthem.sin_addr = alt->sin_addr; 02683 } 02684 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 803 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00804 { 00805 rtp->callback = callback; 00806 }
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 2274 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().
02275 { 02276 if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 02277 return; /* bogus payload type */ 02278 02279 rtp_bridge_lock(rtp); 02280 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 02281 rtp_bridge_unlock(rtp); 02282 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2661 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().
02662 { 02663 rtp->them.sin_port = them->sin_port; 02664 rtp->them.sin_addr = them->sin_addr; 02665 if (rtp->rtcp) { 02666 int h = ntohs(them->sin_port); 02667 rtp->rtcp->them.sin_port = htons(h + 1); 02668 rtp->rtcp->them.sin_addr = them->sin_addr; 02669 } 02670 rtp->rxseqno = 0; 02671 /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */ 02672 if (strictrtp) 02673 rtp->strict_rtp_state = STRICT_RTP_LEARN; 02674 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 765 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().
00766 { 00767 rtp->rtpholdtimeout = timeout; 00768 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 771 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00772 { 00773 rtp->rtpkeepalive = period; 00774 }
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 2301 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(), process_sdp_a_audio(), process_sdp_a_text(), process_sdp_a_video(), set_dtmf_payload(), and setup_rtp_connection().
02304 { 02305 unsigned int i; 02306 int found = 0; 02307 02308 if (pt < 0 || pt >= MAX_RTP_PT) 02309 return -1; /* bogus payload type */ 02310 02311 rtp_bridge_lock(rtp); 02312 02313 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02314 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 02315 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 02316 found = 1; 02317 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 02318 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 02319 mimeTypes[i].payloadType.isAstFormat && 02320 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02321 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 02322 break; 02323 } 02324 } 02325 02326 rtp_bridge_unlock(rtp); 02327 02328 return (found ? 0 : -1); 02329 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 759 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().
00760 { 00761 rtp->rtptimeout = timeout; 00762 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 752 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00753 { 00754 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00755 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00756 }
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 2840 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().
02840 { 02841 char *audioqos; 02842 char *audioqos_jitter; 02843 char *audioqos_loss; 02844 char *audioqos_rtt; 02845 struct ast_channel *bridge; 02846 02847 if (!rtp || !chan) 02848 return; 02849 02850 bridge = ast_bridged_channel(chan); 02851 02852 audioqos = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY); 02853 audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER); 02854 audioqos_loss = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS); 02855 audioqos_rtt = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT); 02856 02857 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos); 02858 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter); 02859 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss); 02860 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt); 02861 02862 if (!bridge) 02863 return; 02864 02865 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos); 02866 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter); 02867 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss); 02868 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt); 02869 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 818 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().
00819 { 00820 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00821 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 823 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().
00824 { 00825 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00826 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 808 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 2637 of file rtp.c.
References ast_netsock_set_qos(), and ast_rtp::s.
Referenced by __oh323_rtp_create(), sip_alloc(), and start_rtp().
02638 { 02639 return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc); 02640 }
void ast_rtp_setstun | ( | struct ast_rtp * | rtp, | |
int | stun_enable | |||
) |
Enable STUN capability.
Definition at line 828 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00829 { 00830 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00831 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Stop RTP session, do not destroy structure
Definition at line 2715 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().
02716 { 02717 if (rtp->rtcp) { 02718 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02719 } 02720 if (rtp->red) { 02721 AST_SCHED_DEL(rtp->sched, rtp->red->schedid); 02722 free(rtp->red); 02723 rtp->red = NULL; 02724 } 02725 02726 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02727 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02728 if (rtp->rtcp) { 02729 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02730 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02731 } 02732 02733 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02734 }
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 707 of file rtp.c.
References ast_stun_request(), and ast_rtp::s.
Referenced by gtalk_update_stun(), and jingle_update_stun().
00708 { 00709 ast_stun_request(rtp->s, suggestion, username, NULL); 00710 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
clear payload type
Definition at line 2286 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_a_audio(), and process_sdp_a_video().
02287 { 02288 if (pt < 0 || pt >= MAX_RTP_PT) 02289 return; /* bogus payload type */ 02290 02291 rtp_bridge_lock(rtp); 02292 rtp->current_RTP_PT[pt].isAstFormat = 0; 02293 rtp->current_RTP_PT[pt].code = 0; 02294 rtp_bridge_unlock(rtp); 02295 }
Definition at line 3795 of file rtp.c.
References ast_codec_pref_getsize(), ast_debug, 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().
03796 { 03797 struct ast_frame *f; 03798 int codec; 03799 int hdrlen = 12; 03800 int subclass; 03801 03802 03803 /* If we have no peer, return immediately */ 03804 if (!rtp->them.sin_addr.s_addr) 03805 return 0; 03806 03807 /* If there is no data length, return immediately */ 03808 if (!_f->datalen && !rtp->red) 03809 return 0; 03810 03811 /* Make sure we have enough space for RTP header */ 03812 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) { 03813 ast_log(LOG_WARNING, "RTP can only send voice, video and text\n"); 03814 return -1; 03815 } 03816 03817 if (rtp->red) { 03818 /* return 0; */ 03819 /* no primary data or generations to send */ 03820 if ((_f = red_t140_to_red(rtp->red)) == NULL) 03821 return 0; 03822 } 03823 03824 /* The bottom bit of a video subclass contains the marker bit */ 03825 subclass = _f->subclass; 03826 if (_f->frametype == AST_FRAME_VIDEO) 03827 subclass &= ~0x1; 03828 03829 codec = ast_rtp_lookup_code(rtp, 1, subclass); 03830 if (codec < 0) { 03831 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 03832 return -1; 03833 } 03834 03835 if (rtp->lasttxformat != subclass) { 03836 /* New format, reset the smoother */ 03837 ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 03838 rtp->lasttxformat = subclass; 03839 if (rtp->smoother) 03840 ast_smoother_free(rtp->smoother); 03841 rtp->smoother = NULL; 03842 } 03843 03844 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 03845 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 03846 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 03847 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 03848 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)); 03849 return -1; 03850 } 03851 if (fmt.flags) 03852 ast_smoother_set_flags(rtp->smoother, fmt.flags); 03853 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)); 03854 } 03855 } 03856 if (rtp->smoother) { 03857 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 03858 ast_smoother_feed_be(rtp->smoother, _f); 03859 } else { 03860 ast_smoother_feed(rtp->smoother, _f); 03861 } 03862 03863 while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) { 03864 ast_rtp_raw_write(rtp, f, codec); 03865 } 03866 } else { 03867 /* Don't buffer outgoing frames; send them one-per-packet: */ 03868 if (_f->offset < hdrlen) 03869 f = ast_frdup(_f); /*! \bug XXX this might never be free'd. Why do we do this? */ 03870 else 03871 f = _f; 03872 if (f->data.ptr) 03873 ast_rtp_raw_write(rtp, f, codec); 03874 if (f != _f) 03875 ast_frfree(f); 03876 } 03877 03878 return 0; 03879 }
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 641 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().
00643 { 00644 struct stun_header *req; 00645 unsigned char reqdata[1024]; 00646 int reqlen, reqleft; 00647 struct stun_attr *attr; 00648 int res = 0; 00649 int retry; 00650 00651 req = (struct stun_header *)reqdata; 00652 stun_req_id(req); 00653 reqlen = 0; 00654 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00655 req->msgtype = 0; 00656 req->msglen = 0; 00657 attr = (struct stun_attr *)req->ies; 00658 if (username) 00659 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00660 req->msglen = htons(reqlen); 00661 req->msgtype = htons(STUN_BINDREQ); 00662 for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */ 00663 /* send request, possibly wait for reply */ 00664 unsigned char reply_buf[1024]; 00665 fd_set rfds; 00666 struct timeval to = { 3, 0 }; /* timeout, make it configurable */ 00667 struct sockaddr_in src; 00668 socklen_t srclen; 00669 00670 res = stun_send(s, dst, req); 00671 if (res < 0) { 00672 ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n", 00673 retry, res); 00674 continue; 00675 } 00676 if (answer == NULL) 00677 break; 00678 FD_ZERO(&rfds); 00679 FD_SET(s, &rfds); 00680 res = ast_select(s + 1, &rfds, NULL, NULL, &to); 00681 if (res <= 0) /* timeout or error */ 00682 continue; 00683 memset(&src, '\0', sizeof(src)); 00684 srclen = sizeof(src); 00685 /* XXX pass -1 in the size, because stun_handle_packet might 00686 * write past the end of the buffer. 00687 */ 00688 res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1, 00689 0, (struct sockaddr *)&src, &srclen); 00690 if (res < 0) { 00691 ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n", 00692 retry, res); 00693 continue; 00694 } 00695 memset(answer, '\0', sizeof(struct sockaddr_in)); 00696 stun_handle_packet(s, &src, reply_buf, res, 00697 stun_get_mapped, answer); 00698 res = 0; /* signal regular exit */ 00699 break; 00700 } 00701 return res; 00702 }
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 3909 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_PARAMETERS, 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().
03910 { 03911 struct ast_frame *fr = NULL; 03912 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03913 int oldcodec0 = codec0, oldcodec1 = codec1; 03914 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,}; 03915 struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,}; 03916 03917 /* Set it up so audio goes directly between the two endpoints */ 03918 03919 /* Test the first channel */ 03920 if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 03921 ast_rtp_get_peer(p1, &ac1); 03922 if (vp1) 03923 ast_rtp_get_peer(vp1, &vac1); 03924 if (tp1) 03925 ast_rtp_get_peer(tp1, &tac1); 03926 } else 03927 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 03928 03929 /* Test the second channel */ 03930 if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 03931 ast_rtp_get_peer(p0, &ac0); 03932 if (vp0) 03933 ast_rtp_get_peer(vp0, &vac0); 03934 if (tp0) 03935 ast_rtp_get_peer(tp0, &tac0); 03936 } else 03937 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 03938 03939 /* Now we can unlock and move into our loop */ 03940 ast_channel_unlock(c0); 03941 ast_channel_unlock(c1); 03942 03943 ast_poll_channel_add(c0, c1); 03944 03945 /* Throw our channels into the structure and enter the loop */ 03946 cs[0] = c0; 03947 cs[1] = c1; 03948 cs[2] = NULL; 03949 for (;;) { 03950 /* Check if anything changed */ 03951 if ((c0->tech_pvt != pvt0) || 03952 (c1->tech_pvt != pvt1) || 03953 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03954 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03955 ast_debug(1, "Oooh, something is weird, backing out\n"); 03956 if (c0->tech_pvt == pvt0) 03957 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03958 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03959 if (c1->tech_pvt == pvt1) 03960 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03961 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03962 ast_poll_channel_del(c0, c1); 03963 return AST_BRIDGE_RETRY; 03964 } 03965 03966 /* Check if they have changed their address */ 03967 ast_rtp_get_peer(p1, &t1); 03968 if (vp1) 03969 ast_rtp_get_peer(vp1, &vt1); 03970 if (tp1) 03971 ast_rtp_get_peer(tp1, &tt1); 03972 if (pr1->get_codec) 03973 codec1 = pr1->get_codec(c1); 03974 ast_rtp_get_peer(p0, &t0); 03975 if (vp0) 03976 ast_rtp_get_peer(vp0, &vt0); 03977 if (tp0) 03978 ast_rtp_get_peer(tp0, &tt0); 03979 if (pr0->get_codec) 03980 codec0 = pr0->get_codec(c0); 03981 if ((inaddrcmp(&t1, &ac1)) || 03982 (vp1 && inaddrcmp(&vt1, &vac1)) || 03983 (tp1 && inaddrcmp(&tt1, &tac1)) || 03984 (codec1 != oldcodec1)) { 03985 ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03986 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 03987 ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 03988 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 03989 ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n", 03990 c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1); 03991 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03992 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 03993 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03994 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 03995 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03996 c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1); 03997 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))) 03998 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 03999 memcpy(&ac1, &t1, sizeof(ac1)); 04000 memcpy(&vac1, &vt1, sizeof(vac1)); 04001 memcpy(&tac1, &tt1, sizeof(tac1)); 04002 oldcodec1 = codec1; 04003 } 04004 if ((inaddrcmp(&t0, &ac0)) || 04005 (vp0 && inaddrcmp(&vt0, &vac0)) || 04006 (tp0 && inaddrcmp(&tt0, &tac0)) || 04007 (codec0 != oldcodec0)) { 04008 ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 04009 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 04010 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 04011 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 04012 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))) 04013 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 04014 memcpy(&ac0, &t0, sizeof(ac0)); 04015 memcpy(&vac0, &vt0, sizeof(vac0)); 04016 memcpy(&tac0, &tt0, sizeof(tac0)); 04017 oldcodec0 = codec0; 04018 } 04019 04020 /* Wait for frame to come in on the channels */ 04021 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 04022 if (!timeoutms) { 04023 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 04024 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 04025 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 04026 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 04027 return AST_BRIDGE_RETRY; 04028 } 04029 ast_debug(1, "Ooh, empty read...\n"); 04030 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 04031 break; 04032 continue; 04033 } 04034 fr = ast_read(who); 04035 other = (who == c0) ? c1 : c0; 04036 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 04037 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 04038 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 04039 /* Break out of bridge */ 04040 *fo = fr; 04041 *rc = who; 04042 ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 04043 if (c0->tech_pvt == pvt0) 04044 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 04045 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 04046 if (c1->tech_pvt == pvt1) 04047 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 04048 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 04049 ast_poll_channel_del(c0, c1); 04050 return AST_BRIDGE_COMPLETE; 04051 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 04052 if ((fr->subclass == AST_CONTROL_HOLD) || 04053 (fr->subclass == AST_CONTROL_UNHOLD) || 04054 (fr->subclass == AST_CONTROL_VIDUPDATE) || 04055 (fr->subclass == AST_CONTROL_SRCUPDATE) || 04056 (fr->subclass == AST_CONTROL_T38_PARAMETERS)) { 04057 if (fr->subclass == AST_CONTROL_HOLD) { 04058 /* If we someone went on hold we want the other side to reinvite back to us */ 04059 if (who == c0) 04060 pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0); 04061 else 04062 pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0); 04063 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 04064 /* If they went off hold they should go back to being direct */ 04065 if (who == c0) 04066 pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 04067 else 04068 pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 04069 } 04070 /* Update local address information */ 04071 ast_rtp_get_peer(p0, &t0); 04072 memcpy(&ac0, &t0, sizeof(ac0)); 04073 ast_rtp_get_peer(p1, &t1); 04074 memcpy(&ac1, &t1, sizeof(ac1)); 04075 /* Update codec information */ 04076 if (pr0->get_codec && c0->tech_pvt) 04077 oldcodec0 = codec0 = pr0->get_codec(c0); 04078 if (pr1->get_codec && c1->tech_pvt) 04079 oldcodec1 = codec1 = pr1->get_codec(c1); 04080 ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen); 04081 ast_frfree(fr); 04082 } else { 04083 *fo = fr; 04084 *rc = who; 04085 ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 04086 return AST_BRIDGE_COMPLETE; 04087 } 04088 } else { 04089 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 04090 (fr->frametype == AST_FRAME_DTMF_END) || 04091 (fr->frametype == AST_FRAME_VOICE) || 04092 (fr->frametype == AST_FRAME_VIDEO) || 04093 (fr->frametype == AST_FRAME_IMAGE) || 04094 (fr->frametype == AST_FRAME_HTML) || 04095 (fr->frametype == AST_FRAME_MODEM) || 04096 (fr->frametype == AST_FRAME_TEXT)) { 04097 ast_write(other, fr); 04098 } 04099 ast_frfree(fr); 04100 } 04101 /* Swap priority */ 04102 #ifndef HAVE_EPOLL 04103 cs[2] = cs[0]; 04104 cs[0] = cs[1]; 04105 cs[1] = cs[2]; 04106 #endif 04107 } 04108 04109 ast_poll_channel_del(c0, c1); 04110 04111 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 04112 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 04113 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 04114 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 04115 04116 return AST_BRIDGE_FAILED; 04117 }
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 4217 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().
04218 { 04219 struct ast_frame *fr = NULL; 04220 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 04221 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 04222 int p0_callback = 0, p1_callback = 0; 04223 enum ast_bridge_result res = AST_BRIDGE_FAILED; 04224 04225 /* Okay, setup each RTP structure to do P2P forwarding */ 04226 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 04227 p2p_set_bridge(p0, p1); 04228 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 04229 p2p_set_bridge(p1, p0); 04230 04231 /* Activate callback modes if possible */ 04232 p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]); 04233 p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]); 04234 04235 /* Now let go of the channel locks and be on our way */ 04236 ast_channel_unlock(c0); 04237 ast_channel_unlock(c1); 04238 04239 ast_poll_channel_add(c0, c1); 04240 04241 /* Go into a loop forwarding frames until we don't need to anymore */ 04242 cs[0] = c0; 04243 cs[1] = c1; 04244 cs[2] = NULL; 04245 for (;;) { 04246 /* If the underlying formats have changed force this bridge to break */ 04247 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 04248 ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n"); 04249 res = AST_BRIDGE_FAILED_NOWARN; 04250 break; 04251 } 04252 /* Check if anything changed */ 04253 if ((c0->tech_pvt != pvt0) || 04254 (c1->tech_pvt != pvt1) || 04255 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 04256 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 04257 ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n"); 04258 /* 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 */ 04259 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 04260 ast_frfree(fr); 04261 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 04262 ast_frfree(fr); 04263 res = AST_BRIDGE_RETRY; 04264 break; 04265 } 04266 /* Wait on a channel to feed us a frame */ 04267 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 04268 if (!timeoutms) { 04269 res = AST_BRIDGE_RETRY; 04270 break; 04271 } 04272 if (option_debug > 2) 04273 ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n"); 04274 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 04275 break; 04276 continue; 04277 } 04278 /* Read in frame from channel */ 04279 fr = ast_read(who); 04280 other = (who == c0) ? c1 : c0; 04281 /* Depending on the frame we may need to break out of our bridge */ 04282 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 04283 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 04284 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 04285 /* Record received frame and who */ 04286 *fo = fr; 04287 *rc = who; 04288 ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup"); 04289 res = AST_BRIDGE_COMPLETE; 04290 break; 04291 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 04292 if ((fr->subclass == AST_CONTROL_HOLD) || 04293 (fr->subclass == AST_CONTROL_UNHOLD) || 04294 (fr->subclass == AST_CONTROL_VIDUPDATE) || 04295 (fr->subclass == AST_CONTROL_SRCUPDATE) || 04296 (fr->subclass == AST_CONTROL_T38_PARAMETERS)) { 04297 /* If we are going on hold, then break callback mode and P2P bridging */ 04298 if (fr->subclass == AST_CONTROL_HOLD) { 04299 if (p0_callback) 04300 p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]); 04301 if (p1_callback) 04302 p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]); 04303 p2p_set_bridge(p0, NULL); 04304 p2p_set_bridge(p1, NULL); 04305 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 04306 /* If we are off hold, then go back to callback mode and P2P bridging */ 04307 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 04308 p2p_set_bridge(p0, p1); 04309 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 04310 p2p_set_bridge(p1, p0); 04311 p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]); 04312 p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]); 04313 } 04314 ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen); 04315 ast_frfree(fr); 04316 } else { 04317 *fo = fr; 04318 *rc = who; 04319 ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 04320 res = AST_BRIDGE_COMPLETE; 04321 break; 04322 } 04323 } else { 04324 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 04325 (fr->frametype == AST_FRAME_DTMF_END) || 04326 (fr->frametype == AST_FRAME_VOICE) || 04327 (fr->frametype == AST_FRAME_VIDEO) || 04328 (fr->frametype == AST_FRAME_IMAGE) || 04329 (fr->frametype == AST_FRAME_HTML) || 04330 (fr->frametype == AST_FRAME_MODEM) || 04331 (fr->frametype == AST_FRAME_TEXT)) { 04332 ast_write(other, fr); 04333 } 04334 04335 ast_frfree(fr); 04336 } 04337 /* Swap priority */ 04338 #ifndef HAVE_EPOLL 04339 cs[2] = cs[0]; 04340 cs[0] = cs[1]; 04341 cs[1] = cs[2]; 04342 #endif 04343 } 04344 04345 /* If we are totally avoiding the core, then restore our link to it */ 04346 if (p0_callback) 04347 p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]); 04348 if (p1_callback) 04349 p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]); 04350 04351 /* Break out of the direct bridge */ 04352 p2p_set_bridge(p0, NULL); 04353 p2p_set_bridge(p1, NULL); 04354 04355 ast_poll_channel_del(c0, c1); 04356 04357 return res; 04358 }
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 1527 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().
01528 { 01529 int res = 0, payload = 0, bridged_payload = 0, mark; 01530 struct rtpPayloadType rtpPT; 01531 int reconstruct = ntohl(rtpheader[0]); 01532 01533 /* Get fields from packet */ 01534 payload = (reconstruct & 0x7f0000) >> 16; 01535 mark = (((reconstruct & 0x800000) >> 23) != 0); 01536 01537 /* Check what the payload value should be */ 01538 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01539 01540 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01541 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01542 return -1; 01543 01544 /* Otherwise adjust bridged payload to match */ 01545 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01546 01547 /* 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 */ 01548 if (!bridged->current_RTP_PT[bridged_payload].code) 01549 return -1; 01550 01551 01552 /* If the mark bit has not been sent yet... do it now */ 01553 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01554 mark = 1; 01555 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01556 } 01557 01558 /* Reconstruct part of the packet */ 01559 reconstruct &= 0xFF80FFFF; 01560 reconstruct |= (bridged_payload << 16); 01561 reconstruct |= (mark << 23); 01562 rtpheader[0] = htonl(reconstruct); 01563 01564 /* Send the packet back out */ 01565 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01566 if (res < 0) { 01567 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01568 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)); 01569 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01570 if (option_debug || rtpdebug) 01571 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)); 01572 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01573 } 01574 return 0; 01575 } else if (rtp_debug_test_addr(&bridged->them)) 01576 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); 01577 01578 return 0; 01579 }
static void calc_rxstamp | ( | struct timeval * | when, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1472 of file rtp.c.
References ast_samp2tv(), ast_tvadd(), ast_tvsub(), ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, normdev_compute(), ast_rtcp::normdev_rxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxtransit, ast_rtp::seedrxts, stddev_compute(), ast_rtcp::stdev_rxjitter, and ast_frame::subclass.
Referenced by ast_rtp_read(), and schedule_delivery().
01473 { 01474 struct timeval now; 01475 struct timeval tmp; 01476 double transit; 01477 double current_time; 01478 double d; 01479 double dtv; 01480 double prog; 01481 double normdev_rxjitter_current; 01482 int rate = rtp_get_rate(rtp->f.subclass); 01483 01484 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01485 gettimeofday(&rtp->rxcore, NULL); 01486 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01487 /* map timestamp to a real time */ 01488 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01489 tmp = ast_samp2tv(timestamp, rate); 01490 rtp->rxcore = ast_tvsub(rtp->rxcore, tmp); 01491 /* Round to 0.1ms for nice, pretty timestamps */ 01492 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01493 } 01494 01495 gettimeofday(&now,NULL); 01496 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01497 tmp = ast_samp2tv(timestamp, rate); 01498 *when = ast_tvadd(rtp->rxcore, tmp); 01499 01500 prog = (double)((timestamp-rtp->seedrxts)/(float)(rate)); 01501 dtv = (double)rtp->drxcore + (double)(prog); 01502 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01503 transit = current_time - dtv; 01504 d = transit - rtp->rxtransit; 01505 rtp->rxtransit = transit; 01506 if (d<0) 01507 d=-d; 01508 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01509 01510 if (rtp->rtcp) { 01511 if (rtp->rxjitter > rtp->rtcp->maxrxjitter) 01512 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01513 if (rtp->rtcp->rxjitter_count == 1) 01514 rtp->rtcp->minrxjitter = rtp->rxjitter; 01515 if (rtp->rxjitter < rtp->rtcp->minrxjitter) 01516 rtp->rtcp->minrxjitter = rtp->rxjitter; 01517 01518 normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count); 01519 rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count); 01520 01521 rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current; 01522 rtp->rtcp->rxjitter_count++; 01523 } 01524 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 3126 of file rtp.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
03127 { 03128 struct timeval t; 03129 long ms; 03130 if (ast_tvzero(rtp->txcore)) { 03131 rtp->txcore = ast_tvnow(); 03132 /* Round to 20ms for nice, pretty timestamps */ 03133 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 03134 } 03135 /* Use previous txcore if available */ 03136 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 03137 ms = ast_tvdiff_ms(t, rtp->txcore); 03138 if (ms < 0) 03139 ms = 0; 03140 /* Use what we just got for next time */ 03141 rtp->txcore = t; 03142 return (unsigned int) ms; 03143 }
static struct ast_frame* create_dtmf_frame | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static] |
Definition at line 878 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_LIST_NEXT, 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().
00879 { 00880 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00881 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00882 ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00883 rtp->resp = 0; 00884 rtp->dtmfsamples = 0; 00885 return &ast_null_frame; 00886 } 00887 ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00888 if (rtp->resp == 'X') { 00889 rtp->f.frametype = AST_FRAME_CONTROL; 00890 rtp->f.subclass = AST_CONTROL_FLASH; 00891 } else { 00892 rtp->f.frametype = type; 00893 rtp->f.subclass = rtp->resp; 00894 } 00895 rtp->f.datalen = 0; 00896 rtp->f.samples = 0; 00897 rtp->f.mallocd = 0; 00898 rtp->f.src = "RTP"; 00899 AST_LIST_NEXT(&rtp->f, frame_list) = NULL; 00900 return &rtp->f; 00901 00902 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 2097 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().
02098 { 02099 struct ast_rtp_protocol *cur = NULL; 02100 02101 AST_RWLIST_RDLOCK(&protos); 02102 AST_RWLIST_TRAVERSE(&protos, cur, list) { 02103 if (cur->type == chan->tech->type) 02104 break; 02105 } 02106 AST_RWLIST_UNLOCK(&protos); 02107 02108 return cur; 02109 }
static char* handle_cli_rtcp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4677 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.
04678 { 04679 switch (cmd) { 04680 case CLI_INIT: 04681 e->command = "rtcp debug [off|ip]"; 04682 e->usage = 04683 "Usage: rtcp debug [off]|[ip host[:port]]\n" 04684 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04685 " specified, limit the dumped packets to those to and from\n" 04686 " the specified 'host' with optional port.\n"; 04687 return NULL; 04688 case CLI_GENERATE: 04689 return NULL; 04690 } 04691 04692 if (a->argc < 2 || a->argc > 4) 04693 return CLI_SHOWUSAGE; 04694 if (a->argc == 2) { 04695 rtcpdebug = 1; 04696 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04697 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04698 } else if (a->argc == 3) { 04699 if (strncasecmp(a->argv[2], "off", 3)) 04700 return CLI_SHOWUSAGE; 04701 rtcpdebug = 0; 04702 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04703 } else { 04704 if (strncasecmp(a->argv[2], "ip", 2)) 04705 return CLI_SHOWUSAGE; 04706 return rtcp_do_debug_ip(a); 04707 } 04708 04709 return CLI_SUCCESS; 04710 }
static char* handle_cli_rtcp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4712 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.
04713 { 04714 switch (cmd) { 04715 case CLI_INIT: 04716 e->command = "rtcp set debug {on|off|ip}"; 04717 e->usage = 04718 "Usage: rtcp set debug {on|off|ip host[:port]}\n" 04719 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04720 " specified, limit the dumped packets to those to and from\n" 04721 " the specified 'host' with optional port.\n"; 04722 return NULL; 04723 case CLI_GENERATE: 04724 return NULL; 04725 } 04726 04727 if (a->argc == e->args) { /* set on or off */ 04728 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04729 rtcpdebug = 1; 04730 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04731 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04732 return CLI_SUCCESS; 04733 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04734 rtcpdebug = 0; 04735 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04736 return CLI_SUCCESS; 04737 } 04738 } else if (a->argc == e->args +1) { /* ip */ 04739 return rtcp_do_debug_ip(a); 04740 } 04741 04742 return CLI_SHOWUSAGE; /* default, failure */ 04743 }
static char* handle_cli_rtcp_set_stats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4768 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.
04769 { 04770 switch (cmd) { 04771 case CLI_INIT: 04772 e->command = "rtcp set stats {on|off}"; 04773 e->usage = 04774 "Usage: rtcp set stats {on|off}\n" 04775 " Enable/Disable dumping of RTCP stats.\n"; 04776 return NULL; 04777 case CLI_GENERATE: 04778 return NULL; 04779 } 04780 04781 if (a->argc != e->args) 04782 return CLI_SHOWUSAGE; 04783 04784 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04785 rtcpstats = 1; 04786 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04787 rtcpstats = 0; 04788 else 04789 return CLI_SHOWUSAGE; 04790 04791 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04792 return CLI_SUCCESS; 04793 }
static char* handle_cli_rtcp_stats_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4745 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.
04746 { 04747 switch (cmd) { 04748 case CLI_INIT: 04749 e->command = "rtcp stats [off]"; 04750 e->usage = 04751 "Usage: rtcp stats [off]\n" 04752 " Enable/Disable dumping of RTCP stats.\n"; 04753 return NULL; 04754 case CLI_GENERATE: 04755 return NULL; 04756 } 04757 04758 if (a->argc < 2 || a->argc > 3) 04759 return CLI_SHOWUSAGE; 04760 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04761 return CLI_SHOWUSAGE; 04762 04763 rtcpstats = (a->argc == 3) ? 0 : 1; 04764 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04765 return CLI_SUCCESS; 04766 }
static char* handle_cli_rtp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4609 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.
04610 { 04611 switch (cmd) { 04612 case CLI_INIT: 04613 e->command = "rtp debug [off|ip]"; 04614 e->usage = 04615 "Usage: rtp debug [off]|[ip host[:port]]\n" 04616 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04617 " specified, limit the dumped packets to those to and from\n" 04618 " the specified 'host' with optional port.\n"; 04619 return NULL; 04620 case CLI_GENERATE: 04621 return NULL; 04622 } 04623 04624 if (a->argc < 2 || a->argc > 4) 04625 return CLI_SHOWUSAGE; 04626 if (a->argc == 2) { 04627 rtpdebug = 1; 04628 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04629 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04630 } else if (a->argc == 3) { 04631 if (strncasecmp(a->argv[2], "off", 3)) 04632 return CLI_SHOWUSAGE; 04633 rtpdebug = 0; 04634 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04635 } else { 04636 if (strncasecmp(a->argv[2], "ip", 2)) 04637 return CLI_SHOWUSAGE; 04638 return rtp_do_debug_ip(a, 1); 04639 } 04640 04641 return CLI_SUCCESS; 04642 }
static char* handle_cli_rtp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4644 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.
04645 { 04646 switch (cmd) { 04647 case CLI_INIT: 04648 e->command = "rtp set debug {on|off|ip}"; 04649 e->usage = 04650 "Usage: rtp set debug {on|off|ip host[:port]}\n" 04651 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04652 " specified, limit the dumped packets to those to and from\n" 04653 " the specified 'host' with optional port.\n"; 04654 return NULL; 04655 case CLI_GENERATE: 04656 return NULL; 04657 } 04658 04659 if (a->argc == e->args) { /* set on or off */ 04660 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04661 rtpdebug = 1; 04662 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04663 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04664 return CLI_SUCCESS; 04665 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04666 rtpdebug = 0; 04667 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04668 return CLI_SUCCESS; 04669 } 04670 } else if (a->argc == e->args +1) { /* ip */ 04671 return rtp_do_debug_ip(a, 0); 04672 } 04673 04674 return CLI_SHOWUSAGE; /* default, failure */ 04675 }
static char* handle_cli_stun_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4795 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.
04796 { 04797 switch (cmd) { 04798 case CLI_INIT: 04799 e->command = "stun debug [off]"; 04800 e->usage = 04801 "Usage: stun debug [off]\n" 04802 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04803 " debugging\n"; 04804 return NULL; 04805 case CLI_GENERATE: 04806 return NULL; 04807 } 04808 04809 if (a->argc < 2 || a->argc > 3) 04810 return CLI_SHOWUSAGE; 04811 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04812 return CLI_SHOWUSAGE; 04813 04814 stundebug = (a->argc == 3) ? 0 : 1; 04815 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04816 return CLI_SUCCESS; 04817 }
static char* handle_cli_stun_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4819 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.
04820 { 04821 switch (cmd) { 04822 case CLI_INIT: 04823 e->command = "stun set debug {on|off}"; 04824 e->usage = 04825 "Usage: stun set debug {on|off}\n" 04826 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04827 " debugging\n"; 04828 return NULL; 04829 case CLI_GENERATE: 04830 return NULL; 04831 } 04832 04833 if (a->argc != e->args) 04834 return CLI_SHOWUSAGE; 04835 04836 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04837 stundebug = 1; 04838 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04839 stundebug = 0; 04840 else 04841 return CLI_SHOWUSAGE; 04842 04843 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04844 return CLI_SUCCESS; 04845 }
static double normdev_compute | ( | double | normdev, | |
double | sample, | |||
unsigned int | sample_count | |||
) | [static] |
Calculate normal deviation.
Definition at line 850 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().
00851 { 00852 normdev = normdev * sample_count + sample; 00853 sample_count++; 00854 00855 return normdev / sample_count; 00856 }
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 4185 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().
04186 { 04187 ast_channel_lock(chan); 04188 04189 /* Remove the callback from the IO context */ 04190 ast_io_remove(rtp->io, iod[0]); 04191 04192 /* Restore file descriptors */ 04193 chan->fds[0] = ast_rtp_fd(rtp); 04194 ast_channel_unlock(chan); 04195 04196 /* Restore callback mode if previously used */ 04197 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 04198 rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp); 04199 04200 return 0; 04201 }
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 4204 of file rtp.c.
References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().
Referenced by bridge_p2p_loop().
04205 { 04206 rtp_bridge_lock(rtp0); 04207 rtp0->bridged = rtp1; 04208 rtp_bridge_unlock(rtp0); 04209 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 931 of file rtp.c.
References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_test_flag, create_dtmf_frame(), ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, FLAG_DTMF_COMPENSATE, ast_frame::flags, option_debug, ast_rtp::resp, rtp_get_rate(), and seq.
Referenced by ast_rtp_read().
00932 { 00933 unsigned int event; 00934 char resp = 0; 00935 struct ast_frame *f = NULL; 00936 unsigned char seq; 00937 unsigned int flags; 00938 unsigned int power; 00939 00940 /* We should have at least 4 bytes in RTP data */ 00941 if (len < 4) 00942 return f; 00943 00944 /* The format of Cisco RTP DTMF packet looks like next: 00945 +0 - sequence number of DTMF RTP packet (begins from 1, 00946 wrapped to 0) 00947 +1 - set of flags 00948 +1 (bit 0) - flaps by different DTMF digits delimited by audio 00949 or repeated digit without audio??? 00950 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone 00951 then falls to 0 at its end) 00952 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...) 00953 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right 00954 by each new packet and thus provides some redudancy. 00955 00956 Sample of Cisco RTP DTMF packet is (all data in hex): 00957 19 07 00 02 12 02 20 02 00958 showing end of DTMF digit '2'. 00959 00960 The packets 00961 27 07 00 02 0A 02 20 02 00962 28 06 20 02 00 02 0A 02 00963 shows begin of new digit '2' with very short pause (20 ms) after 00964 previous digit '2'. Bit +1.0 flips at begin of new digit. 00965 00966 Cisco RTP DTMF packets comes as replacement of audio RTP packets 00967 so its uses the same sequencing and timestamping rules as replaced 00968 audio packets. Repeat interval of DTMF packets is 20 ms and not rely 00969 on audio framing parameters. Marker bit isn't used within stream of 00970 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps 00971 are not sequential at borders between DTMF and audio streams, 00972 */ 00973 00974 seq = data[0]; 00975 flags = data[1]; 00976 power = data[2]; 00977 event = data[3] & 0x1f; 00978 00979 if (option_debug > 2 || rtpdebug) 00980 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); 00981 if (event < 10) { 00982 resp = '0' + event; 00983 } else if (event < 11) { 00984 resp = '*'; 00985 } else if (event < 12) { 00986 resp = '#'; 00987 } else if (event < 16) { 00988 resp = 'A' + (event - 12); 00989 } else if (event < 17) { 00990 resp = 'X'; 00991 } 00992 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) { 00993 rtp->resp = resp; 00994 /* Why we should care on DTMF compensation at reception? */ 00995 if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00996 f = create_dtmf_frame(rtp, AST_FRAME_DTMF_BEGIN); 00997 rtp->dtmfsamples = 0; 00998 } 00999 } else if ((rtp->resp == resp) && !power) { 01000 f = create_dtmf_frame(rtp, AST_FRAME_DTMF_END); 01001 f->samples = rtp->dtmfsamples * (rtp_get_rate(f->subclass) / 1000); 01002 rtp->resp = 0; 01003 } else if (rtp->resp == resp) 01004 rtp->dtmfsamples += 20 * (rtp_get_rate(f->subclass) / 1000); 01005 rtp->dtmf_timeout = dtmftimeout; 01006 return f; 01007 }
static void process_rfc2833 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp, | |||
struct frame_list * | frames | |||
) | [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 | ||
frames |
Definition at line 1022 of file rtp.c.
References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup(), AST_LIST_INSERT_TAIL, ast_log(), ast_samp2tv(), ast_test_flag, ast_tv(), ast_tvdiff_ms(), create_dtmf_frame(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, FLAG_DTMF_COMPENSATE, frames, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_get_rate(), and ast_frame::samples.
Referenced by ast_rtp_read().
01023 { 01024 unsigned int event; 01025 unsigned int event_end; 01026 unsigned int samples; 01027 char resp = 0; 01028 struct ast_frame *f = NULL; 01029 01030 /* Figure out event, event end, and samples */ 01031 event = ntohl(*((unsigned int *)(data))); 01032 event >>= 24; 01033 event_end = ntohl(*((unsigned int *)(data))); 01034 event_end <<= 8; 01035 event_end >>= 24; 01036 samples = ntohl(*((unsigned int *)(data))); 01037 samples &= 0xFFFF; 01038 01039 /* Print out debug if turned on */ 01040 if (rtpdebug || option_debug > 2) 01041 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 01042 01043 /* Figure out what digit was pressed */ 01044 if (event < 10) { 01045 resp = '0' + event; 01046 } else if (event < 11) { 01047 resp = '*'; 01048 } else if (event < 12) { 01049 resp = '#'; 01050 } else if (event < 16) { 01051 resp = 'A' + (event - 12); 01052 } else if (event < 17) { /* Event 16: Hook flash */ 01053 resp = 'X'; 01054 } else { 01055 /* Not a supported event */ 01056 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 01057 return; 01058 } 01059 01060 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 01061 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 01062 rtp->resp = resp; 01063 rtp->dtmf_timeout = 0; 01064 f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_END)); 01065 f->len = 0; 01066 rtp->lastevent = timestamp; 01067 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01068 } 01069 } else { 01070 /* The duration parameter measures the complete 01071 duration of the event (from the beginning) - RFC2833. 01072 Account for the fact that duration is only 16 bits long 01073 (about 8 seconds at 8000 Hz) and can wrap is digit 01074 is hold for too long. */ 01075 unsigned int new_duration = rtp->dtmf_duration; 01076 unsigned int last_duration = new_duration & 0xFFFF; 01077 01078 if (last_duration > 64000 && samples < last_duration) 01079 new_duration += 0xFFFF + 1; 01080 new_duration = (new_duration & ~0xFFFF) | samples; 01081 01082 if (rtp->lastevent > seqno) { 01083 /* Out of order frame. Processing this can cause us to 01084 * improperly duplicate incoming DTMF, so just drop 01085 * this. 01086 */ 01087 return; 01088 } 01089 01090 if (event_end & 0x80) { 01091 /* End event */ 01092 if ((rtp->lastevent != seqno) && rtp->resp) { 01093 rtp->dtmf_duration = new_duration; 01094 f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_END)); 01095 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01096 rtp->resp = 0; 01097 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01098 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01099 } 01100 } else { 01101 /* Begin/continuation */ 01102 01103 if (rtp->resp && rtp->resp != resp) { 01104 /* Another digit already began. End it */ 01105 f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_END)); 01106 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01107 rtp->resp = 0; 01108 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01109 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01110 } 01111 01112 01113 if (rtp->resp) { 01114 /* Digit continues */ 01115 rtp->dtmf_duration = new_duration; 01116 } else { 01117 /* New digit began */ 01118 rtp->resp = resp; 01119 f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_BEGIN)); 01120 rtp->dtmf_duration = samples; 01121 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01122 } 01123 01124 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout; 01125 } 01126 01127 rtp->lastevent = seqno; 01128 } 01129 01130 rtp->dtmfsamples = samples; 01131 }
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 1139 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().
01140 { 01141 struct ast_frame *f = NULL; 01142 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 01143 totally help us out becuase we don't have an engine to keep it going and we are not 01144 guaranteed to have it every 20ms or anything */ 01145 if (rtpdebug) 01146 ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 01147 01148 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 01149 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 01150 ast_inet_ntoa(rtp->them.sin_addr)); 01151 ast_set_flag(rtp, FLAG_3389_WARNING); 01152 } 01153 01154 /* Must have at least one byte */ 01155 if (!len) 01156 return NULL; 01157 if (len < 24) { 01158 rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET; 01159 rtp->f.datalen = len - 1; 01160 rtp->f.offset = AST_FRIENDLY_OFFSET; 01161 memcpy(rtp->f.data.ptr, data + 1, len - 1); 01162 } else { 01163 rtp->f.data.ptr = NULL; 01164 rtp->f.offset = 0; 01165 rtp->f.datalen = 0; 01166 } 01167 rtp->f.frametype = AST_FRAME_CNG; 01168 rtp->f.subclass = data[0] & 0x7f; 01169 rtp->f.samples = 0; 01170 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 01171 f = &rtp->f; 01172 return f; 01173 }
Buffer t.140 data.
rtp | ||
f | frame |
Definition at line 5039 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().
05040 { 05041 if (f->datalen > -1) { 05042 struct rtp_red *red = rtp->red; 05043 memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen); 05044 red->t140.datalen += f->datalen; 05045 red->t140.ts = f->ts; 05046 } 05047 }
Construct a redundant frame.
red | redundant data structure |
Definition at line 4956 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().
04956 { 04957 unsigned char *data = red->t140red.data.ptr; 04958 int len = 0; 04959 int i; 04960 04961 /* replace most aged generation */ 04962 if (red->len[0]) { 04963 for (i = 1; i < red->num_gen+1; i++) 04964 len += red->len[i]; 04965 04966 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 04967 } 04968 04969 /* Store length of each generation and primary data length*/ 04970 for (i = 0; i < red->num_gen; i++) 04971 red->len[i] = red->len[i+1]; 04972 red->len[i] = red->t140.datalen; 04973 04974 /* write each generation length in red header */ 04975 len = red->hdrlen; 04976 for (i = 0; i < red->num_gen; i++) 04977 len += data[i*4+3] = red->len[i]; 04978 04979 /* add primary data to buffer */ 04980 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 04981 red->t140red.datalen = len + red->t140.datalen; 04982 04983 /* no primary data and no generations to send */ 04984 if (len == red->hdrlen && !red->t140.datalen) 04985 return NULL; 04986 04987 /* reset t.140 buffer */ 04988 red->t140.datalen = 0; 04989 04990 return &red->t140red; 04991 }
static int red_write | ( | const void * | data | ) | [static] |
Write t140 redundacy frame.
data | primary data to be buffered |
Definition at line 4944 of file rtp.c.
References ast_rtp_write(), ast_rtp::red, and rtp_red::t140.
Referenced by rtp_red_init().
04945 { 04946 struct ast_rtp *rtp = (struct ast_rtp*) data; 04947 04948 ast_rtp_write(rtp, &rtp->red->t140); 04949 04950 return 1; 04951 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 917 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00918 { 00919 if (rtcpdebug == 0) 00920 return 0; 00921 if (rtcpdebugaddr.sin_addr.s_addr) { 00922 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00923 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00924 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00925 return 0; 00926 } 00927 return 1; 00928 }
static char* rtcp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 4579 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().
04580 { 04581 struct hostent *hp; 04582 struct ast_hostent ahp; 04583 int port = 0; 04584 char *p, *arg; 04585 04586 arg = a->argv[3]; 04587 p = strstr(arg, ":"); 04588 if (p) { 04589 *p = '\0'; 04590 p++; 04591 port = atoi(p); 04592 } 04593 hp = ast_gethostbyname(arg, &ahp); 04594 if (hp == NULL) { 04595 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04596 return CLI_FAILURE; 04597 } 04598 rtcpdebugaddr.sin_family = AF_INET; 04599 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 04600 rtcpdebugaddr.sin_port = htons(port); 04601 if (port == 0) 04602 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 04603 else 04604 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 04605 rtcpdebug = 1; 04606 return CLI_SUCCESS; 04607 }
static void rtp_bridge_lock | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 833 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().
00834 { 00835 #ifdef P2P_INTENSE 00836 ast_mutex_lock(&rtp->bridge_lock); 00837 #endif 00838 return; 00839 }
static void rtp_bridge_unlock | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 841 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().
00842 { 00843 #ifdef P2P_INTENSE 00844 ast_mutex_unlock(&rtp->bridge_lock); 00845 #endif 00846 return; 00847 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 904 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().
00905 { 00906 if (rtpdebug == 0) 00907 return 0; 00908 if (rtpdebugaddr.sin_addr.s_addr) { 00909 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00910 && (rtpdebugaddr.sin_port != addr->sin_port)) 00911 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00912 return 0; 00913 } 00914 return 1; 00915 }
static char* rtp_do_debug_ip | ( | struct ast_cli_args * | a, | |
int | deprecated | |||
) | [static] |
Definition at line 4545 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().
04546 { 04547 struct hostent *hp; 04548 struct ast_hostent ahp; 04549 int port = 0; 04550 char *p, *arg; 04551 04552 if (deprecated == 1) { 04553 arg = a->argv[3]; 04554 } else { 04555 arg = a->argv[4]; 04556 } 04557 p = strstr(arg, ":"); 04558 if (p) { 04559 *p = '\0'; 04560 p++; 04561 port = atoi(p); 04562 } 04563 hp = ast_gethostbyname(arg, &ahp); 04564 if (hp == NULL) { 04565 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04566 return CLI_FAILURE; 04567 } 04568 rtpdebugaddr.sin_family = AF_INET; 04569 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 04570 rtpdebugaddr.sin_port = htons(port); 04571 if (port == 0) 04572 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 04573 else 04574 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 04575 rtpdebug = 1; 04576 return CLI_SUCCESS; 04577 }
static int rtp_get_rate | ( | int | subclass | ) | [static] |
Definition at line 737 of file rtp.c.
References AST_FORMAT_G722, and ast_format_rate().
Referenced by ast_rtp_raw_write(), ast_rtp_read(), calc_rxstamp(), process_cisco_dtmf(), and process_rfc2833().
00738 { 00739 return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass); 00740 }
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 5000 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().
05001 { 05002 struct rtp_red *r; 05003 int x; 05004 05005 if (!(r = ast_calloc(1, sizeof(struct rtp_red)))) 05006 return -1; 05007 05008 r->t140.frametype = AST_FRAME_TEXT; 05009 r->t140.subclass = AST_FORMAT_T140RED; 05010 r->t140.data.ptr = &r->buf_data; 05011 05012 r->t140.ts = 0; 05013 r->t140red = r->t140; 05014 r->t140red.data.ptr = &r->t140red_data; 05015 r->t140red.datalen = 0; 05016 r->ti = ti; 05017 r->num_gen = num_gen; 05018 r->hdrlen = num_gen * 4 + 1; 05019 r->prev_ts = 0; 05020 05021 for (x = 0; x < num_gen; x++) { 05022 r->pt[x] = red_data_pt[x]; 05023 r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 05024 r->t140red_data[x*4] = r->pt[x]; 05025 } 05026 r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */ 05027 r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp); 05028 rtp->red = r; 05029 05030 r->t140.datalen = 0; 05031 05032 return 0; 05033 }
static int rtp_socket | ( | const char * | type | ) | [static] |
Open RTP or RTCP socket for a session. Print a message on failure.
Definition at line 2474 of file rtp.c.
References ast_log(), errno, LOG_WARNING, and s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
02475 { 02476 int s = socket(AF_INET, SOCK_DGRAM, 0); 02477 if (s < 0) { 02478 if (type == NULL) 02479 type = "RTP/RTCP"; 02480 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno)); 02481 } else { 02482 long flags = fcntl(s, F_GETFL); 02483 fcntl(s, F_SETFL, flags | O_NONBLOCK); 02484 #ifdef SO_NO_CHECK 02485 if (nochecksums) 02486 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 02487 #endif 02488 } 02489 return s; 02490 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 1175 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and f.
Referenced by p2p_callback_disable().
01176 { 01177 struct ast_rtp *rtp = cbdata; 01178 struct ast_frame *f; 01179 f = ast_rtp_read(rtp); 01180 if (f) { 01181 if (rtp->callback) 01182 rtp->callback(rtp, f, rtp->data); 01183 } 01184 return 1; 01185 }
static double stddev_compute | ( | double | stddev, | |
double | sample, | |||
double | normdev, | |||
double | normdev_curent, | |||
unsigned int | sample_count | |||
) | [static] |
Definition at line 858 of file rtp.c.
References SQUARE.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().
00859 { 00860 /* 00861 for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf 00862 return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1)); 00863 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 00864 optimized formula 00865 */ 00866 #define SQUARE(x) ((x) * (x)) 00867 00868 stddev = sample_count * stddev; 00869 sample_count++; 00870 00871 return stddev + 00872 ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) + 00873 ( SQUARE(sample - normdev_curent) / sample_count ); 00874 00875 #undef SQUARE 00876 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
helper function to print attribute names
Definition at line 398 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().
00399 { 00400 switch (msg) { 00401 case STUN_MAPPED_ADDRESS: 00402 return "Mapped Address"; 00403 case STUN_RESPONSE_ADDRESS: 00404 return "Response Address"; 00405 case STUN_CHANGE_REQUEST: 00406 return "Change Request"; 00407 case STUN_SOURCE_ADDRESS: 00408 return "Source Address"; 00409 case STUN_CHANGED_ADDRESS: 00410 return "Changed Address"; 00411 case STUN_USERNAME: 00412 return "Username"; 00413 case STUN_PASSWORD: 00414 return "Password"; 00415 case STUN_MESSAGE_INTEGRITY: 00416 return "Message Integrity"; 00417 case STUN_ERROR_CODE: 00418 return "Error Code"; 00419 case STUN_UNKNOWN_ATTRIBUTES: 00420 return "Unknown Attributes"; 00421 case STUN_REFLECTED_FROM: 00422 return "Reflected From"; 00423 } 00424 return "Non-RFC3489 Attribute"; 00425 }
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 615 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().
00616 { 00617 struct stun_addr *addr = (struct stun_addr *)(attr + 1); 00618 struct sockaddr_in *sa = (struct sockaddr_in *)arg; 00619 00620 if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8) 00621 return 1; /* not us. */ 00622 sa->sin_port = addr->port; 00623 sa->sin_addr.s_addr = addr->addr; 00624 return 0; 00625 }
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 517 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().
00519 { 00520 struct stun_header *hdr = (struct stun_header *)data; 00521 struct stun_attr *attr; 00522 struct stun_state st; 00523 int ret = STUN_IGNORE; 00524 int x; 00525 00526 /* On entry, 'len' is the length of the udp payload. After the 00527 * initial checks it becomes the size of unprocessed options, 00528 * while 'data' is advanced accordingly. 00529 */ 00530 if (len < sizeof(struct stun_header)) { 00531 ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header)); 00532 return -1; 00533 } 00534 len -= sizeof(struct stun_header); 00535 data += sizeof(struct stun_header); 00536 x = ntohs(hdr->msglen); /* len as advertised in the message */ 00537 if (stundebug) 00538 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x); 00539 if (x > len) { 00540 ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len); 00541 } else 00542 len = x; 00543 memset(&st, 0, sizeof(st)); 00544 while (len) { 00545 if (len < sizeof(struct stun_attr)) { 00546 ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr)); 00547 break; 00548 } 00549 attr = (struct stun_attr *)data; 00550 /* compute total attribute length */ 00551 x = ntohs(attr->len) + sizeof(struct stun_attr); 00552 if (x > len) { 00553 ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len); 00554 break; 00555 } 00556 if (stun_cb) 00557 stun_cb(attr, arg); 00558 if (stun_process_attr(&st, attr)) { 00559 ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00560 break; 00561 } 00562 /* Clear attribute id: in case previous entry was a string, 00563 * this will act as the terminator for the string. 00564 */ 00565 attr->attr = 0; 00566 data += x; 00567 len -= x; 00568 } 00569 /* Null terminate any string. 00570 * XXX NOTE, we write past the size of the buffer passed by the 00571 * caller, so this is potentially dangerous. The only thing that 00572 * saves us is that usually we read the incoming message in a 00573 * much larger buffer in the struct ast_rtp 00574 */ 00575 *data = '\0'; 00576 00577 /* Now prepare to generate a reply, which at the moment is done 00578 * only for properly formed (len == 0) STUN_BINDREQ messages. 00579 */ 00580 if (len == 0) { 00581 unsigned char respdata[1024]; 00582 struct stun_header *resp = (struct stun_header *)respdata; 00583 int resplen = 0; /* len excluding header */ 00584 int respleft = sizeof(respdata) - sizeof(struct stun_header); 00585 00586 resp->id = hdr->id; 00587 resp->msgtype = 0; 00588 resp->msglen = 0; 00589 attr = (struct stun_attr *)resp->ies; 00590 switch (ntohs(hdr->msgtype)) { 00591 case STUN_BINDREQ: 00592 if (stundebug) 00593 ast_verbose("STUN Bind Request, username: %s\n", 00594 st.username ? st.username : "<none>"); 00595 if (st.username) 00596 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00597 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00598 resp->msglen = htons(resplen); 00599 resp->msgtype = htons(STUN_BINDRESP); 00600 stun_send(s, src, resp); 00601 ret = STUN_ACCEPT; 00602 break; 00603 default: 00604 if (stundebug) 00605 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00606 } 00607 } 00608 return ret; 00609 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
helper function to print message names
Definition at line 378 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00379 { 00380 switch (msg) { 00381 case STUN_BINDREQ: 00382 return "Binding Request"; 00383 case STUN_BINDRESP: 00384 return "Binding Response"; 00385 case STUN_BINDERR: 00386 return "Binding Error Response"; 00387 case STUN_SECREQ: 00388 return "Shared Secret Request"; 00389 case STUN_SECRESP: 00390 return "Shared Secret Response"; 00391 case STUN_SECERR: 00392 return "Shared Secret Error Response"; 00393 } 00394 return "Non-RFC3489 Message"; 00395 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 433 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().
00434 { 00435 if (stundebug) 00436 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00437 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00438 switch (ntohs(attr->attr)) { 00439 case STUN_USERNAME: 00440 state->username = (const char *) (attr->value); 00441 break; 00442 case STUN_PASSWORD: 00443 state->password = (const char *) (attr->value); 00444 break; 00445 default: 00446 if (stundebug) 00447 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00448 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00449 } 00450 return 0; 00451 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
helper function to generate a random request id
Definition at line 494 of file rtp.c.
References ast_random(), stun_trans_id::id, and stun_header::id.
Referenced by ast_stun_request().
00495 { 00496 int x; 00497 for (x = 0; x < 4; x++) 00498 req->id.id[x] = ast_random(); 00499 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
wrapper to send an STUN message
Definition at line 487 of file rtp.c.
References stun_header::msglen.
Referenced by ast_stun_request(), and stun_handle_packet().
00488 { 00489 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00490 (struct sockaddr *)dst, sizeof(*dst)); 00491 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 715 of file rtp.c.
References sec.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00716 { 00717 unsigned int sec, usec, frac; 00718 sec = when.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00719 usec = when.tv_usec; 00720 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00721 *msw = sec; 00722 *lsw = frac; 00723 }
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 1954 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 1999 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 1955 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), aji_handle_presence(), amixer_max(), ast_call_forward(), ast_format_str_reduce(), 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().