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