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 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 2743 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().
02744 { 02745 *found = 1; 02746 02747 if (!strcasecmp(qos, "remote_maxjitter")) 02748 return rtp->rtcp->reported_maxjitter * 1000.0; 02749 if (!strcasecmp(qos, "remote_minjitter")) 02750 return rtp->rtcp->reported_minjitter * 1000.0; 02751 if (!strcasecmp(qos, "remote_normdevjitter")) 02752 return rtp->rtcp->reported_normdev_jitter * 1000.0; 02753 if (!strcasecmp(qos, "remote_stdevjitter")) 02754 return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0; 02755 02756 if (!strcasecmp(qos, "local_maxjitter")) 02757 return rtp->rtcp->maxrxjitter * 1000.0; 02758 if (!strcasecmp(qos, "local_minjitter")) 02759 return rtp->rtcp->minrxjitter * 1000.0; 02760 if (!strcasecmp(qos, "local_normdevjitter")) 02761 return rtp->rtcp->normdev_rxjitter * 1000.0; 02762 if (!strcasecmp(qos, "local_stdevjitter")) 02763 return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0; 02764 02765 if (!strcasecmp(qos, "maxrtt")) 02766 return rtp->rtcp->maxrtt * 1000.0; 02767 if (!strcasecmp(qos, "minrtt")) 02768 return rtp->rtcp->minrtt * 1000.0; 02769 if (!strcasecmp(qos, "normdevrtt")) 02770 return rtp->rtcp->normdevrtt * 1000.0; 02771 if (!strcasecmp(qos, "stdevrtt")) 02772 return sqrt(rtp->rtcp->stdevrtt) * 1000.0; 02773 02774 *found = 0; 02775 02776 return 0.0; 02777 }
| static char* __ast_rtp_get_quality | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2946 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().
02947 { 02948 /* 02949 *ssrc our ssrc 02950 *themssrc their ssrc 02951 *lp lost packets 02952 *rxjitter our calculated jitter(rx) 02953 *rxcount no. received packets 02954 *txjitter reported jitter of the other end 02955 *txcount transmitted packets 02956 *rlp remote lost packets 02957 *rtt round trip time 02958 */ 02959 02960 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 02961 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02962 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02963 rtp->ssrc, 02964 rtp->themssrc, 02965 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02966 rtp->rxjitter, 02967 rtp->rxcount, 02968 (double)rtp->rtcp->reported_jitter / 65536.0, 02969 rtp->txcount, 02970 rtp->rtcp->reported_lost, 02971 rtp->rtcp->rtt 02972 ); 02973 } else { 02974 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;", 02975 rtp->ssrc, 02976 rtp->themssrc, 02977 rtp->rxjitter, 02978 rtp->rxcount, 02979 rtp->txcount 02980 ); 02981 } 02982 02983 return rtp->rtcp->quality; 02984 }
| static char* __ast_rtp_get_quality_jitter | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2825 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().
02826 { 02827 /* 02828 *ssrc our ssrc 02829 *themssrc their ssrc 02830 *lp lost packets 02831 *rxjitter our calculated jitter(rx) 02832 *rxcount no. received packets 02833 *txjitter reported jitter of the other end 02834 *txcount transmitted packets 02835 *rlp remote lost packets 02836 *rtt round trip time 02837 */ 02838 #define RTCP_JITTER_FORMAT1 \ 02839 "minrxjitter=%f;" \ 02840 "maxrxjitter=%f;" \ 02841 "avgrxjitter=%f;" \ 02842 "stdevrxjitter=%f;" \ 02843 "reported_minjitter=%f;" \ 02844 "reported_maxjitter=%f;" \ 02845 "reported_avgjitter=%f;" \ 02846 "reported_stdevjitter=%f;" 02847 02848 #define RTCP_JITTER_FORMAT2 \ 02849 "rxjitter=%f;" 02850 02851 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 02852 snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1, 02853 rtp->rtcp->minrxjitter, 02854 rtp->rtcp->maxrxjitter, 02855 rtp->rtcp->normdev_rxjitter, 02856 sqrt(rtp->rtcp->stdev_rxjitter), 02857 rtp->rtcp->reported_minjitter, 02858 rtp->rtcp->reported_maxjitter, 02859 rtp->rtcp->reported_normdev_jitter, 02860 sqrt(rtp->rtcp->reported_stdev_jitter) 02861 ); 02862 } else { 02863 snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2, 02864 rtp->rxjitter 02865 ); 02866 } 02867 02868 return rtp->rtcp->quality_jitter; 02869 02870 #undef RTCP_JITTER_FORMAT1 02871 #undef RTCP_JITTER_FORMAT2 02872 }
| static char* __ast_rtp_get_quality_loss | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2874 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().
02875 { 02876 unsigned int lost; 02877 unsigned int extended; 02878 unsigned int expected; 02879 int fraction; 02880 02881 #define RTCP_LOSS_FORMAT1 \ 02882 "minrxlost=%f;" \ 02883 "maxrxlost=%f;" \ 02884 "avgrxlostr=%f;" \ 02885 "stdevrxlost=%f;" \ 02886 "reported_minlost=%f;" \ 02887 "reported_maxlost=%f;" \ 02888 "reported_avglost=%f;" \ 02889 "reported_stdevlost=%f;" 02890 02891 #define RTCP_LOSS_FORMAT2 \ 02892 "lost=%d;" \ 02893 "expected=%d;" 02894 02895 if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) { 02896 snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1, 02897 rtp->rtcp->minrxlost, 02898 rtp->rtcp->maxrxlost, 02899 rtp->rtcp->normdev_rxlost, 02900 sqrt(rtp->rtcp->stdev_rxlost), 02901 rtp->rtcp->reported_minlost, 02902 rtp->rtcp->reported_maxlost, 02903 rtp->rtcp->reported_normdev_lost, 02904 sqrt(rtp->rtcp->reported_stdev_lost) 02905 ); 02906 } else { 02907 extended = rtp->cycles + rtp->lastrxseqno; 02908 expected = extended - rtp->seedrxseqno + 1; 02909 if (rtp->rxcount > expected) 02910 expected += rtp->rxcount - expected; 02911 lost = expected - rtp->rxcount; 02912 02913 if (!expected || lost <= 0) 02914 fraction = 0; 02915 else 02916 fraction = (lost << 8) / expected; 02917 02918 snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2, 02919 lost, 02920 expected 02921 ); 02922 } 02923 02924 return rtp->rtcp->quality_loss; 02925 02926 #undef RTCP_LOSS_FORMAT1 02927 #undef RTCP_LOSS_FORMAT2 02928 }
| static char* __ast_rtp_get_quality_rtt | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 2930 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().
02931 { 02932 if (rtp->rtcp && rtp->rtcp->rtcp_info) { 02933 snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;", 02934 rtp->rtcp->minrtt, 02935 rtp->rtcp->maxrtt, 02936 rtp->rtcp->normdevrtt, 02937 sqrt(rtp->rtcp->stdevrtt) 02938 ); 02939 } else { 02940 snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available"); 02941 } 02942 02943 return rtp->rtcp->quality_rtt; 02944 }
| static int __ast_rtp_reload | ( | int | reload | ) | [static] |
Definition at line 4813 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().
04814 { 04815 struct ast_config *cfg; 04816 const char *s; 04817 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04818 04819 if ((cfg = ast_config_load2("rtp.conf", "rtp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 04820 return 0; 04821 04822 rtpstart = 5000; 04823 rtpend = 31000; 04824 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04825 strictrtp = STRICT_RTP_OPEN; 04826 if (cfg) { 04827 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 04828 rtpstart = atoi(s); 04829 if (rtpstart < 1024) 04830 rtpstart = 1024; 04831 if (rtpstart > 65535) 04832 rtpstart = 65535; 04833 } 04834 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 04835 rtpend = atoi(s); 04836 if (rtpend < 1024) 04837 rtpend = 1024; 04838 if (rtpend > 65535) 04839 rtpend = 65535; 04840 } 04841 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 04842 rtcpinterval = atoi(s); 04843 if (rtcpinterval == 0) 04844 rtcpinterval = 0; /* Just so we're clear... it's zero */ 04845 if (rtcpinterval < RTCP_MIN_INTERVALMS) 04846 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 04847 if (rtcpinterval > RTCP_MAX_INTERVALMS) 04848 rtcpinterval = RTCP_MAX_INTERVALMS; 04849 } 04850 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 04851 #ifdef SO_NO_CHECK 04852 if (ast_false(s)) 04853 nochecksums = 1; 04854 else 04855 nochecksums = 0; 04856 #else 04857 if (ast_false(s)) 04858 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 04859 #endif 04860 } 04861 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 04862 dtmftimeout = atoi(s); 04863 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) { 04864 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 04865 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 04866 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04867 }; 04868 } 04869 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) { 04870 strictrtp = ast_true(s); 04871 } 04872 ast_config_destroy(cfg); 04873 } 04874 if (rtpstart >= rtpend) { 04875 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 04876 rtpstart = 5000; 04877 rtpend = 31000; 04878 } 04879 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 04880 return 0; 04881 }
| 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 2455 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().
02456 { 02457 struct ast_rtcp *rtcp; 02458 02459 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 02460 return NULL; 02461 rtcp->s = rtp_socket("RTCP"); 02462 rtcp->us.sin_family = AF_INET; 02463 rtcp->them.sin_family = AF_INET; 02464 rtcp->schedid = -1; 02465 02466 if (rtcp->s < 0) { 02467 ast_free(rtcp); 02468 return NULL; 02469 } 02470 02471 return rtcp; 02472 }
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 3258 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 3516 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().
03517 { 03518 struct ast_rtp *rtp = (struct ast_rtp *)data; 03519 int res; 03520 03521 if (!rtp || !rtp->rtcp) 03522 return 0; 03523 03524 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 03525 res = ast_rtcp_write_sr(data); 03526 else 03527 res = ast_rtcp_write_rr(data); 03528 03529 return res; 03530 }
| static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recipient's report.
Definition at line 3403 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().
03404 { 03405 struct ast_rtp *rtp = (struct ast_rtp *)data; 03406 int res; 03407 int len = 32; 03408 unsigned int lost; 03409 unsigned int extended; 03410 unsigned int expected; 03411 unsigned int expected_interval; 03412 unsigned int received_interval; 03413 int lost_interval; 03414 struct timeval now; 03415 unsigned int *rtcpheader; 03416 char bdata[1024]; 03417 struct timeval dlsr; 03418 int fraction; 03419 03420 double rxlost_current; 03421 03422 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 03423 return 0; 03424 03425 if (!rtp->rtcp->them.sin_addr.s_addr) { 03426 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 03427 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03428 return 0; 03429 } 03430 03431 extended = rtp->cycles + rtp->lastrxseqno; 03432 expected = extended - rtp->seedrxseqno + 1; 03433 lost = expected - rtp->rxcount; 03434 expected_interval = expected - rtp->rtcp->expected_prior; 03435 rtp->rtcp->expected_prior = expected; 03436 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 03437 rtp->rtcp->received_prior = rtp->rxcount; 03438 lost_interval = expected_interval - received_interval; 03439 03440 if (lost_interval <= 0) 03441 rtp->rtcp->rxlost = 0; 03442 else rtp->rtcp->rxlost = rtp->rtcp->rxlost; 03443 if (rtp->rtcp->rxlost_count == 0) 03444 rtp->rtcp->minrxlost = rtp->rtcp->rxlost; 03445 if (lost_interval < rtp->rtcp->minrxlost) 03446 rtp->rtcp->minrxlost = rtp->rtcp->rxlost; 03447 if (lost_interval > rtp->rtcp->maxrxlost) 03448 rtp->rtcp->maxrxlost = rtp->rtcp->rxlost; 03449 03450 rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count); 03451 rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count); 03452 rtp->rtcp->normdev_rxlost = rxlost_current; 03453 rtp->rtcp->rxlost_count++; 03454 03455 if (expected_interval == 0 || lost_interval <= 0) 03456 fraction = 0; 03457 else 03458 fraction = (lost_interval << 8) / expected_interval; 03459 gettimeofday(&now, NULL); 03460 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 03461 rtcpheader = (unsigned int *)bdata; 03462 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 03463 rtcpheader[1] = htonl(rtp->ssrc); 03464 rtcpheader[2] = htonl(rtp->themssrc); 03465 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 03466 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 03467 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 03468 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 03469 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 03470 03471 if (rtp->rtcp->sendfur) { 03472 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 03473 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 03474 len += 8; 03475 rtp->rtcp->sendfur = 0; 03476 } 03477 03478 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 03479 it can change mid call, and SDES can't) */ 03480 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 03481 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 03482 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 03483 len += 12; 03484 03485 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 03486 03487 if (res < 0) { 03488 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 03489 /* Remove the scheduler */ 03490 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03491 return 0; 03492 } 03493 03494 rtp->rtcp->rr_count++; 03495 03496 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 03497 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 03498 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 03499 " IA jitter: %.4f\n" 03500 " Their last SR: %u\n" 03501 " DLSR: %4.4f (sec)\n\n", 03502 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 03503 ntohs(rtp->rtcp->them.sin_port), 03504 rtp->ssrc, rtp->themssrc, fraction, lost, 03505 rtp->rxjitter, 03506 rtp->rtcp->themrxlsr, 03507 (double)(ntohl(rtcpheader[7])/65536.0)); 03508 } 03509 03510 return res; 03511 }
| static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 3270 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().
03271 { 03272 struct ast_rtp *rtp = (struct ast_rtp *)data; 03273 int res; 03274 int len = 0; 03275 struct timeval now; 03276 unsigned int now_lsw; 03277 unsigned int now_msw; 03278 unsigned int *rtcpheader; 03279 unsigned int lost; 03280 unsigned int extended; 03281 unsigned int expected; 03282 unsigned int expected_interval; 03283 unsigned int received_interval; 03284 int lost_interval; 03285 int fraction; 03286 struct timeval dlsr; 03287 char bdata[512]; 03288 03289 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 03290 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 03291 return 0; 03292 03293 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 03294 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 03295 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03296 return 0; 03297 } 03298 03299 gettimeofday(&now, NULL); 03300 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 03301 rtcpheader = (unsigned int *)bdata; 03302 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 03303 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 03304 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 03305 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 03306 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 03307 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 03308 len += 28; 03309 03310 extended = rtp->cycles + rtp->lastrxseqno; 03311 expected = extended - rtp->seedrxseqno + 1; 03312 if (rtp->rxcount > expected) 03313 expected += rtp->rxcount - expected; 03314 lost = expected - rtp->rxcount; 03315 expected_interval = expected - rtp->rtcp->expected_prior; 03316 rtp->rtcp->expected_prior = expected; 03317 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 03318 rtp->rtcp->received_prior = rtp->rxcount; 03319 lost_interval = expected_interval - received_interval; 03320 if (expected_interval == 0 || lost_interval <= 0) 03321 fraction = 0; 03322 else 03323 fraction = (lost_interval << 8) / expected_interval; 03324 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 03325 rtcpheader[7] = htonl(rtp->themssrc); 03326 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 03327 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 03328 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 03329 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 03330 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 03331 len += 24; 03332 03333 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 03334 03335 if (rtp->rtcp->sendfur) { 03336 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 03337 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 03338 len += 8; 03339 rtp->rtcp->sendfur = 0; 03340 } 03341 03342 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 03343 /* it can change mid call, and SDES can't) */ 03344 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 03345 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 03346 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 03347 len += 12; 03348 03349 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 03350 if (res < 0) { 03351 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)); 03352 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03353 return 0; 03354 } 03355 03356 /* FIXME Don't need to get a new one */ 03357 gettimeofday(&rtp->rtcp->txlsr, NULL); 03358 rtp->rtcp->sr_count++; 03359 03360 rtp->rtcp->lastsrtxcount = rtp->txcount; 03361 03362 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 03363 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 03364 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 03365 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 03366 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 03367 ast_verbose(" Sent packets: %u\n", rtp->txcount); 03368 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 03369 ast_verbose(" Report block:\n"); 03370 ast_verbose(" Fraction lost: %u\n", fraction); 03371 ast_verbose(" Cumulative loss: %u\n", lost); 03372 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 03373 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 03374 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 03375 } 03376 manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n" 03377 "OurSSRC: %u\r\n" 03378 "SentNTP: %u.%010u\r\n" 03379 "SentRTP: %u\r\n" 03380 "SentPackets: %u\r\n" 03381 "SentOctets: %u\r\n" 03382 "ReportBlock:\r\n" 03383 "FractionLost: %u\r\n" 03384 "CumulativeLoss: %u\r\n" 03385 "IAJitter: %.4f\r\n" 03386 "TheirLastSR: %u\r\n" 03387 "DLSR: %4.4f (sec)\r\n", 03388 ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), 03389 rtp->ssrc, 03390 (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096, 03391 rtp->lastts, 03392 rtp->txcount, 03393 rtp->txoctetcount, 03394 fraction, 03395 lost, 03396 rtp->rxjitter, 03397 rtp->rtcp->themrxlsr, 03398 (double)(ntohl(rtcpheader[12])/65536.0)); 03399 return res; 03400 }
| 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 4346 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.
04347 { 04348 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 04349 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 04350 struct ast_rtp *tp0 = NULL, *tp1 = NULL; /* Text RTP channels */ 04351 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 04352 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; 04353 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; 04354 enum ast_bridge_result res = AST_BRIDGE_FAILED; 04355 int codec0 = 0, codec1 = 0; 04356 void *pvt0 = NULL, *pvt1 = NULL; 04357 04358 /* Lock channels */ 04359 ast_channel_lock(c0); 04360 while (ast_channel_trylock(c1)) { 04361 ast_channel_unlock(c0); 04362 usleep(1); 04363 ast_channel_lock(c0); 04364 } 04365 04366 /* Ensure neither channel got hungup during lock avoidance */ 04367 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 04368 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 04369 ast_channel_unlock(c0); 04370 ast_channel_unlock(c1); 04371 return AST_BRIDGE_FAILED; 04372 } 04373 04374 /* Find channel driver interfaces */ 04375 if (!(pr0 = get_proto(c0))) { 04376 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 04377 ast_channel_unlock(c0); 04378 ast_channel_unlock(c1); 04379 return AST_BRIDGE_FAILED; 04380 } 04381 if (!(pr1 = get_proto(c1))) { 04382 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 04383 ast_channel_unlock(c0); 04384 ast_channel_unlock(c1); 04385 return AST_BRIDGE_FAILED; 04386 } 04387 04388 /* Get channel specific interface structures */ 04389 pvt0 = c0->tech_pvt; 04390 pvt1 = c1->tech_pvt; 04391 04392 /* Get audio and video interface (if native bridge is possible) */ 04393 audio_p0_res = pr0->get_rtp_info(c0, &p0); 04394 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 04395 text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 04396 audio_p1_res = pr1->get_rtp_info(c1, &p1); 04397 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 04398 text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 04399 04400 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 04401 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 04402 audio_p0_res = AST_RTP_GET_FAILED; 04403 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 04404 audio_p1_res = AST_RTP_GET_FAILED; 04405 04406 /* Check if a bridge is possible (partial/native) */ 04407 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 04408 /* Somebody doesn't want to play... */ 04409 ast_channel_unlock(c0); 04410 ast_channel_unlock(c1); 04411 return AST_BRIDGE_FAILED_NOWARN; 04412 } 04413 04414 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 04415 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 04416 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 04417 audio_p0_res = AST_RTP_TRY_PARTIAL; 04418 } 04419 04420 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 04421 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 04422 audio_p1_res = AST_RTP_TRY_PARTIAL; 04423 } 04424 04425 /* If both sides are not using the same method of DTMF transmission 04426 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 04427 * -------------------------------------------------- 04428 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 04429 * |-----------|------------|-----------------------| 04430 * | Inband | False | True | 04431 * | RFC2833 | True | True | 04432 * | SIP INFO | False | False | 04433 * -------------------------------------------------- 04434 * However, if DTMF from both channels is being monitored by the core, then 04435 * we can still do packet-to-packet bridging, because passing through the 04436 * core will handle DTMF mode translation. 04437 */ 04438 if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 04439 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 04440 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 04441 ast_channel_unlock(c0); 04442 ast_channel_unlock(c1); 04443 return AST_BRIDGE_FAILED_NOWARN; 04444 } 04445 audio_p0_res = AST_RTP_TRY_PARTIAL; 04446 audio_p1_res = AST_RTP_TRY_PARTIAL; 04447 } 04448 04449 /* If we need to feed frames into the core don't do a P2P bridge */ 04450 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 04451 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 04452 ast_channel_unlock(c0); 04453 ast_channel_unlock(c1); 04454 return AST_BRIDGE_FAILED_NOWARN; 04455 } 04456 04457 /* Get codecs from both sides */ 04458 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 04459 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 04460 if (codec0 && codec1 && !(codec0 & codec1)) { 04461 /* Hey, we can't do native bridging if both parties speak different codecs */ 04462 ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 04463 ast_channel_unlock(c0); 04464 ast_channel_unlock(c1); 04465 return AST_BRIDGE_FAILED_NOWARN; 04466 } 04467 04468 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 04469 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 04470 struct ast_format_list fmt0, fmt1; 04471 04472 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 04473 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 04474 ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n"); 04475 ast_channel_unlock(c0); 04476 ast_channel_unlock(c1); 04477 return AST_BRIDGE_FAILED_NOWARN; 04478 } 04479 /* They must also be using the same packetization */ 04480 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 04481 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 04482 if (fmt0.cur_ms != fmt1.cur_ms) { 04483 ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n"); 04484 ast_channel_unlock(c0); 04485 ast_channel_unlock(c1); 04486 return AST_BRIDGE_FAILED_NOWARN; 04487 } 04488 04489 ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 04490 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 04491 } else { 04492 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04493 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 04494 } 04495 04496 return res; 04497 }
| int ast_rtp_codec_getformat | ( | int | pt | ) |
get format from predefined dynamic payload format
Definition at line 3738 of file rtp.c.
References rtpPayloadType::code, and MAX_RTP_PT.
Referenced by process_sdp_a_audio().
03739 { 03740 if (pt < 0 || pt >= MAX_RTP_PT) 03741 return 0; /* bogus payload type */ 03742 03743 if (static_RTP_PT[pt].isAstFormat) 03744 return static_RTP_PT[pt].code; 03745 else 03746 return 0; 03747 }
| struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) | [read] |
Get codec preference.
Definition at line 3733 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp_a_audio().
03734 { 03735 return &rtp->pref; 03736 }
| void ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
| struct ast_codec_pref * | prefs | |||
| ) |
Set codec preference.
Definition at line 3687 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().
03688 { 03689 struct ast_format_list current_format_old, current_format_new; 03690 03691 /* if no packets have been sent through this session yet, then 03692 * changing preferences does not require any extra work 03693 */ 03694 if (rtp->lasttxformat == 0) { 03695 rtp->pref = *prefs; 03696 return; 03697 } 03698 03699 current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 03700 03701 rtp->pref = *prefs; 03702 03703 current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 03704 03705 /* if the framing desired for the current format has changed, we may have to create 03706 * or adjust the smoother for this session 03707 */ 03708 if ((current_format_new.inc_ms != 0) && 03709 (current_format_new.cur_ms != current_format_old.cur_ms)) { 03710 int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms; 03711 03712 if (rtp->smoother) { 03713 ast_smoother_reconfigure(rtp->smoother, new_size); 03714 if (option_debug) { 03715 ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size); 03716 } 03717 } else { 03718 if (!(rtp->smoother = ast_smoother_new(new_size))) { 03719 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 03720 return; 03721 } 03722 if (current_format_new.flags) { 03723 ast_smoother_set_flags(rtp->smoother, current_format_new.flags); 03724 } 03725 if (option_debug) { 03726 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 03727 } 03728 } 03729 } 03730 03731 }
| void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Destroy RTP session
Definition at line 3017 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().
03018 { 03019 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 03020 /*Print some info on the call here */ 03021 ast_verbose(" RTP-stats\n"); 03022 ast_verbose("* Our Receiver:\n"); 03023 ast_verbose(" SSRC: %u\n", rtp->themssrc); 03024 ast_verbose(" Received packets: %u\n", rtp->rxcount); 03025 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0); 03026 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 03027 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 03028 ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0); 03029 ast_verbose("* Our Sender:\n"); 03030 ast_verbose(" SSRC: %u\n", rtp->ssrc); 03031 ast_verbose(" Sent packets: %u\n", rtp->txcount); 03032 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0); 03033 ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0); 03034 ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0); 03035 ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0); 03036 } 03037 03038 manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n" 03039 "ReceivedPackets: %u\r\n" 03040 "LostPackets: %u\r\n" 03041 "Jitter: %.4f\r\n" 03042 "Transit: %.4f\r\n" 03043 "RRCount: %u\r\n", 03044 rtp->themssrc, 03045 rtp->rxcount, 03046 rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0, 03047 rtp->rxjitter, 03048 rtp->rxtransit, 03049 rtp->rtcp ? rtp->rtcp->rr_count : 0); 03050 manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n" 03051 "SentPackets: %u\r\n" 03052 "LostPackets: %u\r\n" 03053 "Jitter: %u\r\n" 03054 "SRCount: %u\r\n" 03055 "RTT: %f\r\n", 03056 rtp->ssrc, 03057 rtp->txcount, 03058 rtp->rtcp ? rtp->rtcp->reported_lost : 0, 03059 rtp->rtcp ? rtp->rtcp->reported_jitter : 0, 03060 rtp->rtcp ? rtp->rtcp->sr_count : 0, 03061 rtp->rtcp ? rtp->rtcp->rtt : 0); 03062 if (rtp->smoother) 03063 ast_smoother_free(rtp->smoother); 03064 if (rtp->ioid) 03065 ast_io_remove(rtp->io, rtp->ioid); 03066 if (rtp->s > -1) 03067 close(rtp->s); 03068 if (rtp->rtcp) { 03069 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 03070 close(rtp->rtcp->s); 03071 ast_free(rtp->rtcp); 03072 rtp->rtcp=NULL; 03073 } 03074 #ifdef P2P_INTENSE 03075 ast_mutex_destroy(&rtp->bridge_lock); 03076 #endif 03077 ast_free(rtp); 03078 }
| 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 2069 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.
02070 { 02071 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 02072 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 02073 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 02074 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 02075 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; 02076 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; 02077 int srccodec, destcodec, nat_active = 0; 02078 02079 /* Lock channels */ 02080 ast_channel_lock(c0); 02081 if (c1) { 02082 while (ast_channel_trylock(c1)) { 02083 ast_channel_unlock(c0); 02084 usleep(1); 02085 ast_channel_lock(c0); 02086 } 02087 } 02088 02089 /* Find channel driver interfaces */ 02090 destpr = get_proto(c0); 02091 if (c1) 02092 srcpr = get_proto(c1); 02093 if (!destpr) { 02094 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name); 02095 ast_channel_unlock(c0); 02096 if (c1) 02097 ast_channel_unlock(c1); 02098 return -1; 02099 } 02100 if (!srcpr) { 02101 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>"); 02102 ast_channel_unlock(c0); 02103 if (c1) 02104 ast_channel_unlock(c1); 02105 return -1; 02106 } 02107 02108 /* Get audio, video and text interface (if native bridge is possible) */ 02109 audio_dest_res = destpr->get_rtp_info(c0, &destp); 02110 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED; 02111 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED; 02112 if (srcpr) { 02113 audio_src_res = srcpr->get_rtp_info(c1, &srcp); 02114 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED; 02115 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED; 02116 } 02117 02118 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 02119 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) { 02120 /* Somebody doesn't want to play... */ 02121 ast_channel_unlock(c0); 02122 if (c1) 02123 ast_channel_unlock(c1); 02124 return -1; 02125 } 02126 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) 02127 srccodec = srcpr->get_codec(c1); 02128 else 02129 srccodec = 0; 02130 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) 02131 destcodec = destpr->get_codec(c0); 02132 else 02133 destcodec = 0; 02134 /* Ensure we have at least one matching codec */ 02135 if (srcp && !(srccodec & destcodec)) { 02136 ast_channel_unlock(c0); 02137 ast_channel_unlock(c1); 02138 return 0; 02139 } 02140 /* Consider empty media as non-existent */ 02141 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 02142 srcp = NULL; 02143 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02144 nat_active = 1; 02145 /* Bridge media early */ 02146 if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active)) 02147 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 02148 ast_channel_unlock(c0); 02149 if (c1) 02150 ast_channel_unlock(c1); 02151 ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 02152 return 0; 02153 }
| 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 2658 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().
02659 { 02660 struct ast_rtp *bridged = NULL; 02661 02662 rtp_bridge_lock(rtp); 02663 bridged = rtp->bridged; 02664 rtp_bridge_unlock(rtp); 02665 02666 return bridged; 02667 }
| 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 2291 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().
02293 { 02294 int pt; 02295 02296 rtp_bridge_lock(rtp); 02297 02298 *astFormats = *nonAstFormats = 0; 02299 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02300 if (rtp->current_RTP_PT[pt].isAstFormat) { 02301 *astFormats |= rtp->current_RTP_PT[pt].code; 02302 } else { 02303 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 02304 } 02305 } 02306 02307 rtp_bridge_unlock(rtp); 02308 }
| int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 2640 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().
02641 { 02642 if ((them->sin_family != AF_INET) || 02643 (them->sin_port != rtp->them.sin_port) || 02644 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02645 them->sin_family = AF_INET; 02646 them->sin_port = rtp->them.sin_port; 02647 them->sin_addr = rtp->them.sin_addr; 02648 return 1; 02649 } 02650 return 0; 02651 }
| 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 2779 of file rtp.c.
References __ast_rtp_get_qos().
Referenced by acf_channel_read().
02780 { 02781 double value; 02782 int found; 02783 02784 value = __ast_rtp_get_qos(rtp, qos, &found); 02785 02786 if (!found) 02787 return -1; 02788 02789 snprintf(buf, buflen, "%.0lf", value); 02790 02791 return 0; 02792 }
| 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 2713 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().
02714 { 02715 if (rtp == NULL) { 02716 if (option_debug > 1) 02717 ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n"); 02718 return 0; 02719 } 02720 if (option_debug > 1 && rtp->rtcp == NULL) { 02721 ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n"); 02722 } 02723 02724 switch (value) { 02725 case AST_RTP_TXCOUNT: 02726 return (unsigned int) rtp->txcount; 02727 case AST_RTP_RXCOUNT: 02728 return (unsigned int) rtp->rxcount; 02729 case AST_RTP_TXJITTER: 02730 return (unsigned int) (rtp->rxjitter * 100.0); 02731 case AST_RTP_RXJITTER: 02732 return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0); 02733 case AST_RTP_RXPLOSS: 02734 return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0; 02735 case AST_RTP_TXPLOSS: 02736 return rtp->rtcp ? rtp->rtcp->reported_lost : 0; 02737 case AST_RTP_RTT: 02738 return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0); 02739 } 02740 return 0; /* To make the compiler happy */ 02741 }
| 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 2986 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().
02987 { 02988 if (qual && rtp) { 02989 qual->local_ssrc = rtp->ssrc; 02990 qual->local_jitter = rtp->rxjitter; 02991 qual->local_count = rtp->rxcount; 02992 qual->remote_ssrc = rtp->themssrc; 02993 qual->remote_count = rtp->txcount; 02994 02995 if (rtp->rtcp) { 02996 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02997 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02998 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02999 qual->rtt = rtp->rtcp->rtt; 03000 } 03001 } 03002 03003 switch (qtype) { 03004 case RTPQOS_SUMMARY: 03005 return __ast_rtp_get_quality(rtp); 03006 case RTPQOS_JITTER: 03007 return __ast_rtp_get_quality_jitter(rtp); 03008 case RTPQOS_LOSS: 03009 return __ast_rtp_get_quality_loss(rtp); 03010 case RTPQOS_RTT: 03011 return __ast_rtp_get_quality_rtt(rtp); 03012 } 03013 03014 return NULL; 03015 }
| 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 2653 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 4889 of file rtp.c.
References __ast_rtp_reload(), and ast_cli_register_multiple().
Referenced by main().
04890 { 04891 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 04892 __ast_rtp_reload(0); 04893 }
| 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 2332 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().
02333 { 02334 int pt = 0; 02335 02336 rtp_bridge_lock(rtp); 02337 02338 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 02339 code == rtp->rtp_lookup_code_cache_code) { 02340 /* Use our cached mapping, to avoid the overhead of the loop below */ 02341 pt = rtp->rtp_lookup_code_cache_result; 02342 rtp_bridge_unlock(rtp); 02343 return pt; 02344 } 02345 02346 /* Check the dynamic list first */ 02347 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02348 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 02349 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02350 rtp->rtp_lookup_code_cache_code = code; 02351 rtp->rtp_lookup_code_cache_result = pt; 02352 rtp_bridge_unlock(rtp); 02353 return pt; 02354 } 02355 } 02356 02357 /* Then the static list */ 02358 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02359 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 02360 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02361 rtp->rtp_lookup_code_cache_code = code; 02362 rtp->rtp_lookup_code_cache_result = pt; 02363 rtp_bridge_unlock(rtp); 02364 return pt; 02365 } 02366 } 02367 02368 rtp_bridge_unlock(rtp); 02369 02370 return -1; 02371 }
| 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 2392 of file rtp.c.
References ast_copy_string(), ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.
Referenced by process_sdp().
02394 { 02395 int format; 02396 unsigned len; 02397 char *end = buf; 02398 char *start = buf; 02399 02400 if (!buf || !size) 02401 return NULL; 02402 02403 snprintf(end, size, "0x%x (", capability); 02404 02405 len = strlen(end); 02406 end += len; 02407 size -= len; 02408 start = end; 02409 02410 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 02411 if (capability & format) { 02412 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 02413 02414 snprintf(end, size, "%s|", name); 02415 len = strlen(end); 02416 end += len; 02417 size -= len; 02418 } 02419 } 02420 02421 if (start == end) 02422 ast_copy_string(start, "nothing)", size); 02423 else if (size > 1) 02424 *(end -1) = ')'; 02425 02426 return buf; 02427 }
| 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 2373 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().
02375 { 02376 unsigned int i; 02377 02378 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02379 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 02380 if (isAstFormat && 02381 (code == AST_FORMAT_G726_AAL2) && 02382 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02383 return "G726-32"; 02384 else 02385 return mimeTypes[i].subtype; 02386 } 02387 } 02388 02389 return ""; 02390 }
| 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 2310 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().
02311 { 02312 struct rtpPayloadType result; 02313 02314 result.isAstFormat = result.code = 0; 02315 02316 if (pt < 0 || pt >= MAX_RTP_PT) 02317 return result; /* bogus payload type */ 02318 02319 /* Start with negotiated codecs */ 02320 rtp_bridge_lock(rtp); 02321 result = rtp->current_RTP_PT[pt]; 02322 rtp_bridge_unlock(rtp); 02323 02324 /* If it doesn't exist, check our static RTP type list, just in case */ 02325 if (!result.code) 02326 result = static_RTP_PT[pt]; 02327 02328 return result; 02329 }
| int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
| struct ast_channel * | src, | |||
| int | media | |||
| ) |
Definition at line 2155 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().
02156 { 02157 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 02158 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 02159 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 02160 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 02161 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; 02162 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; 02163 int srccodec, destcodec; 02164 02165 /* Lock channels */ 02166 ast_channel_lock(dest); 02167 while (ast_channel_trylock(src)) { 02168 ast_channel_unlock(dest); 02169 usleep(1); 02170 ast_channel_lock(dest); 02171 } 02172 02173 /* Find channel driver interfaces */ 02174 if (!(destpr = get_proto(dest))) { 02175 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name); 02176 ast_channel_unlock(dest); 02177 ast_channel_unlock(src); 02178 return 0; 02179 } 02180 if (!(srcpr = get_proto(src))) { 02181 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name); 02182 ast_channel_unlock(dest); 02183 ast_channel_unlock(src); 02184 return 0; 02185 } 02186 02187 /* Get audio and video interface (if native bridge is possible) */ 02188 audio_dest_res = destpr->get_rtp_info(dest, &destp); 02189 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 02190 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED; 02191 audio_src_res = srcpr->get_rtp_info(src, &srcp); 02192 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 02193 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED; 02194 02195 /* Ensure we have at least one matching codec */ 02196 if (srcpr->get_codec) 02197 srccodec = srcpr->get_codec(src); 02198 else 02199 srccodec = 0; 02200 if (destpr->get_codec) 02201 destcodec = destpr->get_codec(dest); 02202 else 02203 destcodec = 0; 02204 02205 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 02206 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)) { 02207 /* Somebody doesn't want to play... */ 02208 ast_channel_unlock(dest); 02209 ast_channel_unlock(src); 02210 return 0; 02211 } 02212 ast_rtp_pt_copy(destp, srcp); 02213 if (vdestp && vsrcp) 02214 ast_rtp_pt_copy(vdestp, vsrcp); 02215 if (tdestp && tsrcp) 02216 ast_rtp_pt_copy(tdestp, tsrcp); 02217 if (media) { 02218 /* Bridge early */ 02219 if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02220 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 02221 } 02222 ast_channel_unlock(dest); 02223 ast_channel_unlock(src); 02224 ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 02225 return 1; 02226 }
| 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 2587 of file rtp.c.
References ast_rtp_new_with_bindaddr().
02588 { 02589 struct in_addr ia; 02590 02591 memset(&ia, 0, sizeof(ia)); 02592 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02593 }
| void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
reload rtp configuration
Definition at line 2478 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().
02479 { 02480 #ifdef P2P_INTENSE 02481 ast_mutex_init(&rtp->bridge_lock); 02482 #endif 02483 02484 rtp->them.sin_family = AF_INET; 02485 rtp->us.sin_family = AF_INET; 02486 rtp->ssrc = ast_random(); 02487 rtp->seqno = ast_random() & 0xffff; 02488 ast_set_flag(rtp, FLAG_HAS_DTMF); 02489 rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN); 02490 }
| void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2605 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().
02606 { 02607 if (rtp) { 02608 rtp->set_marker_bit = 1; 02609 if (!rtp->constantssrc) { 02610 rtp->ssrc = ast_random(); 02611 } 02612 } 02613 }
| 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 2492 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().
02493 { 02494 struct ast_rtp *rtp; 02495 int x; 02496 int startplace; 02497 02498 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 02499 return NULL; 02500 02501 ast_rtp_new_init(rtp); 02502 02503 rtp->s = rtp_socket("RTP"); 02504 if (rtp->s < 0) 02505 goto fail; 02506 if (sched && rtcpenable) { 02507 rtp->sched = sched; 02508 rtp->rtcp = ast_rtcp_new(); 02509 } 02510 02511 /* 02512 * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well. 02513 * Start from a random (even, by RTP spec) port number, and 02514 * iterate until success or no ports are available. 02515 * Note that the requirement of RTP port being even, or RTCP being the 02516 * next one, cannot be enforced in presence of a NAT box because the 02517 * mapping is not under our control. 02518 */ 02519 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 02520 x = x & ~1; /* make it an even number */ 02521 startplace = x; /* remember the starting point */ 02522 /* this is constant across the loop */ 02523 rtp->us.sin_addr = addr; 02524 if (rtp->rtcp) 02525 rtp->rtcp->us.sin_addr = addr; 02526 for (;;) { 02527 rtp->us.sin_port = htons(x); 02528 if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) { 02529 /* bind succeeded, if no rtcp then we are done */ 02530 if (!rtp->rtcp) 02531 break; 02532 /* have rtcp, try to bind it */ 02533 rtp->rtcp->us.sin_port = htons(x + 1); 02534 if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) 02535 break; /* success again, we are really done */ 02536 /* 02537 * RTCP bind failed, so close and recreate the 02538 * already bound RTP socket for the next round. 02539 */ 02540 close(rtp->s); 02541 rtp->s = rtp_socket("RTP"); 02542 if (rtp->s < 0) 02543 goto fail; 02544 } 02545 /* 02546 * If we get here, there was an error in one of the bind() 02547 * calls, so make sure it is nothing unexpected. 02548 */ 02549 if (errno != EADDRINUSE) { 02550 /* We got an error that wasn't expected, abort! */ 02551 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 02552 goto fail; 02553 } 02554 /* 02555 * One of the ports is in use. For the next iteration, 02556 * increment by two and handle wraparound. 02557 * If we reach the starting point, then declare failure. 02558 */ 02559 x += 2; 02560 if (x > rtpend) 02561 x = (rtpstart + 1) & ~1; 02562 if (x == startplace) { 02563 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 02564 goto fail; 02565 } 02566 } 02567 rtp->sched = sched; 02568 rtp->io = io; 02569 if (callbackmode) { 02570 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 02571 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 02572 } 02573 ast_rtp_pt_default(rtp); 02574 return rtp; 02575 02576 fail: 02577 if (rtp->s >= 0) 02578 close(rtp->s); 02579 if (rtp->rtcp) { 02580 close(rtp->rtcp->s); 02581 ast_free(rtp->rtcp); 02582 } 02583 ast_free(rtp); 02584 return NULL; 02585 }
| int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Register an RTP channel client.
Definition at line 3844 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().
03845 { 03846 struct ast_rtp_protocol *cur; 03847 03848 AST_RWLIST_WRLOCK(&protos); 03849 AST_RWLIST_TRAVERSE(&protos, cur, list) { 03850 if (!strcmp(cur->type, proto->type)) { 03851 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 03852 AST_RWLIST_UNLOCK(&protos); 03853 return -1; 03854 } 03855 } 03856 AST_RWLIST_INSERT_HEAD(&protos, proto, list); 03857 AST_RWLIST_UNLOCK(&protos); 03858 03859 return 0; 03860 }
| void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Unregister an RTP channel client.
Definition at line 3836 of file rtp.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by load_module(), and unload_module().
03837 { 03838 AST_RWLIST_WRLOCK(&protos); 03839 AST_RWLIST_REMOVE(&protos, proto, list); 03840 AST_RWLIST_UNLOCK(&protos); 03841 }
| void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1993 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().
01994 { 01995 int i; 01996 01997 if (!rtp) 01998 return; 01999 02000 rtp_bridge_lock(rtp); 02001 02002 for (i = 0; i < MAX_RTP_PT; ++i) { 02003 rtp->current_RTP_PT[i].isAstFormat = 0; 02004 rtp->current_RTP_PT[i].code = 0; 02005 } 02006 02007 rtp->rtp_lookup_code_cache_isAstFormat = 0; 02008 rtp->rtp_lookup_code_cache_code = 0; 02009 rtp->rtp_lookup_code_cache_result = 0; 02010 02011 rtp_bridge_unlock(rtp); 02012 }
Copy payload types between RTP structures.
Definition at line 2033 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().
02034 { 02035 unsigned int i; 02036 02037 rtp_bridge_lock(dest); 02038 rtp_bridge_lock(src); 02039 02040 for (i = 0; i < MAX_RTP_PT; ++i) { 02041 dest->current_RTP_PT[i].isAstFormat = 02042 src->current_RTP_PT[i].isAstFormat; 02043 dest->current_RTP_PT[i].code = 02044 src->current_RTP_PT[i].code; 02045 } 02046 dest->rtp_lookup_code_cache_isAstFormat = 0; 02047 dest->rtp_lookup_code_cache_code = 0; 02048 dest->rtp_lookup_code_cache_result = 0; 02049 02050 rtp_bridge_unlock(src); 02051 rtp_bridge_unlock(dest); 02052 }
| void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 2014 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().
02015 { 02016 int i; 02017 02018 rtp_bridge_lock(rtp); 02019 02020 /* Initialize to default payload types */ 02021 for (i = 0; i < MAX_RTP_PT; ++i) { 02022 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 02023 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 02024 } 02025 02026 rtp->rtp_lookup_code_cache_isAstFormat = 0; 02027 rtp->rtp_lookup_code_cache_code = 0; 02028 rtp->rtp_lookup_code_cache_result = 0; 02029 02030 rtp_bridge_unlock(rtp); 02031 }
Write RTP packet with audio or video media frames into UDP packet.
Definition at line 3568 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().
03569 { 03570 unsigned char *rtpheader; 03571 int hdrlen = 12; 03572 int res; 03573 unsigned int ms; 03574 int pred; 03575 int mark = 0; 03576 int rate = rtp_get_rate(f->subclass) / 1000; 03577 03578 if (f->subclass == AST_FORMAT_G722) { 03579 f->samples /= 2; 03580 } 03581 03582 if (rtp->sending_digit) { 03583 return 0; 03584 } 03585 03586 ms = calc_txstamp(rtp, &f->delivery); 03587 /* Default prediction */ 03588 if (f->frametype == AST_FRAME_VOICE) { 03589 pred = rtp->lastts + f->samples; 03590 03591 /* Re-calculate last TS */ 03592 rtp->lastts = rtp->lastts + ms * rate; 03593 if (ast_tvzero(f->delivery)) { 03594 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 03595 and if so, go with our prediction */ 03596 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 03597 rtp->lastts = pred; 03598 else { 03599 ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 03600 mark = 1; 03601 } 03602 } 03603 } else if (f->frametype == AST_FRAME_VIDEO) { 03604 mark = f->subclass & 0x1; 03605 pred = rtp->lastovidtimestamp + f->samples; 03606 /* Re-calculate last TS */ 03607 rtp->lastts = rtp->lastts + ms * 90; 03608 /* If it's close to our prediction, go for it */ 03609 if (ast_tvzero(f->delivery)) { 03610 if (abs(rtp->lastts - pred) < 7200) { 03611 rtp->lastts = pred; 03612 rtp->lastovidtimestamp += f->samples; 03613 } else { 03614 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); 03615 rtp->lastovidtimestamp = rtp->lastts; 03616 } 03617 } 03618 } else { 03619 pred = rtp->lastotexttimestamp + f->samples; 03620 /* Re-calculate last TS */ 03621 rtp->lastts = rtp->lastts + ms; 03622 /* If it's close to our prediction, go for it */ 03623 if (ast_tvzero(f->delivery)) { 03624 if (abs(rtp->lastts - pred) < 7200) { 03625 rtp->lastts = pred; 03626 rtp->lastotexttimestamp += f->samples; 03627 } else { 03628 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); 03629 rtp->lastotexttimestamp = rtp->lastts; 03630 } 03631 } 03632 } 03633 03634 /* If we have been explicitly told to set the marker bit do so */ 03635 if (rtp->set_marker_bit) { 03636 mark = 1; 03637 rtp->set_marker_bit = 0; 03638 } 03639 03640 /* If the timestamp for non-digit packets has moved beyond the timestamp 03641 for digits, update the digit timestamp. 03642 */ 03643 if (rtp->lastts > rtp->lastdigitts) 03644 rtp->lastdigitts = rtp->lastts; 03645 03646 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 03647 rtp->lastts = f->ts * rate; 03648 03649 /* Get a pointer to the header */ 03650 rtpheader = (unsigned char *)(f->data.ptr - hdrlen); 03651 03652 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 03653 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 03654 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 03655 03656 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 03657 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 03658 if (res < 0) { 03659 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 03660 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)); 03661 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 03662 /* Only give this error message once if we are not RTP debugging */ 03663 if (option_debug || rtpdebug) 03664 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)); 03665 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 03666 } 03667 } else { 03668 rtp->txcount++; 03669 rtp->txoctetcount +=(res - hdrlen); 03670 03671 /* Do not schedule RR if RTCP isn't run */ 03672 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 03673 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 03674 } 03675 } 03676 03677 if (rtp_debug_test_addr(&rtp->them)) 03678 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03679 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 03680 } 03681 03682 rtp->seqno++; 03683 03684 return 0; 03685 }
Definition at line 1568 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().
01569 { 01570 int res; 01571 struct sockaddr_in sock_in; 01572 socklen_t len; 01573 unsigned int seqno; 01574 int version; 01575 int payloadtype; 01576 int hdrlen = 12; 01577 int padding; 01578 int mark; 01579 int ext; 01580 int cc; 01581 unsigned int ssrc; 01582 unsigned int timestamp; 01583 unsigned int *rtpheader; 01584 struct rtpPayloadType rtpPT; 01585 struct ast_rtp *bridged = NULL; 01586 int prev_seqno; 01587 01588 /* If time is up, kill it */ 01589 if (rtp->sending_digit) 01590 ast_rtp_senddigit_continuation(rtp); 01591 01592 len = sizeof(sock_in); 01593 01594 /* Cache where the header will go */ 01595 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01596 0, (struct sockaddr *)&sock_in, &len); 01597 01598 /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */ 01599 if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { 01600 /* Copy over address that this packet was received on */ 01601 memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address)); 01602 /* Now move over to actually protecting the RTP port */ 01603 rtp->strict_rtp_state = STRICT_RTP_CLOSED; 01604 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)); 01605 } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { 01606 /* If the address we previously learned doesn't match the address this packet came in on simply drop it */ 01607 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)) { 01608 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)); 01609 return &ast_null_frame; 01610 } 01611 } 01612 01613 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01614 if (res < 0) { 01615 ast_assert(errno != EBADF); 01616 if (errno != EAGAIN) { 01617 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01618 return NULL; 01619 } 01620 return &ast_null_frame; 01621 } 01622 01623 if (res < hdrlen) { 01624 ast_log(LOG_WARNING, "RTP Read too short\n"); 01625 return &ast_null_frame; 01626 } 01627 01628 /* Get fields */ 01629 seqno = ntohl(rtpheader[0]); 01630 01631 /* Check RTP version */ 01632 version = (seqno & 0xC0000000) >> 30; 01633 if (!version) { 01634 /* If the two high bits are 0, this might be a 01635 * STUN message, so process it. stun_handle_packet() 01636 * answers to requests, and it returns STUN_ACCEPT 01637 * if the request is valid. 01638 */ 01639 if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) && 01640 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01641 memcpy(&rtp->them, &sock_in, sizeof(rtp->them)); 01642 } 01643 return &ast_null_frame; 01644 } 01645 01646 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01647 /* If we don't have the other side's address, then ignore this */ 01648 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01649 return &ast_null_frame; 01650 #endif 01651 01652 /* Send to whoever send to us if NAT is turned on */ 01653 if (rtp->nat) { 01654 if (((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01655 (rtp->them.sin_port != sock_in.sin_port)) && 01656 ((rtp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01657 (rtp->altthem.sin_port != sock_in.sin_port))) { 01658 rtp->them = sock_in; 01659 if (rtp->rtcp) { 01660 int h = 0; 01661 memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them)); 01662 h = ntohs(rtp->them.sin_port); 01663 rtp->rtcp->them.sin_port = htons(h + 1); 01664 } 01665 rtp->rxseqno = 0; 01666 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01667 if (option_debug || rtpdebug) 01668 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)); 01669 } 01670 } 01671 01672 /* If we are bridged to another RTP stream, send direct */ 01673 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01674 return &ast_null_frame; 01675 01676 if (version != 2) 01677 return &ast_null_frame; 01678 01679 payloadtype = (seqno & 0x7f0000) >> 16; 01680 padding = seqno & (1 << 29); 01681 mark = seqno & (1 << 23); 01682 ext = seqno & (1 << 28); 01683 cc = (seqno & 0xF000000) >> 24; 01684 seqno &= 0xffff; 01685 timestamp = ntohl(rtpheader[1]); 01686 ssrc = ntohl(rtpheader[2]); 01687 01688 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01689 if (option_debug || rtpdebug) 01690 ast_debug(0, "Forcing Marker bit, because SSRC has changed\n"); 01691 mark = 1; 01692 } 01693 01694 rtp->rxssrc = ssrc; 01695 01696 if (padding) { 01697 /* Remove padding bytes */ 01698 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01699 } 01700 01701 if (cc) { 01702 /* CSRC fields present */ 01703 hdrlen += cc*4; 01704 } 01705 01706 if (ext) { 01707 /* RTP Extension present */ 01708 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01709 hdrlen += 4; 01710 if (option_debug) { 01711 int profile; 01712 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01713 if (profile == 0x505a) 01714 ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01715 else 01716 ast_debug(1, "Found unknown RTP Extensions %x\n", profile); 01717 } 01718 } 01719 01720 if (res < hdrlen) { 01721 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01722 return &ast_null_frame; 01723 } 01724 01725 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01726 01727 if (rtp->rxcount==1) { 01728 /* This is the first RTP packet successfully received from source */ 01729 rtp->seedrxseqno = seqno; 01730 } 01731 01732 /* Do not schedule RR if RTCP isn't run */ 01733 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01734 /* Schedule transmission of Receiver Report */ 01735 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01736 } 01737 if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01738 rtp->cycles += RTP_SEQ_MOD; 01739 01740 prev_seqno = rtp->lastrxseqno; 01741 01742 rtp->lastrxseqno = seqno; 01743 01744 if (!rtp->themssrc) 01745 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01746 01747 if (rtp_debug_test_addr(&sock_in)) 01748 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01749 ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01750 01751 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01752 if (!rtpPT.isAstFormat) { 01753 struct ast_frame *f = NULL; 01754 01755 /* This is special in-band data that's not one of our codecs */ 01756 if (rtpPT.code == AST_RTP_DTMF) { 01757 /* It's special -- rfc2833 process it */ 01758 if (rtp_debug_test_addr(&sock_in)) { 01759 unsigned char *data; 01760 unsigned int event; 01761 unsigned int event_end; 01762 unsigned int duration; 01763 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01764 event = ntohl(*((unsigned int *)(data))); 01765 event >>= 24; 01766 event_end = ntohl(*((unsigned int *)(data))); 01767 event_end <<= 8; 01768 event_end >>= 24; 01769 duration = ntohl(*((unsigned int *)(data))); 01770 duration &= 0xFFFF; 01771 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); 01772 } 01773 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01774 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01775 /* It's really special -- process it the Cisco way */ 01776 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01777 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01778 rtp->lastevent = seqno; 01779 } 01780 } else if (rtpPT.code == AST_RTP_CN) { 01781 /* Comfort Noise */ 01782 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01783 } else { 01784 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01785 } 01786 return f ? f : &ast_null_frame; 01787 } 01788 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01789 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; 01790 01791 rtp->rxseqno = seqno; 01792 01793 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) { 01794 rtp->dtmf_timeout = 0; 01795 01796 if (rtp->resp) { 01797 struct ast_frame *f; 01798 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01799 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01800 rtp->resp = 0; 01801 rtp->dtmf_timeout = rtp->dtmf_duration = 0; 01802 return f; 01803 } 01804 } 01805 01806 /* Record received timestamp as last received now */ 01807 rtp->lastrxts = timestamp; 01808 01809 rtp->f.mallocd = 0; 01810 rtp->f.datalen = res - hdrlen; 01811 rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01812 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01813 rtp->f.seqno = seqno; 01814 01815 if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) { 01816 unsigned char *data = rtp->f.data.ptr; 01817 01818 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen); 01819 rtp->f.datalen +=3; 01820 *data++ = 0xEF; 01821 *data++ = 0xBF; 01822 *data = 0xBD; 01823 } 01824 01825 if (rtp->f.subclass == AST_FORMAT_T140RED) { 01826 unsigned char *data = rtp->f.data.ptr; 01827 unsigned char *header_end; 01828 int num_generations; 01829 int header_length; 01830 int length; 01831 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/ 01832 int x; 01833 01834 rtp->f.subclass = AST_FORMAT_T140; 01835 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); 01836 if (header_end == NULL) { 01837 return &ast_null_frame; 01838 } 01839 header_end++; 01840 01841 header_length = header_end - data; 01842 num_generations = header_length / 4; 01843 length = header_length; 01844 01845 if (!diff) { 01846 for (x = 0; x < num_generations; x++) 01847 length += data[x * 4 + 3]; 01848 01849 if (!(rtp->f.datalen - length)) 01850 return &ast_null_frame; 01851 01852 rtp->f.data.ptr += length; 01853 rtp->f.datalen -= length; 01854 } else if (diff > num_generations && diff < 10) { 01855 length -= 3; 01856 rtp->f.data.ptr += length; 01857 rtp->f.datalen -= length; 01858 01859 data = rtp->f.data.ptr; 01860 *data++ = 0xEF; 01861 *data++ = 0xBF; 01862 *data = 0xBD; 01863 } else { 01864 for ( x = 0; x < num_generations - diff; x++) 01865 length += data[x * 4 + 3]; 01866 01867 rtp->f.data.ptr += length; 01868 rtp->f.datalen -= length; 01869 } 01870 } 01871 01872 if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) { 01873 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01874 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01875 ast_frame_byteswap_be(&rtp->f); 01876 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01877 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01878 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01879 rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000); 01880 rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 ); 01881 } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) { 01882 /* Video -- samples is # of samples vs. 90000 */ 01883 if (!rtp->lastividtimestamp) 01884 rtp->lastividtimestamp = timestamp; 01885 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01886 rtp->lastividtimestamp = timestamp; 01887 rtp->f.delivery.tv_sec = 0; 01888 rtp->f.delivery.tv_usec = 0; 01889 /* Pass the RTP marker bit as bit 0 in the subclass field. 01890 * This is ok because subclass is actually a bitmask, and 01891 * the low bits represent audio formats, that are not 01892 * involved here since we deal with video. 01893 */ 01894 if (mark) 01895 rtp->f.subclass |= 0x1; 01896 } else { 01897 /* TEXT -- samples is # of samples vs. 1000 */ 01898 if (!rtp->lastitexttimestamp) 01899 rtp->lastitexttimestamp = timestamp; 01900 rtp->f.samples = timestamp - rtp->lastitexttimestamp; 01901 rtp->lastitexttimestamp = timestamp; 01902 rtp->f.delivery.tv_sec = 0; 01903 rtp->f.delivery.tv_usec = 0; 01904 } 01905 rtp->f.src = "RTP"; 01906 return &rtp->f; 01907 }
| int ast_rtp_reload | ( | void | ) |
Initialize RTP subsystem
Definition at line 4883 of file rtp.c.
References __ast_rtp_reload().
04884 { 04885 return __ast_rtp_reload(1); 04886 }
| void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2690 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.
02691 { 02692 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02693 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02694 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02695 rtp->lastts = 0; 02696 rtp->lastdigitts = 0; 02697 rtp->lastrxts = 0; 02698 rtp->lastividtimestamp = 0; 02699 rtp->lastovidtimestamp = 0; 02700 rtp->lastitexttimestamp = 0; 02701 rtp->lastotexttimestamp = 0; 02702 rtp->lasteventseqn = 0; 02703 rtp->lastevent = 0; 02704 rtp->lasttxformat = 0; 02705 rtp->lastrxformat = 0; 02706 rtp->dtmf_timeout = 0; 02707 rtp->dtmfsamples = 0; 02708 rtp->seqno = 0; 02709 rtp->rxseqno = 0; 02710 }
| int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
| int | level | |||
| ) |
generate comfort noice (CNG)
Definition at line 3533 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().
03534 { 03535 unsigned int *rtpheader; 03536 int hdrlen = 12; 03537 int res; 03538 int payload; 03539 char data[256]; 03540 level = 127 - (level & 0x7f); 03541 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 03542 03543 /* If we have no peer, return immediately */ 03544 if (!rtp->them.sin_addr.s_addr) 03545 return 0; 03546 03547 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03548 03549 /* Get a pointer to the header */ 03550 rtpheader = (unsigned int *)data; 03551 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 03552 rtpheader[1] = htonl(rtp->lastts); 03553 rtpheader[2] = htonl(rtp->ssrc); 03554 data[12] = level; 03555 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 03556 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 03557 if (res <0) 03558 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)); 03559 if (rtp_debug_test_addr(&rtp->them)) 03560 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 03561 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 03562 03563 } 03564 return 0; 03565 }
| int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
| char | digit | |||
| ) |
Send begin frames for DTMF.
Definition at line 3100 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().
03101 { 03102 unsigned int *rtpheader; 03103 int hdrlen = 12, res = 0, i = 0, payload = 0; 03104 char data[256]; 03105 03106 if ((digit <= '9') && (digit >= '0')) 03107 digit -= '0'; 03108 else if (digit == '*') 03109 digit = 10; 03110 else if (digit == '#') 03111 digit = 11; 03112 else if ((digit >= 'A') && (digit <= 'D')) 03113 digit = digit - 'A' + 12; 03114 else if ((digit >= 'a') && (digit <= 'd')) 03115 digit = digit - 'a' + 12; 03116 else { 03117 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 03118 return 0; 03119 } 03120 03121 /* If we have no peer, return immediately */ 03122 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03123 return 0; 03124 03125 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 03126 03127 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03128 rtp->send_duration = 160; 03129 rtp->lastdigitts = rtp->lastts + rtp->send_duration; 03130 03131 /* Get a pointer to the header */ 03132 rtpheader = (unsigned int *)data; 03133 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 03134 rtpheader[1] = htonl(rtp->lastdigitts); 03135 rtpheader[2] = htonl(rtp->ssrc); 03136 03137 for (i = 0; i < 2; i++) { 03138 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 03139 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03140 if (res < 0) 03141 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 03142 ast_inet_ntoa(rtp->them.sin_addr), 03143 ntohs(rtp->them.sin_port), strerror(errno)); 03144 if (rtp_debug_test_addr(&rtp->them)) 03145 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03146 ast_inet_ntoa(rtp->them.sin_addr), 03147 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03148 /* Increment sequence number */ 03149 rtp->seqno++; 03150 /* Increment duration */ 03151 rtp->send_duration += 160; 03152 /* Clear marker bit and set seqno */ 03153 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 03154 } 03155 03156 /* Since we received a begin, we can safely store the digit and disable any compensation */ 03157 rtp->sending_digit = 1; 03158 rtp->send_digit = digit; 03159 rtp->send_payload = payload; 03160 03161 return 0; 03162 }
| static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 3165 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().
03166 { 03167 unsigned int *rtpheader; 03168 int hdrlen = 12, res = 0; 03169 char data[256]; 03170 03171 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03172 return 0; 03173 03174 /* Setup packet to send */ 03175 rtpheader = (unsigned int *)data; 03176 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 03177 rtpheader[1] = htonl(rtp->lastdigitts); 03178 rtpheader[2] = htonl(rtp->ssrc); 03179 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 03180 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 03181 03182 /* Transmit */ 03183 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03184 if (res < 0) 03185 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 03186 ast_inet_ntoa(rtp->them.sin_addr), 03187 ntohs(rtp->them.sin_port), strerror(errno)); 03188 if (rtp_debug_test_addr(&rtp->them)) 03189 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03190 ast_inet_ntoa(rtp->them.sin_addr), 03191 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03192 03193 /* Increment sequence number */ 03194 rtp->seqno++; 03195 /* Increment duration */ 03196 rtp->send_duration += 160; 03197 03198 return 0; 03199 }
| int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
| char | digit | |||
| ) |
Send end packets for DTMF.
Definition at line 3202 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().
03203 { 03204 unsigned int *rtpheader; 03205 int hdrlen = 12, res = 0, i = 0; 03206 char data[256]; 03207 03208 /* If no address, then bail out */ 03209 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 03210 return 0; 03211 03212 if ((digit <= '9') && (digit >= '0')) 03213 digit -= '0'; 03214 else if (digit == '*') 03215 digit = 10; 03216 else if (digit == '#') 03217 digit = 11; 03218 else if ((digit >= 'A') && (digit <= 'D')) 03219 digit = digit - 'A' + 12; 03220 else if ((digit >= 'a') && (digit <= 'd')) 03221 digit = digit - 'a' + 12; 03222 else { 03223 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 03224 return 0; 03225 } 03226 03227 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03228 03229 rtpheader = (unsigned int *)data; 03230 rtpheader[1] = htonl(rtp->lastdigitts); 03231 rtpheader[2] = htonl(rtp->ssrc); 03232 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 03233 /* Set end bit */ 03234 rtpheader[3] |= htonl((1 << 23)); 03235 03236 /* Send 3 termination packets */ 03237 for (i = 0; i < 3; i++) { 03238 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 03239 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 03240 rtp->seqno++; 03241 if (res < 0) 03242 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 03243 ast_inet_ntoa(rtp->them.sin_addr), 03244 ntohs(rtp->them.sin_port), strerror(errno)); 03245 if (rtp_debug_test_addr(&rtp->them)) 03246 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03247 ast_inet_ntoa(rtp->them.sin_addr), 03248 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 03249 } 03250 rtp->lastts += rtp->send_duration; 03251 rtp->sending_digit = 0; 03252 rtp->send_digit = 0; 03253 03254 return res; 03255 }
| 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 2630 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 2600 of file rtp.c.
References ast_rtp::constantssrc.
Referenced by create_addr_from_peer(), and handle_request_invite().
02601 { 02602 rtp->constantssrc = 1; 02603 }
| 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 2232 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().
02233 { 02234 if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 02235 return; /* bogus payload type */ 02236 02237 rtp_bridge_lock(rtp); 02238 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 02239 rtp_bridge_unlock(rtp); 02240 }
| void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 2615 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().
02616 { 02617 rtp->them.sin_port = them->sin_port; 02618 rtp->them.sin_addr = them->sin_addr; 02619 if (rtp->rtcp) { 02620 int h = ntohs(them->sin_port); 02621 rtp->rtcp->them.sin_port = htons(h + 1); 02622 rtp->rtcp->them.sin_addr = them->sin_addr; 02623 } 02624 rtp->rxseqno = 0; 02625 /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */ 02626 if (strictrtp) 02627 rtp->strict_rtp_state = STRICT_RTP_LEARN; 02628 }
| 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 2259 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().
02262 { 02263 unsigned int i; 02264 int found = 0; 02265 02266 if (pt < 0 || pt >= MAX_RTP_PT) 02267 return -1; /* bogus payload type */ 02268 02269 rtp_bridge_lock(rtp); 02270 02271 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02272 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 02273 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 02274 found = 1; 02275 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 02276 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 02277 mimeTypes[i].payloadType.isAstFormat && 02278 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02279 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 02280 break; 02281 } 02282 } 02283 02284 rtp_bridge_unlock(rtp); 02285 02286 return (found ? 0 : -1); 02287 }
| 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 2794 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().
02794 { 02795 char *audioqos; 02796 char *audioqos_jitter; 02797 char *audioqos_loss; 02798 char *audioqos_rtt; 02799 struct ast_channel *bridge; 02800 02801 if (!rtp || !chan) 02802 return; 02803 02804 bridge = ast_bridged_channel(chan); 02805 02806 audioqos = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY); 02807 audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER); 02808 audioqos_loss = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS); 02809 audioqos_rtt = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT); 02810 02811 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos); 02812 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter); 02813 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss); 02814 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt); 02815 02816 if (!bridge) 02817 return; 02818 02819 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos); 02820 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter); 02821 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss); 02822 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt); 02823 }
| 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 2595 of file rtp.c.
References ast_netsock_set_qos(), and ast_rtp::s.
Referenced by __oh323_rtp_create(), sip_alloc(), and start_rtp().
02596 { 02597 return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc); 02598 }
| 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 2669 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().
02670 { 02671 if (rtp->rtcp) { 02672 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02673 } 02674 if (rtp->red) { 02675 AST_SCHED_DEL(rtp->sched, rtp->red->schedid); 02676 free(rtp->red); 02677 rtp->red = NULL; 02678 } 02679 02680 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02681 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02682 if (rtp->rtcp) { 02683 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02684 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02685 } 02686 02687 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02688 }
| 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 2244 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().
02245 { 02246 if (pt < 0 || pt >= MAX_RTP_PT) 02247 return; /* bogus payload type */ 02248 02249 rtp_bridge_lock(rtp); 02250 rtp->current_RTP_PT[pt].isAstFormat = 0; 02251 rtp->current_RTP_PT[pt].code = 0; 02252 rtp_bridge_unlock(rtp); 02253 }
Definition at line 3749 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().
03750 { 03751 struct ast_frame *f; 03752 int codec; 03753 int hdrlen = 12; 03754 int subclass; 03755 03756 03757 /* If we have no peer, return immediately */ 03758 if (!rtp->them.sin_addr.s_addr) 03759 return 0; 03760 03761 /* If there is no data length, return immediately */ 03762 if (!_f->datalen && !rtp->red) 03763 return 0; 03764 03765 /* Make sure we have enough space for RTP header */ 03766 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) { 03767 ast_log(LOG_WARNING, "RTP can only send voice, video and text\n"); 03768 return -1; 03769 } 03770 03771 if (rtp->red) { 03772 /* return 0; */ 03773 /* no primary data or generations to send */ 03774 if ((_f = red_t140_to_red(rtp->red)) == NULL) 03775 return 0; 03776 } 03777 03778 /* The bottom bit of a video subclass contains the marker bit */ 03779 subclass = _f->subclass; 03780 if (_f->frametype == AST_FRAME_VIDEO) 03781 subclass &= ~0x1; 03782 03783 codec = ast_rtp_lookup_code(rtp, 1, subclass); 03784 if (codec < 0) { 03785 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 03786 return -1; 03787 } 03788 03789 if (rtp->lasttxformat != subclass) { 03790 /* New format, reset the smoother */ 03791 ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 03792 rtp->lasttxformat = subclass; 03793 if (rtp->smoother) 03794 ast_smoother_free(rtp->smoother); 03795 rtp->smoother = NULL; 03796 } 03797 03798 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 03799 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 03800 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 03801 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 03802 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)); 03803 return -1; 03804 } 03805 if (fmt.flags) 03806 ast_smoother_set_flags(rtp->smoother, fmt.flags); 03807 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)); 03808 } 03809 } 03810 if (rtp->smoother) { 03811 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 03812 ast_smoother_feed_be(rtp->smoother, _f); 03813 } else { 03814 ast_smoother_feed(rtp->smoother, _f); 03815 } 03816 03817 while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) { 03818 ast_rtp_raw_write(rtp, f, codec); 03819 } 03820 } else { 03821 /* Don't buffer outgoing frames; send them one-per-packet: */ 03822 if (_f->offset < hdrlen) 03823 f = ast_frdup(_f); /*! \bug XXX this might never be free'd. Why do we do this? */ 03824 else 03825 f = _f; 03826 if (f->data.ptr) 03827 ast_rtp_raw_write(rtp, f, codec); 03828 if (f != _f) 03829 ast_frfree(f); 03830 } 03831 03832 return 0; 03833 }
| 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 3863 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().
03864 { 03865 struct ast_frame *fr = NULL; 03866 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03867 int oldcodec0 = codec0, oldcodec1 = codec1; 03868 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,}; 03869 struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,}; 03870 03871 /* Set it up so audio goes directly between the two endpoints */ 03872 03873 /* Test the first channel */ 03874 if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 03875 ast_rtp_get_peer(p1, &ac1); 03876 if (vp1) 03877 ast_rtp_get_peer(vp1, &vac1); 03878 if (tp1) 03879 ast_rtp_get_peer(tp1, &tac1); 03880 } else 03881 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 03882 03883 /* Test the second channel */ 03884 if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 03885 ast_rtp_get_peer(p0, &ac0); 03886 if (vp0) 03887 ast_rtp_get_peer(vp0, &vac0); 03888 if (tp0) 03889 ast_rtp_get_peer(tp0, &tac0); 03890 } else 03891 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 03892 03893 /* Now we can unlock and move into our loop */ 03894 ast_channel_unlock(c0); 03895 ast_channel_unlock(c1); 03896 03897 ast_poll_channel_add(c0, c1); 03898 03899 /* Throw our channels into the structure and enter the loop */ 03900 cs[0] = c0; 03901 cs[1] = c1; 03902 cs[2] = NULL; 03903 for (;;) { 03904 /* Check if anything changed */ 03905 if ((c0->tech_pvt != pvt0) || 03906 (c1->tech_pvt != pvt1) || 03907 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03908 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03909 ast_debug(1, "Oooh, something is weird, backing out\n"); 03910 if (c0->tech_pvt == pvt0) 03911 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03912 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03913 if (c1->tech_pvt == pvt1) 03914 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03915 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03916 ast_poll_channel_del(c0, c1); 03917 return AST_BRIDGE_RETRY; 03918 } 03919 03920 /* Check if they have changed their address */ 03921 ast_rtp_get_peer(p1, &t1); 03922 if (vp1) 03923 ast_rtp_get_peer(vp1, &vt1); 03924 if (tp1) 03925 ast_rtp_get_peer(tp1, &tt1); 03926 if (pr1->get_codec) 03927 codec1 = pr1->get_codec(c1); 03928 ast_rtp_get_peer(p0, &t0); 03929 if (vp0) 03930 ast_rtp_get_peer(vp0, &vt0); 03931 if (tp0) 03932 ast_rtp_get_peer(tp0, &tt0); 03933 if (pr0->get_codec) 03934 codec0 = pr0->get_codec(c0); 03935 if ((inaddrcmp(&t1, &ac1)) || 03936 (vp1 && inaddrcmp(&vt1, &vac1)) || 03937 (tp1 && inaddrcmp(&tt1, &tac1)) || 03938 (codec1 != oldcodec1)) { 03939 ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03940 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 03941 ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 03942 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 03943 ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n", 03944 c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1); 03945 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03946 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 03947 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03948 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 03949 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03950 c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1); 03951 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))) 03952 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 03953 memcpy(&ac1, &t1, sizeof(ac1)); 03954 memcpy(&vac1, &vt1, sizeof(vac1)); 03955 memcpy(&tac1, &tt1, sizeof(tac1)); 03956 oldcodec1 = codec1; 03957 } 03958 if ((inaddrcmp(&t0, &ac0)) || 03959 (vp0 && inaddrcmp(&vt0, &vac0)) || 03960 (tp0 && inaddrcmp(&tt0, &tac0)) || 03961 (codec0 != oldcodec0)) { 03962 ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03963 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 03964 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03965 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 03966 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))) 03967 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 03968 memcpy(&ac0, &t0, sizeof(ac0)); 03969 memcpy(&vac0, &vt0, sizeof(vac0)); 03970 memcpy(&tac0, &tt0, sizeof(tac0)); 03971 oldcodec0 = codec0; 03972 } 03973 03974 /* Wait for frame to come in on the channels */ 03975 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03976 if (!timeoutms) { 03977 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03978 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03979 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03980 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03981 return AST_BRIDGE_RETRY; 03982 } 03983 ast_debug(1, "Ooh, empty read...\n"); 03984 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03985 break; 03986 continue; 03987 } 03988 fr = ast_read(who); 03989 other = (who == c0) ? c1 : c0; 03990 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03991 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 03992 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 03993 /* Break out of bridge */ 03994 *fo = fr; 03995 *rc = who; 03996 ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03997 if (c0->tech_pvt == pvt0) 03998 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03999 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 04000 if (c1->tech_pvt == pvt1) 04001 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 04002 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 04003 ast_poll_channel_del(c0, c1); 04004 return AST_BRIDGE_COMPLETE; 04005 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 04006 if ((fr->subclass == AST_CONTROL_HOLD) || 04007 (fr->subclass == AST_CONTROL_UNHOLD) || 04008 (fr->subclass == AST_CONTROL_VIDUPDATE) || 04009 (fr->subclass == AST_CONTROL_SRCUPDATE) || 04010 (fr->subclass == AST_CONTROL_T38_PARAMETERS)) { 04011 if (fr->subclass == AST_CONTROL_HOLD) { 04012 /* If we someone went on hold we want the other side to reinvite back to us */ 04013 if (who == c0) 04014 pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0); 04015 else 04016 pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0); 04017 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 04018 /* If they went off hold they should go back to being direct */ 04019 if (who == c0) 04020 pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 04021 else 04022 pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 04023 } 04024 /* Update local address information */ 04025 ast_rtp_get_peer(p0, &t0); 04026 memcpy(&ac0, &t0, sizeof(ac0)); 04027 ast_rtp_get_peer(p1, &t1); 04028 memcpy(&ac1, &t1, sizeof(ac1)); 04029 /* Update codec information */ 04030 if (pr0->get_codec && c0->tech_pvt) 04031 oldcodec0 = codec0 = pr0->get_codec(c0); 04032 if (pr1->get_codec && c1->tech_pvt) 04033 oldcodec1 = codec1 = pr1->get_codec(c1); 04034 ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen); 04035 ast_frfree(fr); 04036 } else { 04037 *fo = fr; 04038 *rc = who; 04039 ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 04040 return AST_BRIDGE_COMPLETE; 04041 } 04042 } else { 04043 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 04044 (fr->frametype == AST_FRAME_DTMF_END) || 04045 (fr->frametype == AST_FRAME_VOICE) || 04046 (fr->frametype == AST_FRAME_VIDEO) || 04047 (fr->frametype == AST_FRAME_IMAGE) || 04048 (fr->frametype == AST_FRAME_HTML) || 04049 (fr->frametype == AST_FRAME_MODEM) || 04050 (fr->frametype == AST_FRAME_TEXT)) { 04051 ast_write(other, fr); 04052 } 04053 ast_frfree(fr); 04054 } 04055 /* Swap priority */ 04056 #ifndef HAVE_EPOLL 04057 cs[2] = cs[0]; 04058 cs[0] = cs[1]; 04059 cs[1] = cs[2]; 04060 #endif 04061 } 04062 04063 ast_poll_channel_del(c0, c1); 04064 04065 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 04066 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 04067 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 04068 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 04069 04070 return AST_BRIDGE_FAILED; 04071 }
| 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 4171 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().
04172 { 04173 struct ast_frame *fr = NULL; 04174 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 04175 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 04176 int p0_callback = 0, p1_callback = 0; 04177 enum ast_bridge_result res = AST_BRIDGE_FAILED; 04178 04179 /* Okay, setup each RTP structure to do P2P forwarding */ 04180 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 04181 p2p_set_bridge(p0, p1); 04182 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 04183 p2p_set_bridge(p1, p0); 04184 04185 /* Activate callback modes if possible */ 04186 p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]); 04187 p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]); 04188 04189 /* Now let go of the channel locks and be on our way */ 04190 ast_channel_unlock(c0); 04191 ast_channel_unlock(c1); 04192 04193 ast_poll_channel_add(c0, c1); 04194 04195 /* Go into a loop forwarding frames until we don't need to anymore */ 04196 cs[0] = c0; 04197 cs[1] = c1; 04198 cs[2] = NULL; 04199 for (;;) { 04200 /* If the underlying formats have changed force this bridge to break */ 04201 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 04202 ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n"); 04203 res = AST_BRIDGE_FAILED_NOWARN; 04204 break; 04205 } 04206 /* Check if anything changed */ 04207 if ((c0->tech_pvt != pvt0) || 04208 (c1->tech_pvt != pvt1) || 04209 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 04210 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 04211 ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n"); 04212 /* 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 */ 04213 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 04214 ast_frfree(fr); 04215 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 04216 ast_frfree(fr); 04217 res = AST_BRIDGE_RETRY; 04218 break; 04219 } 04220 /* Wait on a channel to feed us a frame */ 04221 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 04222 if (!timeoutms) { 04223 res = AST_BRIDGE_RETRY; 04224 break; 04225 } 04226 if (option_debug > 2) 04227 ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n"); 04228 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 04229 break; 04230 continue; 04231 } 04232 /* Read in frame from channel */ 04233 fr = ast_read(who); 04234 other = (who == c0) ? c1 : c0; 04235 /* Depending on the frame we may need to break out of our bridge */ 04236 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 04237 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 04238 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 04239 /* Record received frame and who */ 04240 *fo = fr; 04241 *rc = who; 04242 ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup"); 04243 res = AST_BRIDGE_COMPLETE; 04244 break; 04245 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 04246 if ((fr->subclass == AST_CONTROL_HOLD) || 04247 (fr->subclass == AST_CONTROL_UNHOLD) || 04248 (fr->subclass == AST_CONTROL_VIDUPDATE) || 04249 (fr->subclass == AST_CONTROL_SRCUPDATE) || 04250 (fr->subclass == AST_CONTROL_T38_PARAMETERS)) { 04251 /* If we are going on hold, then break callback mode and P2P bridging */ 04252 if (fr->subclass == AST_CONTROL_HOLD) { 04253 if (p0_callback) 04254 p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]); 04255 if (p1_callback) 04256 p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]); 04257 p2p_set_bridge(p0, NULL); 04258 p2p_set_bridge(p1, NULL); 04259 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 04260 /* If we are off hold, then go back to callback mode and P2P bridging */ 04261 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 04262 p2p_set_bridge(p0, p1); 04263 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 04264 p2p_set_bridge(p1, p0); 04265 p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]); 04266 p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]); 04267 } 04268 ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen); 04269 ast_frfree(fr); 04270 } else { 04271 *fo = fr; 04272 *rc = who; 04273 ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 04274 res = AST_BRIDGE_COMPLETE; 04275 break; 04276 } 04277 } else { 04278 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 04279 (fr->frametype == AST_FRAME_DTMF_END) || 04280 (fr->frametype == AST_FRAME_VOICE) || 04281 (fr->frametype == AST_FRAME_VIDEO) || 04282 (fr->frametype == AST_FRAME_IMAGE) || 04283 (fr->frametype == AST_FRAME_HTML) || 04284 (fr->frametype == AST_FRAME_MODEM) || 04285 (fr->frametype == AST_FRAME_TEXT)) { 04286 ast_write(other, fr); 04287 } 04288 04289 ast_frfree(fr); 04290 } 04291 /* Swap priority */ 04292 #ifndef HAVE_EPOLL 04293 cs[2] = cs[0]; 04294 cs[0] = cs[1]; 04295 cs[1] = cs[2]; 04296 #endif 04297 } 04298 04299 /* If we are totally avoiding the core, then restore our link to it */ 04300 if (p0_callback) 04301 p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]); 04302 if (p1_callback) 04303 p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]); 04304 04305 /* Break out of the direct bridge */ 04306 p2p_set_bridge(p0, NULL); 04307 p2p_set_bridge(p1, NULL); 04308 04309 ast_poll_channel_del(c0, c1); 04310 04311 return res; 04312 }
| 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 1514 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().
01515 { 01516 int res = 0, payload = 0, bridged_payload = 0, mark; 01517 struct rtpPayloadType rtpPT; 01518 int reconstruct = ntohl(rtpheader[0]); 01519 01520 /* Get fields from packet */ 01521 payload = (reconstruct & 0x7f0000) >> 16; 01522 mark = (((reconstruct & 0x800000) >> 23) != 0); 01523 01524 /* Check what the payload value should be */ 01525 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01526 01527 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01528 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01529 return -1; 01530 01531 /* Otherwise adjust bridged payload to match */ 01532 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01533 01534 /* 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 */ 01535 if (!bridged->current_RTP_PT[bridged_payload].code) 01536 return -1; 01537 01538 01539 /* If the mark bit has not been sent yet... do it now */ 01540 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01541 mark = 1; 01542 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01543 } 01544 01545 /* Reconstruct part of the packet */ 01546 reconstruct &= 0xFF80FFFF; 01547 reconstruct |= (bridged_payload << 16); 01548 reconstruct |= (mark << 23); 01549 rtpheader[0] = htonl(reconstruct); 01550 01551 /* Send the packet back out */ 01552 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01553 if (res < 0) { 01554 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01555 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)); 01556 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01557 if (option_debug || rtpdebug) 01558 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)); 01559 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01560 } 01561 return 0; 01562 } else if (rtp_debug_test_addr(&bridged->them)) 01563 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); 01564 01565 return 0; 01566 }
| static void calc_rxstamp | ( | struct timeval * | when, | |
| struct ast_rtp * | rtp, | |||
| unsigned int | timestamp, | |||
| int | mark | |||
| ) | [static] |
Definition at line 1459 of file rtp.c.
References ast_samp2tv(), ast_tvadd(), ast_tvsub(), ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, normdev_compute(), ast_rtcp::normdev_rxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxtransit, ast_rtp::seedrxts, stddev_compute(), ast_rtcp::stdev_rxjitter, and ast_frame::subclass.
Referenced by ast_rtp_read().
01460 { 01461 struct timeval now; 01462 struct timeval tmp; 01463 double transit; 01464 double current_time; 01465 double d; 01466 double dtv; 01467 double prog; 01468 double normdev_rxjitter_current; 01469 int rate = rtp_get_rate(rtp->f.subclass); 01470 01471 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01472 gettimeofday(&rtp->rxcore, NULL); 01473 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01474 /* map timestamp to a real time */ 01475 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01476 tmp = ast_samp2tv(timestamp, rate); 01477 rtp->rxcore = ast_tvsub(rtp->rxcore, tmp); 01478 /* Round to 0.1ms for nice, pretty timestamps */ 01479 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01480 } 01481 01482 gettimeofday(&now,NULL); 01483 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01484 tmp = ast_samp2tv(timestamp, rate); 01485 *when = ast_tvadd(rtp->rxcore, tmp); 01486 01487 prog = (double)((timestamp-rtp->seedrxts)/(float)(rate)); 01488 dtv = (double)rtp->drxcore + (double)(prog); 01489 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01490 transit = current_time - dtv; 01491 d = transit - rtp->rxtransit; 01492 rtp->rxtransit = transit; 01493 if (d<0) 01494 d=-d; 01495 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01496 01497 if (rtp->rtcp) { 01498 if (rtp->rxjitter > rtp->rtcp->maxrxjitter) 01499 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01500 if (rtp->rtcp->rxjitter_count == 1) 01501 rtp->rtcp->minrxjitter = rtp->rxjitter; 01502 if (rtp->rxjitter < rtp->rtcp->minrxjitter) 01503 rtp->rtcp->minrxjitter = rtp->rxjitter; 01504 01505 normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count); 01506 rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count); 01507 01508 rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current; 01509 rtp->rtcp->rxjitter_count++; 01510 } 01511 }
| static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
| struct timeval * | delivery | |||
| ) | [static] |
Definition at line 3080 of file rtp.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
03081 { 03082 struct timeval t; 03083 long ms; 03084 if (ast_tvzero(rtp->txcore)) { 03085 rtp->txcore = ast_tvnow(); 03086 /* Round to 20ms for nice, pretty timestamps */ 03087 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 03088 } 03089 /* Use previous txcore if available */ 03090 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 03091 ms = ast_tvdiff_ms(t, rtp->txcore); 03092 if (ms < 0) 03093 ms = 0; 03094 /* Use what we just got for next time */ 03095 rtp->txcore = t; 03096 return (unsigned int) ms; 03097 }
| static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static, read] |
Get channel driver interface structure.
Definition at line 2055 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().
02056 { 02057 struct ast_rtp_protocol *cur = NULL; 02058 02059 AST_RWLIST_RDLOCK(&protos); 02060 AST_RWLIST_TRAVERSE(&protos, cur, list) { 02061 if (cur->type == chan->tech->type) 02062 break; 02063 } 02064 AST_RWLIST_UNLOCK(&protos); 02065 02066 return cur; 02067 }
| static char* handle_cli_rtcp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4631 of file rtp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcp_do_debug_ip(), rtcpdebugaddr, and ast_cli_entry::usage.
04632 { 04633 switch (cmd) { 04634 case CLI_INIT: 04635 e->command = "rtcp debug [off|ip]"; 04636 e->usage = 04637 "Usage: rtcp debug [off]|[ip host[:port]]\n" 04638 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04639 " specified, limit the dumped packets to those to and from\n" 04640 " the specified 'host' with optional port.\n"; 04641 return NULL; 04642 case CLI_GENERATE: 04643 return NULL; 04644 } 04645 04646 if (a->argc < 2 || a->argc > 4) 04647 return CLI_SHOWUSAGE; 04648 if (a->argc == 2) { 04649 rtcpdebug = 1; 04650 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04651 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04652 } else if (a->argc == 3) { 04653 if (strncasecmp(a->argv[2], "off", 3)) 04654 return CLI_SHOWUSAGE; 04655 rtcpdebug = 0; 04656 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04657 } else { 04658 if (strncasecmp(a->argv[2], "ip", 2)) 04659 return CLI_SHOWUSAGE; 04660 return rtcp_do_debug_ip(a); 04661 } 04662 04663 return CLI_SUCCESS; 04664 }
| static char* handle_cli_rtcp_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4666 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.
04667 { 04668 switch (cmd) { 04669 case CLI_INIT: 04670 e->command = "rtcp set debug {on|off|ip}"; 04671 e->usage = 04672 "Usage: rtcp set debug {on|off|ip host[:port]}\n" 04673 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04674 " specified, limit the dumped packets to those to and from\n" 04675 " the specified 'host' with optional port.\n"; 04676 return NULL; 04677 case CLI_GENERATE: 04678 return NULL; 04679 } 04680 04681 if (a->argc == e->args) { /* set on or off */ 04682 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04683 rtcpdebug = 1; 04684 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04685 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04686 return CLI_SUCCESS; 04687 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04688 rtcpdebug = 0; 04689 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04690 return CLI_SUCCESS; 04691 } 04692 } else if (a->argc == e->args +1) { /* ip */ 04693 return rtcp_do_debug_ip(a); 04694 } 04695 04696 return CLI_SHOWUSAGE; /* default, failure */ 04697 }
| static char* handle_cli_rtcp_set_stats | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4722 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.
04723 { 04724 switch (cmd) { 04725 case CLI_INIT: 04726 e->command = "rtcp set stats {on|off}"; 04727 e->usage = 04728 "Usage: rtcp set stats {on|off}\n" 04729 " Enable/Disable dumping of RTCP stats.\n"; 04730 return NULL; 04731 case CLI_GENERATE: 04732 return NULL; 04733 } 04734 04735 if (a->argc != e->args) 04736 return CLI_SHOWUSAGE; 04737 04738 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04739 rtcpstats = 1; 04740 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04741 rtcpstats = 0; 04742 else 04743 return CLI_SHOWUSAGE; 04744 04745 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04746 return CLI_SUCCESS; 04747 }
| static char* handle_cli_rtcp_stats_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4699 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.
04700 { 04701 switch (cmd) { 04702 case CLI_INIT: 04703 e->command = "rtcp stats [off]"; 04704 e->usage = 04705 "Usage: rtcp stats [off]\n" 04706 " Enable/Disable dumping of RTCP stats.\n"; 04707 return NULL; 04708 case CLI_GENERATE: 04709 return NULL; 04710 } 04711 04712 if (a->argc < 2 || a->argc > 3) 04713 return CLI_SHOWUSAGE; 04714 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04715 return CLI_SHOWUSAGE; 04716 04717 rtcpstats = (a->argc == 3) ? 0 : 1; 04718 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04719 return CLI_SUCCESS; 04720 }
| static char* handle_cli_rtp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4563 of file rtp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtp_do_debug_ip(), rtpdebugaddr, and ast_cli_entry::usage.
04564 { 04565 switch (cmd) { 04566 case CLI_INIT: 04567 e->command = "rtp debug [off|ip]"; 04568 e->usage = 04569 "Usage: rtp debug [off]|[ip host[:port]]\n" 04570 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04571 " specified, limit the dumped packets to those to and from\n" 04572 " the specified 'host' with optional port.\n"; 04573 return NULL; 04574 case CLI_GENERATE: 04575 return NULL; 04576 } 04577 04578 if (a->argc < 2 || a->argc > 4) 04579 return CLI_SHOWUSAGE; 04580 if (a->argc == 2) { 04581 rtpdebug = 1; 04582 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04583 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04584 } else if (a->argc == 3) { 04585 if (strncasecmp(a->argv[2], "off", 3)) 04586 return CLI_SHOWUSAGE; 04587 rtpdebug = 0; 04588 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04589 } else { 04590 if (strncasecmp(a->argv[2], "ip", 2)) 04591 return CLI_SHOWUSAGE; 04592 return rtp_do_debug_ip(a, 1); 04593 } 04594 04595 return CLI_SUCCESS; 04596 }
| static char* handle_cli_rtp_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4598 of file rtp.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtp_do_debug_ip(), rtpdebugaddr, and ast_cli_entry::usage.
04599 { 04600 switch (cmd) { 04601 case CLI_INIT: 04602 e->command = "rtp set debug {on|off|ip}"; 04603 e->usage = 04604 "Usage: rtp set debug {on|off|ip host[:port]}\n" 04605 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04606 " specified, limit the dumped packets to those to and from\n" 04607 " the specified 'host' with optional port.\n"; 04608 return NULL; 04609 case CLI_GENERATE: 04610 return NULL; 04611 } 04612 04613 if (a->argc == e->args) { /* set on or off */ 04614 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04615 rtpdebug = 1; 04616 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04617 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04618 return CLI_SUCCESS; 04619 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04620 rtpdebug = 0; 04621 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04622 return CLI_SUCCESS; 04623 } 04624 } else if (a->argc == e->args +1) { /* ip */ 04625 return rtp_do_debug_ip(a, 0); 04626 } 04627 04628 return CLI_SHOWUSAGE; /* default, failure */ 04629 }
| static char* handle_cli_stun_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4749 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.
04750 { 04751 switch (cmd) { 04752 case CLI_INIT: 04753 e->command = "stun debug [off]"; 04754 e->usage = 04755 "Usage: stun debug [off]\n" 04756 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04757 " debugging\n"; 04758 return NULL; 04759 case CLI_GENERATE: 04760 return NULL; 04761 } 04762 04763 if (a->argc < 2 || a->argc > 3) 04764 return CLI_SHOWUSAGE; 04765 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04766 return CLI_SHOWUSAGE; 04767 04768 stundebug = (a->argc == 3) ? 0 : 1; 04769 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04770 return CLI_SUCCESS; 04771 }
| static char* handle_cli_stun_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4773 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.
04774 { 04775 switch (cmd) { 04776 case CLI_INIT: 04777 e->command = "stun set debug {on|off}"; 04778 e->usage = 04779 "Usage: stun set debug {on|off}\n" 04780 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04781 " debugging\n"; 04782 return NULL; 04783 case CLI_GENERATE: 04784 return NULL; 04785 } 04786 04787 if (a->argc != e->args) 04788 return CLI_SHOWUSAGE; 04789 04790 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04791 stundebug = 1; 04792 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04793 stundebug = 0; 04794 else 04795 return CLI_SHOWUSAGE; 04796 04797 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04798 return CLI_SUCCESS; 04799 }
| 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 4139 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().
04140 { 04141 ast_channel_lock(chan); 04142 04143 /* Remove the callback from the IO context */ 04144 ast_io_remove(rtp->io, iod[0]); 04145 04146 /* Restore file descriptors */ 04147 chan->fds[0] = ast_rtp_fd(rtp); 04148 ast_channel_unlock(chan); 04149 04150 /* Restore callback mode if previously used */ 04151 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 04152 rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp); 04153 04154 return 0; 04155 }
| 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 4158 of file rtp.c.
References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().
Referenced by bridge_p2p_loop().
04159 { 04160 rtp_bridge_lock(rtp0); 04161 rtp0->bridged = rtp1; 04162 rtp_bridge_unlock(rtp0); 04163 }
| 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 4993 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 4910 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().
04910 { 04911 unsigned char *data = red->t140red.data.ptr; 04912 int len = 0; 04913 int i; 04914 04915 /* replace most aged generation */ 04916 if (red->len[0]) { 04917 for (i = 1; i < red->num_gen+1; i++) 04918 len += red->len[i]; 04919 04920 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 04921 } 04922 04923 /* Store length of each generation and primary data length*/ 04924 for (i = 0; i < red->num_gen; i++) 04925 red->len[i] = red->len[i+1]; 04926 red->len[i] = red->t140.datalen; 04927 04928 /* write each generation length in red header */ 04929 len = red->hdrlen; 04930 for (i = 0; i < red->num_gen; i++) 04931 len += data[i*4+3] = red->len[i]; 04932 04933 /* add primary data to buffer */ 04934 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 04935 red->t140red.datalen = len + red->t140.datalen; 04936 04937 /* no primary data and no generations to send */ 04938 if (len == red->hdrlen && !red->t140.datalen) 04939 return NULL; 04940 04941 /* reset t.140 buffer */ 04942 red->t140.datalen = 0; 04943 04944 return &red->t140red; 04945 }
| static int red_write | ( | const void * | data | ) | [static] |
Write t140 redundacy frame.
| data | primary data to be buffered |
Definition at line 4898 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 4533 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().
04534 { 04535 struct hostent *hp; 04536 struct ast_hostent ahp; 04537 int port = 0; 04538 char *p, *arg; 04539 04540 arg = a->argv[3]; 04541 p = strstr(arg, ":"); 04542 if (p) { 04543 *p = '\0'; 04544 p++; 04545 port = atoi(p); 04546 } 04547 hp = ast_gethostbyname(arg, &ahp); 04548 if (hp == NULL) { 04549 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04550 return CLI_FAILURE; 04551 } 04552 rtcpdebugaddr.sin_family = AF_INET; 04553 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 04554 rtcpdebugaddr.sin_port = htons(port); 04555 if (port == 0) 04556 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 04557 else 04558 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 04559 rtcpdebug = 1; 04560 return CLI_SUCCESS; 04561 }
| 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 4499 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().
04500 { 04501 struct hostent *hp; 04502 struct ast_hostent ahp; 04503 int port = 0; 04504 char *p, *arg; 04505 04506 if (deprecated == 1) { 04507 arg = a->argv[3]; 04508 } else { 04509 arg = a->argv[4]; 04510 } 04511 p = strstr(arg, ":"); 04512 if (p) { 04513 *p = '\0'; 04514 p++; 04515 port = atoi(p); 04516 } 04517 hp = ast_gethostbyname(arg, &ahp); 04518 if (hp == NULL) { 04519 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04520 return CLI_FAILURE; 04521 } 04522 rtpdebugaddr.sin_family = AF_INET; 04523 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 04524 rtpdebugaddr.sin_port = htons(port); 04525 if (port == 0) 04526 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 04527 else 04528 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 04529 rtpdebug = 1; 04530 return CLI_SUCCESS; 04531 }
| 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 4954 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().
04955 { 04956 struct rtp_red *r; 04957 int x; 04958 04959 if (!(r = ast_calloc(1, sizeof(struct rtp_red)))) 04960 return -1; 04961 04962 r->t140.frametype = AST_FRAME_TEXT; 04963 r->t140.subclass = AST_FORMAT_T140RED; 04964 r->t140.data.ptr = &r->buf_data; 04965 04966 r->t140.ts = 0; 04967 r->t140red = r->t140; 04968 r->t140red.data.ptr = &r->t140red_data; 04969 r->t140red.datalen = 0; 04970 r->ti = ti; 04971 r->num_gen = num_gen; 04972 r->hdrlen = num_gen * 4 + 1; 04973 r->prev_ts = 0; 04974 04975 for (x = 0; x < num_gen; x++) { 04976 r->pt[x] = red_data_pt[x]; 04977 r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 04978 r->t140red_data[x*4] = r->pt[x]; 04979 } 04980 r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */ 04981 r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp); 04982 rtp->red = r; 04983 04984 r->t140.datalen = 0; 04985 04986 return 0; 04987 }
| static int rtp_socket | ( | const char * | type | ) | [static] |
Open RTP or RTCP socket for a session. Print a message on failure.
Definition at line 2432 of file rtp.c.
References ast_log(), errno, LOG_WARNING, and s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
02433 { 02434 int s = socket(AF_INET, SOCK_DGRAM, 0); 02435 if (s < 0) { 02436 if (type == NULL) 02437 type = "RTP/RTCP"; 02438 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno)); 02439 } else { 02440 long flags = fcntl(s, F_GETFL); 02441 fcntl(s, F_SETFL, flags | O_NONBLOCK); 02442 #ifdef SO_NO_CHECK 02443 if (nochecksums) 02444 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 02445 #endif 02446 } 02447 return s; 02448 }
| 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 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 1912 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 1914 of file rtp.c.
Referenced by ast_rtp_set_rtpmap_type().
| char* type |
Definition at line 1913 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