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_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) |
| 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 214 of file rtp.c.
Referenced by process_rfc3389().
| #define FLAG_CALLBACK_MODE (1 << 6) |
Definition at line 221 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().
| #define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 222 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 218 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 223 of file rtp.c.
Referenced by ast_rtp_setstun().
| #define FLAG_NAT_ACTIVE (3 << 1) |
Definition at line 215 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 216 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 217 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 220 of file rtp.c.
Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write().
| #define FLAG_P2P_SENT_MARK (1 << 4) |
Definition at line 219 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 344 of file rtp.c.
Referenced by ast_rtp_read(), and stun_handle_packet().
| #define STUN_BINDERR 0x0111 |
Definition at line 355 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 353 of file rtp.c.
Referenced by ast_stun_request(), stun_handle_packet(), and stun_msg2str().
| #define STUN_BINDRESP 0x0101 |
Definition at line 354 of file rtp.c.
Referenced by stun_handle_packet(), and stun_msg2str().
| #define STUN_CHANGE_REQUEST 0x0003 |
Definition at line 365 of file rtp.c.
Referenced by stun_attr2str().
| #define STUN_CHANGED_ADDRESS 0x0005 |
Definition at line 367 of file rtp.c.
Referenced by stun_attr2str().
| #define STUN_ERROR_CODE 0x0009 |
Definition at line 371 of file rtp.c.
Referenced by stun_attr2str().
| #define STUN_IGNORE (0) |
Definition at line 343 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 363 of file rtp.c.
Referenced by stun_attr2str(), stun_get_mapped(), and stun_handle_packet().
| #define STUN_MESSAGE_INTEGRITY 0x0008 |
Definition at line 370 of file rtp.c.
Referenced by stun_attr2str().
| #define STUN_PASSWORD 0x0007 |
Definition at line 369 of file rtp.c.
Referenced by stun_attr2str(), and stun_process_attr().
| #define STUN_REFLECTED_FROM 0x000b |
Definition at line 373 of file rtp.c.
Referenced by stun_attr2str().
| #define STUN_RESPONSE_ADDRESS 0x0002 |
Definition at line 364 of file rtp.c.
Referenced by stun_attr2str().
| #define STUN_SECERR 0x0112 |
Definition at line 358 of file rtp.c.
Referenced by stun_msg2str().
| #define STUN_SECREQ 0x0002 |
Definition at line 356 of file rtp.c.
Referenced by stun_msg2str().
| #define STUN_SECRESP 0x0102 |
Definition at line 357 of file rtp.c.
Referenced by stun_msg2str().
| #define STUN_SOURCE_ADDRESS 0x0004 |
Definition at line 366 of file rtp.c.
Referenced by stun_attr2str().
| #define STUN_UNKNOWN_ATTRIBUTES 0x000a |
Definition at line 372 of file rtp.c.
Referenced by stun_attr2str().
| #define STUN_USERNAME 0x0006 |
Definition at line 368 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 4809 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().
04810 { 04811 struct ast_config *cfg; 04812 const char *s; 04813 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04814 04815 if ((cfg = ast_config_load2("rtp.conf", "rtp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 04816 return 0; 04817 04818 rtpstart = 5000; 04819 rtpend = 31000; 04820 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04821 strictrtp = STRICT_RTP_OPEN; 04822 if (cfg) { 04823 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 04824 rtpstart = atoi(s); 04825 if (rtpstart < 1024) 04826 rtpstart = 1024; 04827 if (rtpstart > 65535) 04828 rtpstart = 65535; 04829 } 04830 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 04831 rtpend = atoi(s); 04832 if (rtpend < 1024) 04833 rtpend = 1024; 04834 if (rtpend > 65535) 04835 rtpend = 65535; 04836 } 04837 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 04838 rtcpinterval = atoi(s); 04839 if (rtcpinterval == 0) 04840 rtcpinterval = 0; /* Just so we're clear... it's zero */ 04841 if (rtcpinterval < RTCP_MIN_INTERVALMS) 04842 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 04843 if (rtcpinterval > RTCP_MAX_INTERVALMS) 04844 rtcpinterval = RTCP_MAX_INTERVALMS; 04845 } 04846 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 04847 #ifdef SO_NO_CHECK 04848 if (ast_false(s)) 04849 nochecksums = 1; 04850 else 04851 nochecksums = 0; 04852 #else 04853 if (ast_false(s)) 04854 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 04855 #endif 04856 } 04857 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 04858 dtmftimeout = atoi(s); 04859 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) { 04860 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 04861 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 04862 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04863 }; 04864 } 04865 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) { 04866 strictrtp = ast_true(s); 04867 } 04868 ast_config_destroy(cfg); 04869 } 04870 if (rtpstart >= rtpend) { 04871 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 04872 rtpstart = 5000; 04873 rtpend = 31000; 04874 } 04875 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 04876 return 0; 04877 }
| 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 466 of file rtp.c.
References stun_addr::addr, stun_addr::family, stun_addr::port, and stun_addr::unused.
Referenced by stun_handle_packet().
00467 { 00468 int size = sizeof(**attr) + 8; 00469 struct stun_addr *addr; 00470 if (*left > size) { 00471 (*attr)->attr = htons(attrval); 00472 (*attr)->len = htons(8); 00473 addr = (struct stun_addr *)((*attr)->value); 00474 addr->unused = 0; 00475 addr->family = 0x01; 00476 addr->port = sock_in->sin_port; 00477 addr->addr = sock_in->sin_addr.s_addr; 00478 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00479 *len += size; 00480 *left -= size; 00481 } 00482 }
| 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 452 of file rtp.c.
Referenced by ast_stun_request(), and stun_handle_packet().
00453 { 00454 int size = sizeof(**attr) + strlen(s); 00455 if (*left > size) { 00456 (*attr)->attr = htons(attrval); 00457 (*attr)->len = htons(strlen(s)); 00458 memcpy((*attr)->value, s, strlen(s)); 00459 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00460 *len += size; 00461 *left -= size; 00462 } 00463 }
| unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 740 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00741 { 00742 unsigned int interval; 00743 /*! \todo XXX Do a more reasonable calculation on this one 00744 * Look in RFC 3550 Section A.7 for an example*/ 00745 interval = rtcpinterval; 00746 return interval; 00747 }
| int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 728 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 2462 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().
02463 { 02464 struct ast_rtcp *rtcp; 02465 02466 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 02467 return NULL; 02468 rtcp->s = rtp_socket("RTCP"); 02469 rtcp->us.sin_family = AF_INET; 02470 rtcp->them.sin_family = AF_INET; 02471 rtcp->schedid = -1; 02472 02473 if (rtcp->s < 0) { 02474 ast_free(rtcp); 02475 return NULL; 02476 } 02477 02478 return rtcp; 02479 }
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 499 of file rtp.c.
Referenced by process_sdp().
00500 { 00501 return sizeof(struct ast_rtp); 00502 }
| 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().
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().
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(), 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 2076 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.
02077 { 02078 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 02079 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 02080 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 02081 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 02082 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; 02083 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; 02084 int srccodec, destcodec, nat_active = 0; 02085 02086 /* Lock channels */ 02087 ast_channel_lock(c0); 02088 if (c1) { 02089 while (ast_channel_trylock(c1)) { 02090 ast_channel_unlock(c0); 02091 usleep(1); 02092 ast_channel_lock(c0); 02093 } 02094 } 02095 02096 /* Find channel driver interfaces */ 02097 destpr = get_proto(c0); 02098 if (c1) 02099 srcpr = get_proto(c1); 02100 if (!destpr) { 02101 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name); 02102 ast_channel_unlock(c0); 02103 if (c1) 02104 ast_channel_unlock(c1); 02105 return -1; 02106 } 02107 if (!srcpr) { 02108 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>"); 02109 ast_channel_unlock(c0); 02110 if (c1) 02111 ast_channel_unlock(c1); 02112 return -1; 02113 } 02114 02115 /* Get audio, video and text interface (if native bridge is possible) */ 02116 audio_dest_res = destpr->get_rtp_info(c0, &destp); 02117 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED; 02118 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED; 02119 if (srcpr) { 02120 audio_src_res = srcpr->get_rtp_info(c1, &srcp); 02121 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED; 02122 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED; 02123 } 02124 02125 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 02126 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) { 02127 /* Somebody doesn't want to play... */ 02128 ast_channel_unlock(c0); 02129 if (c1) 02130 ast_channel_unlock(c1); 02131 return -1; 02132 } 02133 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) 02134 srccodec = srcpr->get_codec(c1); 02135 else 02136 srccodec = 0; 02137 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) 02138 destcodec = destpr->get_codec(c0); 02139 else 02140 destcodec = 0; 02141 /* Ensure we have at least one matching codec */ 02142 if (srcp && !(srccodec & destcodec)) { 02143 ast_channel_unlock(c0); 02144 ast_channel_unlock(c1); 02145 return 0; 02146 } 02147 /* Consider empty media as non-existent */ 02148 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 02149 srcp = NULL; 02150 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02151 nat_active = 1; 02152 /* Bridge media early */ 02153 if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active)) 02154 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 02155 ast_channel_unlock(c0); 02156 if (c1) 02157 ast_channel_unlock(c1); 02158 ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 02159 return 0; 02160 }
| int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 723 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().
00724 { 00725 return rtp->s; 00726 }
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 2298 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().
02300 { 02301 int pt; 02302 02303 rtp_bridge_lock(rtp); 02304 02305 *astFormats = *nonAstFormats = 0; 02306 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02307 if (rtp->current_RTP_PT[pt].isAstFormat) { 02308 *astFormats |= rtp->current_RTP_PT[pt].code; 02309 } else { 02310 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 02311 } 02312 } 02313 02314 rtp_bridge_unlock(rtp); 02315 }
| 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 783 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by check_rtp_timeout().
00784 { 00785 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00786 return 0; 00787 return rtp->rtpholdtimeout; 00788 }
| int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 791 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by check_rtp_timeout().
00792 { 00793 return rtp->rtpkeepalive; 00794 }
| int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 775 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by check_rtp_timeout().
00776 { 00777 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00778 return 0; 00779 return rtp->rtptimeout; 00780 }
| 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 811 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00812 { 00813 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00814 }
| void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 4885 of file rtp.c.
References __ast_rtp_reload(), and ast_cli_register_multiple().
Referenced by main().
04886 { 04887 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 04888 __ast_rtp_reload(0); 04889 }
| 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 2339 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().
02340 { 02341 int pt = 0; 02342 02343 rtp_bridge_lock(rtp); 02344 02345 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 02346 code == rtp->rtp_lookup_code_cache_code) { 02347 /* Use our cached mapping, to avoid the overhead of the loop below */ 02348 pt = rtp->rtp_lookup_code_cache_result; 02349 rtp_bridge_unlock(rtp); 02350 return pt; 02351 } 02352 02353 /* Check the dynamic list first */ 02354 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02355 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 02356 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02357 rtp->rtp_lookup_code_cache_code = code; 02358 rtp->rtp_lookup_code_cache_result = pt; 02359 rtp_bridge_unlock(rtp); 02360 return pt; 02361 } 02362 } 02363 02364 /* Then the static list */ 02365 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02366 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 02367 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02368 rtp->rtp_lookup_code_cache_code = code; 02369 rtp->rtp_lookup_code_cache_result = pt; 02370 rtp_bridge_unlock(rtp); 02371 return pt; 02372 } 02373 } 02374 02375 rtp_bridge_unlock(rtp); 02376 02377 return -1; 02378 }
| 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 2399 of file rtp.c.
References ast_copy_string(), ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.
Referenced by process_sdp().
02401 { 02402 int format; 02403 unsigned len; 02404 char *end = buf; 02405 char *start = buf; 02406 02407 if (!buf || !size) 02408 return NULL; 02409 02410 snprintf(end, size, "0x%x (", capability); 02411 02412 len = strlen(end); 02413 end += len; 02414 size -= len; 02415 start = end; 02416 02417 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 02418 if (capability & format) { 02419 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 02420 02421 snprintf(end, size, "%s|", name); 02422 len = strlen(end); 02423 end += len; 02424 size -= len; 02425 } 02426 } 02427 02428 if (start == end) 02429 ast_copy_string(start, "nothing)", size); 02430 else if (size > 1) 02431 *(end -1) = ')'; 02432 02433 return buf; 02434 }
| 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 2380 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().
02382 { 02383 unsigned int i; 02384 02385 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02386 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 02387 if (isAstFormat && 02388 (code == AST_FORMAT_G726_AAL2) && 02389 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02390 return "G726-32"; 02391 else 02392 return mimeTypes[i].subtype; 02393 } 02394 } 02395 02396 return ""; 02397 }
| 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 2317 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().
02318 { 02319 struct rtpPayloadType result; 02320 02321 result.isAstFormat = result.code = 0; 02322 02323 if (pt < 0 || pt > MAX_RTP_PT) 02324 return result; /* bogus payload type */ 02325 02326 /* Start with negotiated codecs */ 02327 rtp_bridge_lock(rtp); 02328 result = rtp->current_RTP_PT[pt]; 02329 rtp_bridge_unlock(rtp); 02330 02331 /* If it doesn't exist, check our static RTP type list, just in case */ 02332 if (!result.code) 02333 result = static_RTP_PT[pt]; 02334 02335 return result; 02336 }
| int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
| struct ast_channel * | src, | |||
| int | media | |||
| ) |
Definition at line 2162 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().
02163 { 02164 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 02165 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 02166 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 02167 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 02168 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; 02169 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; 02170 int srccodec, destcodec; 02171 02172 /* Lock channels */ 02173 ast_channel_lock(dest); 02174 while (ast_channel_trylock(src)) { 02175 ast_channel_unlock(dest); 02176 usleep(1); 02177 ast_channel_lock(dest); 02178 } 02179 02180 /* Find channel driver interfaces */ 02181 if (!(destpr = get_proto(dest))) { 02182 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name); 02183 ast_channel_unlock(dest); 02184 ast_channel_unlock(src); 02185 return 0; 02186 } 02187 if (!(srcpr = get_proto(src))) { 02188 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name); 02189 ast_channel_unlock(dest); 02190 ast_channel_unlock(src); 02191 return 0; 02192 } 02193 02194 /* Get audio and video interface (if native bridge is possible) */ 02195 audio_dest_res = destpr->get_rtp_info(dest, &destp); 02196 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 02197 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED; 02198 audio_src_res = srcpr->get_rtp_info(src, &srcp); 02199 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 02200 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED; 02201 02202 /* Ensure we have at least one matching codec */ 02203 if (srcpr->get_codec) 02204 srccodec = srcpr->get_codec(src); 02205 else 02206 srccodec = 0; 02207 if (destpr->get_codec) 02208 destcodec = destpr->get_codec(dest); 02209 else 02210 destcodec = 0; 02211 02212 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 02213 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)) { 02214 /* Somebody doesn't want to play... */ 02215 ast_channel_unlock(dest); 02216 ast_channel_unlock(src); 02217 return 0; 02218 } 02219 ast_rtp_pt_copy(destp, srcp); 02220 if (vdestp && vsrcp) 02221 ast_rtp_pt_copy(vdestp, vsrcp); 02222 if (tdestp && tsrcp) 02223 ast_rtp_pt_copy(tdestp, tsrcp); 02224 if (media) { 02225 /* Bridge early */ 02226 if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02227 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 02228 } 02229 ast_channel_unlock(dest); 02230 ast_channel_unlock(src); 02231 ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 02232 return 1; 02233 }
| 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 2594 of file rtp.c.
References ast_rtp_new_with_bindaddr().
02595 { 02596 struct in_addr ia; 02597 02598 memset(&ia, 0, sizeof(ia)); 02599 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02600 }
| void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
reload rtp configuration
Definition at line 2485 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().
02486 { 02487 #ifdef P2P_INTENSE 02488 ast_mutex_init(&rtp->bridge_lock); 02489 #endif 02490 02491 rtp->them.sin_family = AF_INET; 02492 rtp->us.sin_family = AF_INET; 02493 rtp->ssrc = ast_random(); 02494 rtp->seqno = ast_random() & 0xffff; 02495 ast_set_flag(rtp, FLAG_HAS_DTMF); 02496 rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN); 02497 }
| void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2607 of file rtp.c.
References ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_answer(), sip_indicate(), sip_write(), and skinny_indicate().
02608 { 02609 if (rtp) { 02610 rtp->set_marker_bit = 1; 02611 } 02612 return; 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 2499 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().
02500 { 02501 struct ast_rtp *rtp; 02502 int x; 02503 int startplace; 02504 02505 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 02506 return NULL; 02507 02508 ast_rtp_new_init(rtp); 02509 02510 rtp->s = rtp_socket("RTP"); 02511 if (rtp->s < 0) 02512 goto fail; 02513 if (sched && rtcpenable) { 02514 rtp->sched = sched; 02515 rtp->rtcp = ast_rtcp_new(); 02516 } 02517 02518 /* 02519 * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well. 02520 * Start from a random (even, by RTP spec) port number, and 02521 * iterate until success or no ports are available. 02522 * Note that the requirement of RTP port being even, or RTCP being the 02523 * next one, cannot be enforced in presence of a NAT box because the 02524 * mapping is not under our control. 02525 */ 02526 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 02527 x = x & ~1; /* make it an even number */ 02528 startplace = x; /* remember the starting point */ 02529 /* this is constant across the loop */ 02530 rtp->us.sin_addr = addr; 02531 if (rtp->rtcp) 02532 rtp->rtcp->us.sin_addr = addr; 02533 for (;;) { 02534 rtp->us.sin_port = htons(x); 02535 if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) { 02536 /* bind succeeded, if no rtcp then we are done */ 02537 if (!rtp->rtcp) 02538 break; 02539 /* have rtcp, try to bind it */ 02540 rtp->rtcp->us.sin_port = htons(x + 1); 02541 if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) 02542 break; /* success again, we are really done */ 02543 /* 02544 * RTCP bind failed, so close and recreate the 02545 * already bound RTP socket for the next round. 02546 */ 02547 close(rtp->s); 02548 rtp->s = rtp_socket("RTP"); 02549 if (rtp->s < 0) 02550 goto fail; 02551 } 02552 /* 02553 * If we get here, there was an error in one of the bind() 02554 * calls, so make sure it is nothing unexpected. 02555 */ 02556 if (errno != EADDRINUSE) { 02557 /* We got an error that wasn't expected, abort! */ 02558 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 02559 goto fail; 02560 } 02561 /* 02562 * One of the ports is in use. For the next iteration, 02563 * increment by two and handle wraparound. 02564 * If we reach the starting point, then declare failure. 02565 */ 02566 x += 2; 02567 if (x > rtpend) 02568 x = (rtpstart + 1) & ~1; 02569 if (x == startplace) { 02570 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 02571 goto fail; 02572 } 02573 } 02574 rtp->sched = sched; 02575 rtp->io = io; 02576 if (callbackmode) { 02577 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 02578 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 02579 } 02580 ast_rtp_pt_default(rtp); 02581 return rtp; 02582 02583 fail: 02584 if (rtp->s >= 0) 02585 close(rtp->s); 02586 if (rtp->rtcp) { 02587 close(rtp->rtcp->s); 02588 ast_free(rtp->rtcp); 02589 } 02590 ast_free(rtp); 02591 return NULL; 02592 }
| 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 2000 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().
02001 { 02002 int i; 02003 02004 if (!rtp) 02005 return; 02006 02007 rtp_bridge_lock(rtp); 02008 02009 for (i = 0; i < MAX_RTP_PT; ++i) { 02010 rtp->current_RTP_PT[i].isAstFormat = 0; 02011 rtp->current_RTP_PT[i].code = 0; 02012 } 02013 02014 rtp->rtp_lookup_code_cache_isAstFormat = 0; 02015 rtp->rtp_lookup_code_cache_code = 0; 02016 rtp->rtp_lookup_code_cache_result = 0; 02017 02018 rtp_bridge_unlock(rtp); 02019 }
Copy payload types between RTP structures.
Definition at line 2040 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().
02041 { 02042 unsigned int i; 02043 02044 rtp_bridge_lock(dest); 02045 rtp_bridge_lock(src); 02046 02047 for (i = 0; i < MAX_RTP_PT; ++i) { 02048 dest->current_RTP_PT[i].isAstFormat = 02049 src->current_RTP_PT[i].isAstFormat; 02050 dest->current_RTP_PT[i].code = 02051 src->current_RTP_PT[i].code; 02052 } 02053 dest->rtp_lookup_code_cache_isAstFormat = 0; 02054 dest->rtp_lookup_code_cache_code = 0; 02055 dest->rtp_lookup_code_cache_result = 0; 02056 02057 rtp_bridge_unlock(src); 02058 rtp_bridge_unlock(dest); 02059 }
| void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 2021 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().
02022 { 02023 int i; 02024 02025 rtp_bridge_lock(rtp); 02026 02027 /* Initialize to default payload types */ 02028 for (i = 0; i < MAX_RTP_PT; ++i) { 02029 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 02030 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 02031 } 02032 02033 rtp->rtp_lookup_code_cache_isAstFormat = 0; 02034 rtp->rtp_lookup_code_cache_code = 0; 02035 rtp->rtp_lookup_code_cache_result = 0; 02036 02037 rtp_bridge_unlock(rtp); 02038 }
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 1575 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().
01576 { 01577 int res; 01578 struct sockaddr_in sock_in; 01579 socklen_t len; 01580 unsigned int seqno; 01581 int version; 01582 int payloadtype; 01583 int hdrlen = 12; 01584 int padding; 01585 int mark; 01586 int ext; 01587 int cc; 01588 unsigned int ssrc; 01589 unsigned int timestamp; 01590 unsigned int *rtpheader; 01591 struct rtpPayloadType rtpPT; 01592 struct ast_rtp *bridged = NULL; 01593 int prev_seqno; 01594 01595 /* If time is up, kill it */ 01596 if (rtp->sending_digit) 01597 ast_rtp_senddigit_continuation(rtp); 01598 01599 len = sizeof(sock_in); 01600 01601 /* Cache where the header will go */ 01602 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01603 0, (struct sockaddr *)&sock_in, &len); 01604 01605 /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */ 01606 if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { 01607 /* Copy over address that this packet was received on */ 01608 memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address)); 01609 /* Now move over to actually protecting the RTP port */ 01610 rtp->strict_rtp_state = STRICT_RTP_CLOSED; 01611 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)); 01612 } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { 01613 /* If the address we previously learned doesn't match the address this packet came in on simply drop it */ 01614 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)) { 01615 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)); 01616 return &ast_null_frame; 01617 } 01618 } 01619 01620 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01621 if (res < 0) { 01622 ast_assert(errno != EBADF); 01623 if (errno != EAGAIN) { 01624 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01625 return NULL; 01626 } 01627 return &ast_null_frame; 01628 } 01629 01630 if (res < hdrlen) { 01631 ast_log(LOG_WARNING, "RTP Read too short\n"); 01632 return &ast_null_frame; 01633 } 01634 01635 /* Get fields */ 01636 seqno = ntohl(rtpheader[0]); 01637 01638 /* Check RTP version */ 01639 version = (seqno & 0xC0000000) >> 30; 01640 if (!version) { 01641 /* If the two high bits are 0, this might be a 01642 * STUN message, so process it. stun_handle_packet() 01643 * answers to requests, and it returns STUN_ACCEPT 01644 * if the request is valid. 01645 */ 01646 if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) && 01647 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01648 memcpy(&rtp->them, &sock_in, sizeof(rtp->them)); 01649 } 01650 return &ast_null_frame; 01651 } 01652 01653 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01654 /* If we don't have the other side's address, then ignore this */ 01655 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01656 return &ast_null_frame; 01657 #endif 01658 01659 /* Send to whoever send to us if NAT is turned on */ 01660 if (rtp->nat) { 01661 if (((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01662 (rtp->them.sin_port != sock_in.sin_port)) && 01663 ((rtp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 01664 (rtp->altthem.sin_port != sock_in.sin_port))) { 01665 rtp->them = sock_in; 01666 if (rtp->rtcp) { 01667 int h = 0; 01668 memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them)); 01669 h = ntohs(rtp->them.sin_port); 01670 rtp->rtcp->them.sin_port = htons(h + 1); 01671 } 01672 rtp->rxseqno = 0; 01673 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01674 if (option_debug || rtpdebug) 01675 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)); 01676 } 01677 } 01678 01679 /* If we are bridged to another RTP stream, send direct */ 01680 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01681 return &ast_null_frame; 01682 01683 if (version != 2) 01684 return &ast_null_frame; 01685 01686 payloadtype = (seqno & 0x7f0000) >> 16; 01687 padding = seqno & (1 << 29); 01688 mark = seqno & (1 << 23); 01689 ext = seqno & (1 << 28); 01690 cc = (seqno & 0xF000000) >> 24; 01691 seqno &= 0xffff; 01692 timestamp = ntohl(rtpheader[1]); 01693 ssrc = ntohl(rtpheader[2]); 01694 01695 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01696 if (option_debug || rtpdebug) 01697 ast_debug(0, "Forcing Marker bit, because SSRC has changed\n"); 01698 mark = 1; 01699 } 01700 01701 rtp->rxssrc = ssrc; 01702 01703 if (padding) { 01704 /* Remove padding bytes */ 01705 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01706 } 01707 01708 if (cc) { 01709 /* CSRC fields present */ 01710 hdrlen += cc*4; 01711 } 01712 01713 if (ext) { 01714 /* RTP Extension present */ 01715 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01716 hdrlen += 4; 01717 if (option_debug) { 01718 int profile; 01719 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01720 if (profile == 0x505a) 01721 ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01722 else 01723 ast_debug(1, "Found unknown RTP Extensions %x\n", profile); 01724 } 01725 } 01726 01727 if (res < hdrlen) { 01728 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01729 return &ast_null_frame; 01730 } 01731 01732 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01733 01734 if (rtp->rxcount==1) { 01735 /* This is the first RTP packet successfully received from source */ 01736 rtp->seedrxseqno = seqno; 01737 } 01738 01739 /* Do not schedule RR if RTCP isn't run */ 01740 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01741 /* Schedule transmission of Receiver Report */ 01742 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01743 } 01744 if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01745 rtp->cycles += RTP_SEQ_MOD; 01746 01747 prev_seqno = rtp->lastrxseqno; 01748 01749 rtp->lastrxseqno = seqno; 01750 01751 if (!rtp->themssrc) 01752 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01753 01754 if (rtp_debug_test_addr(&sock_in)) 01755 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01756 ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01757 01758 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01759 if (!rtpPT.isAstFormat) { 01760 struct ast_frame *f = NULL; 01761 01762 /* This is special in-band data that's not one of our codecs */ 01763 if (rtpPT.code == AST_RTP_DTMF) { 01764 /* It's special -- rfc2833 process it */ 01765 if (rtp_debug_test_addr(&sock_in)) { 01766 unsigned char *data; 01767 unsigned int event; 01768 unsigned int event_end; 01769 unsigned int duration; 01770 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01771 event = ntohl(*((unsigned int *)(data))); 01772 event >>= 24; 01773 event_end = ntohl(*((unsigned int *)(data))); 01774 event_end <<= 8; 01775 event_end >>= 24; 01776 duration = ntohl(*((unsigned int *)(data))); 01777 duration &= 0xFFFF; 01778 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); 01779 } 01780 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01781 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01782 /* It's really special -- process it the Cisco way */ 01783 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01784 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01785 rtp->lastevent = seqno; 01786 } 01787 } else if (rtpPT.code == AST_RTP_CN) { 01788 /* Comfort Noise */ 01789 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01790 } else { 01791 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01792 } 01793 return f ? f : &ast_null_frame; 01794 } 01795 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01796 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; 01797 01798 rtp->rxseqno = seqno; 01799 01800 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) { 01801 rtp->dtmf_timeout = 0; 01802 01803 if (rtp->resp) { 01804 struct ast_frame *f; 01805 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01806 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01807 rtp->resp = 0; 01808 rtp->dtmf_timeout = rtp->dtmf_duration = 0; 01809 return f; 01810 } 01811 } 01812 01813 /* Record received timestamp as last received now */ 01814 rtp->lastrxts = timestamp; 01815 01816 rtp->f.mallocd = 0; 01817 rtp->f.datalen = res - hdrlen; 01818 rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01819 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01820 rtp->f.seqno = seqno; 01821 01822 if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) { 01823 unsigned char *data = rtp->f.data.ptr; 01824 01825 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen); 01826 rtp->f.datalen +=3; 01827 *data++ = 0xEF; 01828 *data++ = 0xBF; 01829 *data = 0xBD; 01830 } 01831 01832 if (rtp->f.subclass == AST_FORMAT_T140RED) { 01833 unsigned char *data = rtp->f.data.ptr; 01834 unsigned char *header_end; 01835 int num_generations; 01836 int header_length; 01837 int length; 01838 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/ 01839 int x; 01840 01841 rtp->f.subclass = AST_FORMAT_T140; 01842 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); 01843 if (header_end == NULL) { 01844 return &ast_null_frame; 01845 } 01846 header_end++; 01847 01848 header_length = header_end - data; 01849 num_generations = header_length / 4; 01850 length = header_length; 01851 01852 if (!diff) { 01853 for (x = 0; x < num_generations; x++) 01854 length += data[x * 4 + 3]; 01855 01856 if (!(rtp->f.datalen - length)) 01857 return &ast_null_frame; 01858 01859 rtp->f.data.ptr += length; 01860 rtp->f.datalen -= length; 01861 } else if (diff > num_generations && diff < 10) { 01862 length -= 3; 01863 rtp->f.data.ptr += length; 01864 rtp->f.datalen -= length; 01865 01866 data = rtp->f.data.ptr; 01867 *data++ = 0xEF; 01868 *data++ = 0xBF; 01869 *data = 0xBD; 01870 } else { 01871 for ( x = 0; x < num_generations - diff; x++) 01872 length += data[x * 4 + 3]; 01873 01874 rtp->f.data.ptr += length; 01875 rtp->f.datalen -= length; 01876 } 01877 } 01878 01879 if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) { 01880 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01881 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01882 ast_frame_byteswap_be(&rtp->f); 01883 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01884 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01885 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01886 rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000); 01887 rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 ); 01888 } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) { 01889 /* Video -- samples is # of samples vs. 90000 */ 01890 if (!rtp->lastividtimestamp) 01891 rtp->lastividtimestamp = timestamp; 01892 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01893 rtp->lastividtimestamp = timestamp; 01894 rtp->f.delivery.tv_sec = 0; 01895 rtp->f.delivery.tv_usec = 0; 01896 /* Pass the RTP marker bit as bit 0 in the subclass field. 01897 * This is ok because subclass is actually a bitmask, and 01898 * the low bits represent audio formats, that are not 01899 * involved here since we deal with video. 01900 */ 01901 if (mark) 01902 rtp->f.subclass |= 0x1; 01903 } else { 01904 /* TEXT -- samples is # of samples vs. 1000 */ 01905 if (!rtp->lastitexttimestamp) 01906 rtp->lastitexttimestamp = timestamp; 01907 rtp->f.samples = timestamp - rtp->lastitexttimestamp; 01908 rtp->lastitexttimestamp = timestamp; 01909 rtp->f.delivery.tv_sec = 0; 01910 rtp->f.delivery.tv_usec = 0; 01911 } 01912 rtp->f.src = "RTP"; 01913 return &rtp->f; 01914 }
| int ast_rtp_reload | ( | void | ) |
Initialize RTP subsystem
Definition at line 4879 of file rtp.c.
References __ast_rtp_reload().
04880 { 04881 return __ast_rtp_reload(1); 04882 }
| 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 801 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00802 { 00803 rtp->callback = callback; 00804 }
| 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 2239 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().
02240 { 02241 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 02242 return; /* bogus payload type */ 02243 02244 rtp_bridge_lock(rtp); 02245 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 02246 rtp_bridge_unlock(rtp); 02247 }
| 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 763 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().
00764 { 00765 rtp->rtpholdtimeout = timeout; 00766 }
| void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
| int | period | |||
| ) |
set RTP keepalive interval
Definition at line 769 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00770 { 00771 rtp->rtpkeepalive = period; 00772 }
| 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 2266 of file rtp.c.
References ARRAY_LEN, AST_FORMAT_G726, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, rtp_bridge_lock(), rtp_bridge_unlock(), subtype, and type.
Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), jingle_newcall(), process_sdp(), set_dtmf_payload(), and setup_rtp_connection().
02269 { 02270 unsigned int i; 02271 int found = 0; 02272 02273 if (pt < 0 || pt > MAX_RTP_PT) 02274 return -1; /* bogus payload type */ 02275 02276 rtp_bridge_lock(rtp); 02277 02278 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02279 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 02280 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 02281 found = 1; 02282 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 02283 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 02284 mimeTypes[i].payloadType.isAstFormat && 02285 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02286 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 02287 break; 02288 } 02289 } 02290 02291 rtp_bridge_unlock(rtp); 02292 02293 return (found ? 0 : -1); 02294 }
| void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
| int | timeout | |||
| ) |
Set rtp timeout.
Definition at line 757 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().
00758 { 00759 rtp->rtptimeout = timeout; 00760 }
| void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 750 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00751 { 00752 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00753 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00754 }
| 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 816 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().
00817 { 00818 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00819 }
| void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
| int | compensate | |||
| ) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 821 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().
00822 { 00823 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00824 }
| void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
| int | nat | |||
| ) |
Definition at line 806 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 2602 of file rtp.c.
References ast_netsock_set_qos(), and ast_rtp::s.
Referenced by __oh323_rtp_create(), sip_alloc(), and start_rtp().
02603 { 02604 return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc); 02605 }
| void ast_rtp_setstun | ( | struct ast_rtp * | rtp, | |
| int | stun_enable | |||
| ) |
Enable STUN capability.
Definition at line 826 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00827 { 00828 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00829 }
| 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 705 of file rtp.c.
References ast_stun_request(), and ast_rtp::s.
Referenced by gtalk_update_stun(), and jingle_update_stun().
00706 { 00707 ast_stun_request(rtp->s, suggestion, username, NULL); 00708 }
| 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 2251 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().
02252 { 02253 if (pt < 0 || pt > MAX_RTP_PT) 02254 return; /* bogus payload type */ 02255 02256 rtp_bridge_lock(rtp); 02257 rtp->current_RTP_PT[pt].isAstFormat = 0; 02258 rtp->current_RTP_PT[pt].code = 0; 02259 rtp_bridge_unlock(rtp); 02260 }
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 639 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().
00641 { 00642 struct stun_header *req; 00643 unsigned char reqdata[1024]; 00644 int reqlen, reqleft; 00645 struct stun_attr *attr; 00646 int res = 0; 00647 int retry; 00648 00649 req = (struct stun_header *)reqdata; 00650 stun_req_id(req); 00651 reqlen = 0; 00652 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00653 req->msgtype = 0; 00654 req->msglen = 0; 00655 attr = (struct stun_attr *)req->ies; 00656 if (username) 00657 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00658 req->msglen = htons(reqlen); 00659 req->msgtype = htons(STUN_BINDREQ); 00660 for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */ 00661 /* send request, possibly wait for reply */ 00662 unsigned char reply_buf[1024]; 00663 fd_set rfds; 00664 struct timeval to = { 3, 0 }; /* timeout, make it configurable */ 00665 struct sockaddr_in src; 00666 socklen_t srclen; 00667 00668 res = stun_send(s, dst, req); 00669 if (res < 0) { 00670 ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n", 00671 retry, res); 00672 continue; 00673 } 00674 if (answer == NULL) 00675 break; 00676 FD_ZERO(&rfds); 00677 FD_SET(s, &rfds); 00678 res = ast_select(s + 1, &rfds, NULL, NULL, &to); 00679 if (res <= 0) /* timeout or error */ 00680 continue; 00681 memset(&src, '\0', sizeof(src)); 00682 srclen = sizeof(src); 00683 /* XXX pass -1 in the size, because stun_handle_packet might 00684 * write past the end of the buffer. 00685 */ 00686 res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1, 00687 0, (struct sockaddr *)&src, &srclen); 00688 if (res < 0) { 00689 ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n", 00690 retry, res); 00691 continue; 00692 } 00693 memset(answer, '\0', sizeof(struct sockaddr_in)); 00694 stun_handle_packet(s, &src, reply_buf, res, 00695 stun_get_mapped, answer); 00696 res = 0; /* signal regular exit */ 00697 break; 00698 } 00699 return res; 00700 }
| 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 1521 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().
01522 { 01523 int res = 0, payload = 0, bridged_payload = 0, mark; 01524 struct rtpPayloadType rtpPT; 01525 int reconstruct = ntohl(rtpheader[0]); 01526 01527 /* Get fields from packet */ 01528 payload = (reconstruct & 0x7f0000) >> 16; 01529 mark = (((reconstruct & 0x800000) >> 23) != 0); 01530 01531 /* Check what the payload value should be */ 01532 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01533 01534 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01535 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01536 return -1; 01537 01538 /* Otherwise adjust bridged payload to match */ 01539 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01540 01541 /* 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 */ 01542 if (!bridged->current_RTP_PT[bridged_payload].code) 01543 return -1; 01544 01545 01546 /* If the mark bit has not been sent yet... do it now */ 01547 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01548 mark = 1; 01549 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01550 } 01551 01552 /* Reconstruct part of the packet */ 01553 reconstruct &= 0xFF80FFFF; 01554 reconstruct |= (bridged_payload << 16); 01555 reconstruct |= (mark << 23); 01556 rtpheader[0] = htonl(reconstruct); 01557 01558 /* Send the packet back out */ 01559 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01560 if (res < 0) { 01561 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01562 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)); 01563 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01564 if (option_debug || rtpdebug) 01565 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)); 01566 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01567 } 01568 return 0; 01569 } else if (rtp_debug_test_addr(&bridged->them)) 01570 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); 01571 01572 return 0; 01573 }
| 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_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 double transit; 01463 double current_time; 01464 double d; 01465 double dtv; 01466 double prog; 01467 double normdev_rxjitter_current; 01468 int rate = rtp_get_rate(rtp->f.subclass); 01469 01470 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01471 gettimeofday(&rtp->rxcore, NULL); 01472 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01473 /* map timestamp to a real time */ 01474 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01475 rtp->rxcore.tv_sec -= timestamp / rate; 01476 rtp->rxcore.tv_usec -= (timestamp % rate) * 125; 01477 /* Round to 0.1ms for nice, pretty timestamps */ 01478 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01479 if (rtp->rxcore.tv_usec < 0) { 01480 /* Adjust appropriately if necessary */ 01481 rtp->rxcore.tv_usec += 1000000; 01482 rtp->rxcore.tv_sec -= 1; 01483 } 01484 } 01485 01486 gettimeofday(&now,NULL); 01487 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01488 when->tv_sec = rtp->rxcore.tv_sec + timestamp / rate; 01489 when->tv_usec = rtp->rxcore.tv_usec + (timestamp % rate) * 125; 01490 if (when->tv_usec >= 1000000) { 01491 when->tv_usec -= 1000000; 01492 when->tv_sec += 1; 01493 } 01494 prog = (double)((timestamp-rtp->seedrxts)/(float)(rate)); 01495 dtv = (double)rtp->drxcore + (double)(prog); 01496 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01497 transit = current_time - dtv; 01498 d = transit - rtp->rxtransit; 01499 rtp->rxtransit = transit; 01500 if (d<0) 01501 d=-d; 01502 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01503 01504 if (rtp->rtcp) { 01505 if (rtp->rxjitter > rtp->rtcp->maxrxjitter) 01506 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01507 if (rtp->rtcp->rxjitter_count == 1) 01508 rtp->rtcp->minrxjitter = rtp->rxjitter; 01509 if (rtp->rxjitter < rtp->rtcp->minrxjitter) 01510 rtp->rtcp->minrxjitter = rtp->rxjitter; 01511 01512 normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count); 01513 rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count); 01514 01515 rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current; 01516 rtp->rtcp->rxjitter_count++; 01517 } 01518 }
| 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 2062 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().
02063 { 02064 struct ast_rtp_protocol *cur = NULL; 02065 02066 AST_RWLIST_RDLOCK(&protos); 02067 AST_RWLIST_TRAVERSE(&protos, cur, list) { 02068 if (cur->type == chan->tech->type) 02069 break; 02070 } 02071 AST_RWLIST_UNLOCK(&protos); 02072 02073 return cur; 02074 }
| static char* handle_cli_rtcp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4627 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.
04628 { 04629 switch (cmd) { 04630 case CLI_INIT: 04631 e->command = "rtcp debug [off|ip]"; 04632 e->usage = 04633 "Usage: rtcp debug [off]|[ip host[:port]]\n" 04634 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04635 " specified, limit the dumped packets to those to and from\n" 04636 " the specified 'host' with optional port.\n"; 04637 return NULL; 04638 case CLI_GENERATE: 04639 return NULL; 04640 } 04641 04642 if (a->argc < 2 || a->argc > 4) 04643 return CLI_SHOWUSAGE; 04644 if (a->argc == 2) { 04645 rtcpdebug = 1; 04646 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04647 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04648 } else if (a->argc == 3) { 04649 if (strncasecmp(a->argv[2], "off", 3)) 04650 return CLI_SHOWUSAGE; 04651 rtcpdebug = 0; 04652 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04653 } else { 04654 if (strncasecmp(a->argv[2], "ip", 2)) 04655 return CLI_SHOWUSAGE; 04656 return rtcp_do_debug_ip(a); 04657 } 04658 04659 return CLI_SUCCESS; 04660 }
| static char* handle_cli_rtcp_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4662 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.
04663 { 04664 switch (cmd) { 04665 case CLI_INIT: 04666 e->command = "rtcp set debug {on|off|ip}"; 04667 e->usage = 04668 "Usage: rtcp set debug {on|off|ip host[:port]}\n" 04669 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04670 " specified, limit the dumped packets to those to and from\n" 04671 " the specified 'host' with optional port.\n"; 04672 return NULL; 04673 case CLI_GENERATE: 04674 return NULL; 04675 } 04676 04677 if (a->argc == e->args) { /* set on or off */ 04678 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04679 rtcpdebug = 1; 04680 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04681 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04682 return CLI_SUCCESS; 04683 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04684 rtcpdebug = 0; 04685 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04686 return CLI_SUCCESS; 04687 } 04688 } else if (a->argc == e->args +1) { /* ip */ 04689 return rtcp_do_debug_ip(a); 04690 } 04691 04692 return CLI_SHOWUSAGE; /* default, failure */ 04693 }
| static char* handle_cli_rtcp_set_stats | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4718 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.
04719 { 04720 switch (cmd) { 04721 case CLI_INIT: 04722 e->command = "rtcp set stats {on|off}"; 04723 e->usage = 04724 "Usage: rtcp set stats {on|off}\n" 04725 " Enable/Disable dumping of RTCP stats.\n"; 04726 return NULL; 04727 case CLI_GENERATE: 04728 return NULL; 04729 } 04730 04731 if (a->argc != e->args) 04732 return CLI_SHOWUSAGE; 04733 04734 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04735 rtcpstats = 1; 04736 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04737 rtcpstats = 0; 04738 else 04739 return CLI_SHOWUSAGE; 04740 04741 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04742 return CLI_SUCCESS; 04743 }
| static char* handle_cli_rtcp_stats_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4695 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.
04696 { 04697 switch (cmd) { 04698 case CLI_INIT: 04699 e->command = "rtcp stats [off]"; 04700 e->usage = 04701 "Usage: rtcp stats [off]\n" 04702 " Enable/Disable dumping of RTCP stats.\n"; 04703 return NULL; 04704 case CLI_GENERATE: 04705 return NULL; 04706 } 04707 04708 if (a->argc < 2 || a->argc > 3) 04709 return CLI_SHOWUSAGE; 04710 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04711 return CLI_SHOWUSAGE; 04712 04713 rtcpstats = (a->argc == 3) ? 0 : 1; 04714 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04715 return CLI_SUCCESS; 04716 }
| static char* handle_cli_rtp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4559 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.
04560 { 04561 switch (cmd) { 04562 case CLI_INIT: 04563 e->command = "rtp debug [off|ip]"; 04564 e->usage = 04565 "Usage: rtp debug [off]|[ip host[:port]]\n" 04566 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04567 " specified, limit the dumped packets to those to and from\n" 04568 " the specified 'host' with optional port.\n"; 04569 return NULL; 04570 case CLI_GENERATE: 04571 return NULL; 04572 } 04573 04574 if (a->argc < 2 || a->argc > 4) 04575 return CLI_SHOWUSAGE; 04576 if (a->argc == 2) { 04577 rtpdebug = 1; 04578 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04579 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04580 } else if (a->argc == 3) { 04581 if (strncasecmp(a->argv[2], "off", 3)) 04582 return CLI_SHOWUSAGE; 04583 rtpdebug = 0; 04584 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04585 } else { 04586 if (strncasecmp(a->argv[2], "ip", 2)) 04587 return CLI_SHOWUSAGE; 04588 return rtp_do_debug_ip(a); 04589 } 04590 04591 return CLI_SUCCESS; 04592 }
| static char* handle_cli_rtp_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4594 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.
04595 { 04596 switch (cmd) { 04597 case CLI_INIT: 04598 e->command = "rtp set debug {on|off|ip}"; 04599 e->usage = 04600 "Usage: rtp set debug {on|off|ip host[:port]}\n" 04601 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04602 " specified, limit the dumped packets to those to and from\n" 04603 " the specified 'host' with optional port.\n"; 04604 return NULL; 04605 case CLI_GENERATE: 04606 return NULL; 04607 } 04608 04609 if (a->argc == e->args) { /* set on or off */ 04610 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04611 rtpdebug = 1; 04612 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04613 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04614 return CLI_SUCCESS; 04615 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04616 rtpdebug = 0; 04617 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04618 return CLI_SUCCESS; 04619 } 04620 } else if (a->argc == e->args +1) { /* ip */ 04621 return rtp_do_debug_ip(a); 04622 } 04623 04624 return CLI_SHOWUSAGE; /* default, failure */ 04625 }
| static char* handle_cli_stun_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4745 of file rtp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
04746 { 04747 switch (cmd) { 04748 case CLI_INIT: 04749 e->command = "stun debug [off]"; 04750 e->usage = 04751 "Usage: stun debug [off]\n" 04752 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04753 " debugging\n"; 04754 return NULL; 04755 case CLI_GENERATE: 04756 return NULL; 04757 } 04758 04759 if (a->argc < 2 || a->argc > 3) 04760 return CLI_SHOWUSAGE; 04761 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04762 return CLI_SHOWUSAGE; 04763 04764 stundebug = (a->argc == 3) ? 0 : 1; 04765 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04766 return CLI_SUCCESS; 04767 }
| static char* handle_cli_stun_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4769 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.
04770 { 04771 switch (cmd) { 04772 case CLI_INIT: 04773 e->command = "stun set debug {on|off}"; 04774 e->usage = 04775 "Usage: stun set debug {on|off}\n" 04776 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04777 " debugging\n"; 04778 return NULL; 04779 case CLI_GENERATE: 04780 return NULL; 04781 } 04782 04783 if (a->argc != e->args) 04784 return CLI_SHOWUSAGE; 04785 04786 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04787 stundebug = 1; 04788 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04789 stundebug = 0; 04790 else 04791 return CLI_SHOWUSAGE; 04792 04793 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04794 return CLI_SUCCESS; 04795 }
| static double normdev_compute | ( | double | normdev, | |
| double | sample, | |||
| unsigned int | sample_count | |||
| ) | [static] |
Calculate normal deviation.
Definition at line 848 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 928 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().
00929 { 00930 unsigned int event; 00931 char resp = 0; 00932 struct ast_frame *f = NULL; 00933 unsigned char seq; 00934 unsigned int flags; 00935 unsigned int power; 00936 00937 /* We should have at least 4 bytes in RTP data */ 00938 if (len < 4) 00939 return f; 00940 00941 /* The format of Cisco RTP DTMF packet looks like next: 00942 +0 - sequence number of DTMF RTP packet (begins from 1, 00943 wrapped to 0) 00944 +1 - set of flags 00945 +1 (bit 0) - flaps by different DTMF digits delimited by audio 00946 or repeated digit without audio??? 00947 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone 00948 then falls to 0 at its end) 00949 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...) 00950 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right 00951 by each new packet and thus provides some redudancy. 00952 00953 Sample of Cisco RTP DTMF packet is (all data in hex): 00954 19 07 00 02 12 02 20 02 00955 showing end of DTMF digit '2'. 00956 00957 The packets 00958 27 07 00 02 0A 02 20 02 00959 28 06 20 02 00 02 0A 02 00960 shows begin of new digit '2' with very short pause (20 ms) after 00961 previous digit '2'. Bit +1.0 flips at begin of new digit. 00962 00963 Cisco RTP DTMF packets comes as replacement of audio RTP packets 00964 so its uses the same sequencing and timestamping rules as replaced 00965 audio packets. Repeat interval of DTMF packets is 20 ms and not rely 00966 on audio framing parameters. Marker bit isn't used within stream of 00967 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps 00968 are not sequential at borders between DTMF and audio streams, 00969 */ 00970 00971 seq = data[0]; 00972 flags = data[1]; 00973 power = data[2]; 00974 event = data[3] & 0x1f; 00975 00976 if (option_debug > 2 || rtpdebug) 00977 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); 00978 if (event < 10) { 00979 resp = '0' + event; 00980 } else if (event < 11) { 00981 resp = '*'; 00982 } else if (event < 12) { 00983 resp = '#'; 00984 } else if (event < 16) { 00985 resp = 'A' + (event - 12); 00986 } else if (event < 17) { 00987 resp = 'X'; 00988 } 00989 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) { 00990 rtp->resp = resp; 00991 /* Why we should care on DTMF compensation at reception? */ 00992 if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00993 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00994 rtp->dtmfsamples = 0; 00995 } 00996 } else if ((rtp->resp == resp) && !power) { 00997 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00998 f->samples = rtp->dtmfsamples * (rtp_get_rate(f->subclass) / 1000); 00999 rtp->resp = 0; 01000 } else if (rtp->resp == resp) 01001 rtp->dtmfsamples += 20 * (rtp_get_rate(f->subclass) / 1000); 01002 rtp->dtmf_timeout = dtmftimeout; 01003 return f; 01004 }
| 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 1018 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().
01019 { 01020 unsigned int event; 01021 unsigned int event_end; 01022 unsigned int samples; 01023 char resp = 0; 01024 struct ast_frame *f = NULL; 01025 01026 /* Figure out event, event end, and samples */ 01027 event = ntohl(*((unsigned int *)(data))); 01028 event >>= 24; 01029 event_end = ntohl(*((unsigned int *)(data))); 01030 event_end <<= 8; 01031 event_end >>= 24; 01032 samples = ntohl(*((unsigned int *)(data))); 01033 samples &= 0xFFFF; 01034 01035 /* Print out debug if turned on */ 01036 if (rtpdebug || option_debug > 2) 01037 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 01038 01039 /* Figure out what digit was pressed */ 01040 if (event < 10) { 01041 resp = '0' + event; 01042 } else if (event < 11) { 01043 resp = '*'; 01044 } else if (event < 12) { 01045 resp = '#'; 01046 } else if (event < 16) { 01047 resp = 'A' + (event - 12); 01048 } else if (event < 17) { /* Event 16: Hook flash */ 01049 resp = 'X'; 01050 } else { 01051 /* Not a supported event */ 01052 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 01053 return &ast_null_frame; 01054 } 01055 01056 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 01057 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 01058 rtp->resp = resp; 01059 rtp->dtmf_timeout = 0; 01060 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01061 f->len = 0; 01062 rtp->lastevent = timestamp; 01063 } 01064 } else { 01065 /* The duration parameter measures the complete 01066 duration of the event (from the beginning) - RFC2833. 01067 Account for the fact that duration is only 16 bits long 01068 (about 8 seconds at 8000 Hz) and can wrap is digit 01069 is hold for too long. */ 01070 unsigned int new_duration = rtp->dtmf_duration; 01071 unsigned int last_duration = new_duration & 0xFFFF; 01072 01073 if (last_duration > 64000 && samples < last_duration) 01074 new_duration += 0xFFFF + 1; 01075 new_duration = (new_duration & ~0xFFFF) | samples; 01076 01077 if (event_end & 0x80) { 01078 /* End event */ 01079 if ((rtp->lastevent != seqno) && rtp->resp) { 01080 rtp->dtmf_duration = new_duration; 01081 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01082 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01083 rtp->resp = 0; 01084 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01085 } 01086 } else { 01087 /* Begin/continuation */ 01088 01089 if (rtp->resp && rtp->resp != resp) { 01090 /* Another digit already began. End it */ 01091 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01092 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0)); 01093 rtp->resp = 0; 01094 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01095 } 01096 01097 01098 if (rtp->resp) { 01099 /* Digit continues */ 01100 rtp->dtmf_duration = new_duration; 01101 } else { 01102 /* New digit began */ 01103 rtp->resp = resp; 01104 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 01105 rtp->dtmf_duration = samples; 01106 } 01107 01108 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout; 01109 } 01110 01111 rtp->lastevent = seqno; 01112 } 01113 01114 rtp->dtmfsamples = samples; 01115 01116 return f; 01117 }
| 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 1125 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().
01126 { 01127 struct ast_frame *f = NULL; 01128 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 01129 totally help us out becuase we don't have an engine to keep it going and we are not 01130 guaranteed to have it every 20ms or anything */ 01131 if (rtpdebug) 01132 ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 01133 01134 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 01135 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 01136 ast_inet_ntoa(rtp->them.sin_addr)); 01137 ast_set_flag(rtp, FLAG_3389_WARNING); 01138 } 01139 01140 /* Must have at least one byte */ 01141 if (!len) 01142 return NULL; 01143 if (len < 24) { 01144 rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET; 01145 rtp->f.datalen = len - 1; 01146 rtp->f.offset = AST_FRIENDLY_OFFSET; 01147 memcpy(rtp->f.data.ptr, data + 1, len - 1); 01148 } else { 01149 rtp->f.data.ptr = NULL; 01150 rtp->f.offset = 0; 01151 rtp->f.datalen = 0; 01152 } 01153 rtp->f.frametype = AST_FRAME_CNG; 01154 rtp->f.subclass = data[0] & 0x7f; 01155 rtp->f.datalen = len - 1; 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 4989 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 4906 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().
04906 { 04907 unsigned char *data = red->t140red.data.ptr; 04908 int len = 0; 04909 int i; 04910 04911 /* replace most aged generation */ 04912 if (red->len[0]) { 04913 for (i = 1; i < red->num_gen+1; i++) 04914 len += red->len[i]; 04915 04916 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 04917 } 04918 04919 /* Store length of each generation and primary data length*/ 04920 for (i = 0; i < red->num_gen; i++) 04921 red->len[i] = red->len[i+1]; 04922 red->len[i] = red->t140.datalen; 04923 04924 /* write each generation length in red header */ 04925 len = red->hdrlen; 04926 for (i = 0; i < red->num_gen; i++) 04927 len += data[i*4+3] = red->len[i]; 04928 04929 /* add primary data to buffer */ 04930 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 04931 red->t140red.datalen = len + red->t140.datalen; 04932 04933 /* no primary data and no generations to send */ 04934 if (len == red->hdrlen && !red->t140.datalen) 04935 return NULL; 04936 04937 /* reset t.140 buffer */ 04938 red->t140.datalen = 0; 04939 04940 return &red->t140red; 04941 }
| static int red_write | ( | const void * | data | ) | [static] |
Write t140 redundacy frame.
| data | primary data to be buffered |
Definition at line 4894 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 914 of file rtp.c.
References rtcpdebugaddr.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00915 { 00916 if (rtcpdebug == 0) 00917 return 0; 00918 if (rtcpdebugaddr.sin_addr.s_addr) { 00919 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00920 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00921 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00922 return 0; 00923 } 00924 return 1; 00925 }
| static char* rtcp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 4529 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().
04530 { 04531 struct hostent *hp; 04532 struct ast_hostent ahp; 04533 int port = 0; 04534 char *p, *arg; 04535 04536 arg = a->argv[3]; 04537 p = strstr(arg, ":"); 04538 if (p) { 04539 *p = '\0'; 04540 p++; 04541 port = atoi(p); 04542 } 04543 hp = ast_gethostbyname(arg, &ahp); 04544 if (hp == NULL) { 04545 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04546 return CLI_FAILURE; 04547 } 04548 rtcpdebugaddr.sin_family = AF_INET; 04549 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 04550 rtcpdebugaddr.sin_port = htons(port); 04551 if (port == 0) 04552 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 04553 else 04554 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 04555 rtcpdebug = 1; 04556 return CLI_SUCCESS; 04557 }
| static void rtp_bridge_lock | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 831 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().
00832 { 00833 #ifdef P2P_INTENSE 00834 ast_mutex_lock(&rtp->bridge_lock); 00835 #endif 00836 return; 00837 }
| static void rtp_bridge_unlock | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 839 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().
00840 { 00841 #ifdef P2P_INTENSE 00842 ast_mutex_unlock(&rtp->bridge_lock); 00843 #endif 00844 return; 00845 }
| static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 901 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().
00902 { 00903 if (rtpdebug == 0) 00904 return 0; 00905 if (rtpdebugaddr.sin_addr.s_addr) { 00906 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00907 && (rtpdebugaddr.sin_port != addr->sin_port)) 00908 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00909 return 0; 00910 } 00911 return 1; 00912 }
| static char* rtp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [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 arg = a->argv[3]; 04507 p = strstr(arg, ":"); 04508 if (p) { 04509 *p = '\0'; 04510 p++; 04511 port = atoi(p); 04512 } 04513 hp = ast_gethostbyname(arg, &ahp); 04514 if (hp == NULL) { 04515 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04516 return CLI_FAILURE; 04517 } 04518 rtpdebugaddr.sin_family = AF_INET; 04519 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 04520 rtpdebugaddr.sin_port = htons(port); 04521 if (port == 0) 04522 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 04523 else 04524 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 04525 rtpdebug = 1; 04526 return CLI_SUCCESS; 04527 }
| static int rtp_get_rate | ( | int | subclass | ) | [static] |
Definition at line 735 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().
00736 { 00737 return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass); 00738 }
| 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 4950 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().
04951 { 04952 struct rtp_red *r; 04953 int x; 04954 04955 if (!(r = ast_calloc(1, sizeof(struct rtp_red)))) 04956 return -1; 04957 04958 r->t140.frametype = AST_FRAME_TEXT; 04959 r->t140.subclass = AST_FORMAT_T140RED; 04960 r->t140.data.ptr = &r->buf_data; 04961 04962 r->t140.ts = 0; 04963 r->t140red = r->t140; 04964 r->t140red.data.ptr = &r->t140red_data; 04965 r->t140red.datalen = 0; 04966 r->ti = ti; 04967 r->num_gen = num_gen; 04968 r->hdrlen = num_gen * 4 + 1; 04969 r->prev_ts = 0; 04970 04971 for (x = 0; x < num_gen; x++) { 04972 r->pt[x] = red_data_pt[x]; 04973 r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 04974 r->t140red_data[x*4] = r->pt[x]; 04975 } 04976 r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */ 04977 r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp); 04978 rtp->red = r; 04979 04980 r->t140.datalen = 0; 04981 04982 return 0; 04983 }
| static int rtp_socket | ( | const char * | type | ) | [static] |
Open RTP or RTCP socket for a session. Print a message on failure.
Definition at line 2439 of file rtp.c.
References ast_log(), errno, LOG_WARNING, and s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
02440 { 02441 int s = socket(AF_INET, SOCK_DGRAM, 0); 02442 if (s < 0) { 02443 if (type == NULL) 02444 type = "RTP/RTCP"; 02445 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno)); 02446 } else { 02447 long flags = fcntl(s, F_GETFL); 02448 fcntl(s, F_SETFL, flags | O_NONBLOCK); 02449 #ifdef SO_NO_CHECK 02450 if (nochecksums) 02451 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 02452 #endif 02453 } 02454 return s; 02455 }
| 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 876 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().
00877 { 00878 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00879 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00880 ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00881 rtp->resp = 0; 00882 rtp->dtmfsamples = 0; 00883 return &ast_null_frame; 00884 } 00885 ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00886 if (rtp->resp == 'X') { 00887 rtp->f.frametype = AST_FRAME_CONTROL; 00888 rtp->f.subclass = AST_CONTROL_FLASH; 00889 } else { 00890 rtp->f.frametype = type; 00891 rtp->f.subclass = rtp->resp; 00892 } 00893 rtp->f.datalen = 0; 00894 rtp->f.samples = 0; 00895 rtp->f.mallocd = 0; 00896 rtp->f.src = "RTP"; 00897 return &rtp->f; 00898 00899 }
| static double stddev_compute | ( | double | stddev, | |
| double | sample, | |||
| double | normdev, | |||
| double | normdev_curent, | |||
| unsigned int | sample_count | |||
| ) | [static] |
Definition at line 856 of file rtp.c.
References SQUARE.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().
00857 { 00858 /* 00859 for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf 00860 return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1)); 00861 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 00862 optimized formula 00863 */ 00864 #define SQUARE(x) ((x) * (x)) 00865 00866 stddev = sample_count * stddev; 00867 sample_count++; 00868 00869 return stddev + 00870 ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) + 00871 ( SQUARE(sample - normdev_curent) / sample_count ); 00872 00873 #undef SQUARE 00874 }
| static const char* stun_attr2str | ( | int | msg | ) | [static] |
helper function to print attribute names
Definition at line 396 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().
00397 { 00398 switch (msg) { 00399 case STUN_MAPPED_ADDRESS: 00400 return "Mapped Address"; 00401 case STUN_RESPONSE_ADDRESS: 00402 return "Response Address"; 00403 case STUN_CHANGE_REQUEST: 00404 return "Change Request"; 00405 case STUN_SOURCE_ADDRESS: 00406 return "Source Address"; 00407 case STUN_CHANGED_ADDRESS: 00408 return "Changed Address"; 00409 case STUN_USERNAME: 00410 return "Username"; 00411 case STUN_PASSWORD: 00412 return "Password"; 00413 case STUN_MESSAGE_INTEGRITY: 00414 return "Message Integrity"; 00415 case STUN_ERROR_CODE: 00416 return "Error Code"; 00417 case STUN_UNKNOWN_ATTRIBUTES: 00418 return "Unknown Attributes"; 00419 case STUN_REFLECTED_FROM: 00420 return "Reflected From"; 00421 } 00422 return "Non-RFC3489 Attribute"; 00423 }
| 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 613 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().
00614 { 00615 struct stun_addr *addr = (struct stun_addr *)(attr + 1); 00616 struct sockaddr_in *sa = (struct sockaddr_in *)arg; 00617 00618 if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8) 00619 return 1; /* not us. */ 00620 sa->sin_port = addr->port; 00621 sa->sin_addr.s_addr = addr->addr; 00622 return 0; 00623 }
| 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 515 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().
00517 { 00518 struct stun_header *hdr = (struct stun_header *)data; 00519 struct stun_attr *attr; 00520 struct stun_state st; 00521 int ret = STUN_IGNORE; 00522 int x; 00523 00524 /* On entry, 'len' is the length of the udp payload. After the 00525 * initial checks it becomes the size of unprocessed options, 00526 * while 'data' is advanced accordingly. 00527 */ 00528 if (len < sizeof(struct stun_header)) { 00529 ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header)); 00530 return -1; 00531 } 00532 len -= sizeof(struct stun_header); 00533 data += sizeof(struct stun_header); 00534 x = ntohs(hdr->msglen); /* len as advertised in the message */ 00535 if (stundebug) 00536 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x); 00537 if (x > len) { 00538 ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len); 00539 } else 00540 len = x; 00541 memset(&st, 0, sizeof(st)); 00542 while (len) { 00543 if (len < sizeof(struct stun_attr)) { 00544 ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr)); 00545 break; 00546 } 00547 attr = (struct stun_attr *)data; 00548 /* compute total attribute length */ 00549 x = ntohs(attr->len) + sizeof(struct stun_attr); 00550 if (x > len) { 00551 ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len); 00552 break; 00553 } 00554 if (stun_cb) 00555 stun_cb(attr, arg); 00556 if (stun_process_attr(&st, attr)) { 00557 ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00558 break; 00559 } 00560 /* Clear attribute id: in case previous entry was a string, 00561 * this will act as the terminator for the string. 00562 */ 00563 attr->attr = 0; 00564 data += x; 00565 len -= x; 00566 } 00567 /* Null terminate any string. 00568 * XXX NOTE, we write past the size of the buffer passed by the 00569 * caller, so this is potentially dangerous. The only thing that 00570 * saves us is that usually we read the incoming message in a 00571 * much larger buffer in the struct ast_rtp 00572 */ 00573 *data = '\0'; 00574 00575 /* Now prepare to generate a reply, which at the moment is done 00576 * only for properly formed (len == 0) STUN_BINDREQ messages. 00577 */ 00578 if (len == 0) { 00579 unsigned char respdata[1024]; 00580 struct stun_header *resp = (struct stun_header *)respdata; 00581 int resplen = 0; /* len excluding header */ 00582 int respleft = sizeof(respdata) - sizeof(struct stun_header); 00583 00584 resp->id = hdr->id; 00585 resp->msgtype = 0; 00586 resp->msglen = 0; 00587 attr = (struct stun_attr *)resp->ies; 00588 switch (ntohs(hdr->msgtype)) { 00589 case STUN_BINDREQ: 00590 if (stundebug) 00591 ast_verbose("STUN Bind Request, username: %s\n", 00592 st.username ? st.username : "<none>"); 00593 if (st.username) 00594 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00595 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00596 resp->msglen = htons(resplen); 00597 resp->msgtype = htons(STUN_BINDRESP); 00598 stun_send(s, src, resp); 00599 ret = STUN_ACCEPT; 00600 break; 00601 default: 00602 if (stundebug) 00603 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00604 } 00605 } 00606 return ret; 00607 }
| static const char* stun_msg2str | ( | int | msg | ) | [static] |
helper function to print message names
Definition at line 376 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00377 { 00378 switch (msg) { 00379 case STUN_BINDREQ: 00380 return "Binding Request"; 00381 case STUN_BINDRESP: 00382 return "Binding Response"; 00383 case STUN_BINDERR: 00384 return "Binding Error Response"; 00385 case STUN_SECREQ: 00386 return "Shared Secret Request"; 00387 case STUN_SECRESP: 00388 return "Shared Secret Response"; 00389 case STUN_SECERR: 00390 return "Shared Secret Error Response"; 00391 } 00392 return "Non-RFC3489 Message"; 00393 }
| static int stun_process_attr | ( | struct stun_state * | state, | |
| struct stun_attr * | attr | |||
| ) | [static] |
Definition at line 431 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().
00432 { 00433 if (stundebug) 00434 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00435 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00436 switch (ntohs(attr->attr)) { 00437 case STUN_USERNAME: 00438 state->username = (const char *) (attr->value); 00439 break; 00440 case STUN_PASSWORD: 00441 state->password = (const char *) (attr->value); 00442 break; 00443 default: 00444 if (stundebug) 00445 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00446 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00447 } 00448 return 0; 00449 }
| static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
helper function to generate a random request id
Definition at line 492 of file rtp.c.
References ast_random(), stun_trans_id::id, and stun_header::id.
Referenced by ast_stun_request().
00493 { 00494 int x; 00495 for (x = 0; x < 4; x++) 00496 req->id.id[x] = ast_random(); 00497 }
| static int stun_send | ( | int | s, | |
| struct sockaddr_in * | dst, | |||
| struct stun_header * | resp | |||
| ) | [static] |
wrapper to send an STUN message
Definition at line 485 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 713 of file rtp.c.
References sec.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00714 { 00715 unsigned int sec, usec, frac; 00716 sec = when.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00717 usec = when.tv_usec; 00718 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00719 *msw = sec; 00720 *lsw = frac; 00721 }
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 1919 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 1921 of file rtp.c.
Referenced by ast_rtp_set_rtpmap_type().
| char* type |
Definition at line 1920 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), aji_handle_presence(), amixer_max(), ast_call_forward(), 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