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