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