#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include "asterisk/rtp.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 | rtpPayloadType |
Structure representing a RTP session.The value of each payload format mapping:. 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_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 | 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 int | __ast_rtp_reload (int reload) |
static void | append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, 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. | |
ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
int | ast_rtcp_send_h261fur (void *data) |
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP. | |
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) |
The RTP bridge. | |
int | ast_rtp_codec_getformat (int pt) |
get format from predefined dynamic payload format | |
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) |
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) |
char * | ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual) |
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):. | |
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) |
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) |
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 an RTP channel client. | |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
Unregister an RTP channel client. | |
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. | |
ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
int | ast_rtp_reload (void) |
void | ast_rtp_reset (struct ast_rtp *rtp) |
int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
generate comfort noice (CNG) | |
int | ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit) |
Send begin frames for DTMF. | |
static int | ast_rtp_senddigit_continuation (struct ast_rtp *rtp) |
Send continuation frame for DTMF. | |
int | ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit) |
Send end packets for DTMF. | |
void | ast_rtp_set_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt) |
set potential alternate source for RTP media | |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
Activate payload type. | |
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) |
Initiate payload type to a known MIME media type for a codec. | |
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_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 tos, int cos, 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 STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request(). | |
void | ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt) |
clear payload 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. | |
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 *tv, 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 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. | |
static int | rtcp_debug_test_addr (struct sockaddr_in *addr) |
static char * | rtcp_do_debug_ip (struct ast_cli_args *a) |
static void | rtp_bridge_lock (struct ast_rtp *rtp) |
static void | rtp_bridge_unlock (struct ast_rtp *rtp) |
static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
static char * | rtp_do_debug_ip (struct ast_cli_args *a) |
static int | rtp_socket (const char *type) |
Open RTP or RTCP socket for a session. Print a message on failure. | |
static int | rtpread (int *id, int fd, short events, void *cbdata) |
static struct ast_frame * | send_dtmf (struct ast_rtp *rtp, enum ast_frame_type type) |
static 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 = { .handler = handle_cli_rtcp_debug_deprecated , .summary = "Enable/Disable RTCP debugging" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_rtcp_stats_deprecated = { .handler = handle_cli_rtcp_stats_deprecated , .summary = "Enable/Disable RTCP stats" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_rtp [] |
static struct ast_cli_entry | cli_rtp_debug_deprecated = { .handler = handle_cli_rtp_debug_deprecated , .summary = "Enable/Disable RTP debugging" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_stun_debug_deprecated = { .handler = handle_cli_stun_debug_deprecated , .summary = "Enable/Disable STUN debugging" ,__VA_ARGS__ } |
static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
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) |
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 201 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 197 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 194 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 195 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 196 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 198 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 49 of file rtp.c.
Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp().
#define RTCP_DEFAULT_INTERVALMS 5000 |
#define RTCP_MAX_INTERVALMS 60000 |
Max milli-seconds between RTCP reports we send
Definition at line 54 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 53 of file rtp.c.
Referenced by __ast_rtp_reload().
#define RTCP_PT_BYE 203 |
#define RTCP_PT_FUR 192 |
Definition at line 56 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 59 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 51 of file rtp.c.
Referenced by ast_rtp_read().
#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 303 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 313 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 318 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 83 of file rtp.c.
00083 { 00084 STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */ 00085 STRICT_RTP_LEARN, /*! Accept next packet as source */ 00086 STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */ 00087 };
static int __ast_rtp_reload | ( | int | reload | ) | [static] |
Definition at line 4296 of file rtp.c.
References ast_config_destroy(), ast_config_load, 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().
04297 { 04298 struct ast_config *cfg; 04299 const char *s; 04300 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04301 04302 if ((cfg = ast_config_load("rtp.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 04303 return 0; 04304 04305 rtpstart = 5000; 04306 rtpend = 31000; 04307 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04308 strictrtp = STRICT_RTP_OPEN; 04309 if (cfg) { 04310 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 04311 rtpstart = atoi(s); 04312 if (rtpstart < 1024) 04313 rtpstart = 1024; 04314 if (rtpstart > 65535) 04315 rtpstart = 65535; 04316 } 04317 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 04318 rtpend = atoi(s); 04319 if (rtpend < 1024) 04320 rtpend = 1024; 04321 if (rtpend > 65535) 04322 rtpend = 65535; 04323 } 04324 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 04325 rtcpinterval = atoi(s); 04326 if (rtcpinterval == 0) 04327 rtcpinterval = 0; /* Just so we're clear... it's zero */ 04328 if (rtcpinterval < RTCP_MIN_INTERVALMS) 04329 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 04330 if (rtcpinterval > RTCP_MAX_INTERVALMS) 04331 rtcpinterval = RTCP_MAX_INTERVALMS; 04332 } 04333 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 04334 #ifdef SO_NO_CHECK 04335 if (ast_false(s)) 04336 nochecksums = 1; 04337 else 04338 nochecksums = 0; 04339 #else 04340 if (ast_false(s)) 04341 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 04342 #endif 04343 } 04344 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 04345 dtmftimeout = atoi(s); 04346 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) { 04347 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 04348 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 04349 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 04350 }; 04351 } 04352 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) { 04353 strictrtp = ast_true(s); 04354 } 04355 ast_config_destroy(cfg); 04356 } 04357 if (rtpstart >= rtpend) { 04358 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 04359 rtpstart = 5000; 04360 rtpend = 31000; 04361 } 04362 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 04363 return 0; 04364 }
static void append_attr_address | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
struct sockaddr_in * | sin, | |||
int * | len, | |||
int * | left | |||
) | [static] |
append an address to an STUN message
Definition at line 416 of file rtp.c.
References stun_addr::addr.
Referenced by stun_handle_packet().
00417 { 00418 int size = sizeof(**attr) + 8; 00419 struct stun_addr *addr; 00420 if (*left > size) { 00421 (*attr)->attr = htons(attrval); 00422 (*attr)->len = htons(8); 00423 addr = (struct stun_addr *)((*attr)->value); 00424 addr->unused = 0; 00425 addr->family = 0x01; 00426 addr->port = sin->sin_port; 00427 addr->addr = sin->sin_addr.s_addr; 00428 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00429 *len += size; 00430 *left -= size; 00431 } 00432 }
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 402 of file rtp.c.
Referenced by ast_stun_request(), and stun_handle_packet().
00403 { 00404 int size = sizeof(**attr) + strlen(s); 00405 if (*left > size) { 00406 (*attr)->attr = htons(attrval); 00407 (*attr)->len = htons(strlen(s)); 00408 memcpy((*attr)->value, s, strlen(s)); 00409 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00410 *len += size; 00411 *left -= size; 00412 } 00413 }
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 685 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00686 { 00687 unsigned int interval; 00688 /*! \todo XXX Do a more reasonable calculation on this one 00689 * Look in RFC 3550 Section A.7 for an example*/ 00690 interval = rtcpinterval; 00691 return interval; 00692 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 678 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] |
Initialize a new RTCP session.
Definition at line 2241 of file rtp.c.
References ast_calloc, ast_free, rtp_socket(), and ast_rtcp::s.
Referenced by ast_rtp_new_with_bindaddr().
02242 { 02243 struct ast_rtcp *rtcp; 02244 02245 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 02246 return NULL; 02247 rtcp->s = rtp_socket("RTCP"); 02248 rtcp->us.sin_family = AF_INET; 02249 rtcp->them.sin_family = AF_INET; 02250 rtcp->schedid = -1; 02251 02252 if (rtcp->s < 0) { 02253 ast_free(rtcp); 02254 return NULL; 02255 } 02256 02257 return rtcp; 02258 }
Definition at line 1090 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, f, ast_rtp::f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, 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().
01091 { 01092 socklen_t len; 01093 int position, i, packetwords; 01094 int res; 01095 struct sockaddr_in sin; 01096 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 01097 unsigned int *rtcpheader; 01098 int pt; 01099 struct timeval now; 01100 unsigned int length; 01101 int rc; 01102 double rttsec; 01103 uint64_t rtt = 0; 01104 unsigned int dlsr; 01105 unsigned int lsr; 01106 unsigned int msw; 01107 unsigned int lsw; 01108 unsigned int comp; 01109 struct ast_frame *f = &ast_null_frame; 01110 01111 if (!rtp || !rtp->rtcp) 01112 return &ast_null_frame; 01113 01114 len = sizeof(sin); 01115 01116 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 01117 0, (struct sockaddr *)&sin, &len); 01118 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 01119 01120 if (res < 0) { 01121 ast_assert(errno != EBADF); 01122 if (errno != EAGAIN) { 01123 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 01124 return NULL; 01125 } 01126 return &ast_null_frame; 01127 } 01128 01129 packetwords = res / 4; 01130 01131 if (rtp->nat) { 01132 /* Send to whoever sent to us */ 01133 if (((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01134 (rtp->rtcp->them.sin_port != sin.sin_port)) && 01135 ((rtp->rtcp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) || 01136 (rtp->rtcp->altthem.sin_port != sin.sin_port))) { 01137 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01138 if (option_debug || rtpdebug) 01139 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)); 01140 } 01141 } 01142 01143 ast_debug(1, "Got RTCP report of %d bytes\n", res); 01144 01145 /* Process a compound packet */ 01146 position = 0; 01147 while (position < packetwords) { 01148 i = position; 01149 length = ntohl(rtcpheader[i]); 01150 pt = (length & 0xff0000) >> 16; 01151 rc = (length & 0x1f000000) >> 24; 01152 length &= 0xffff; 01153 01154 if ((i + length) > packetwords) { 01155 if (option_debug || rtpdebug) 01156 ast_log(LOG_DEBUG, "RTCP Read too short\n"); 01157 return &ast_null_frame; 01158 } 01159 01160 if (rtcp_debug_test_addr(&sin)) { 01161 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 01162 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 01163 ast_verbose("Reception reports: %d\n", rc); 01164 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 01165 } 01166 01167 i += 2; /* Advance past header and ssrc */ 01168 01169 switch (pt) { 01170 case RTCP_PT_SR: 01171 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 01172 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 01173 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 01174 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 01175 01176 if (rtcp_debug_test_addr(&sin)) { 01177 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 01178 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 01179 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 01180 } 01181 i += 5; 01182 if (rc < 1) 01183 break; 01184 /* Intentional fall through */ 01185 case RTCP_PT_RR: 01186 /* Don't handle multiple reception reports (rc > 1) yet */ 01187 /* Calculate RTT per RFC */ 01188 gettimeofday(&now, NULL); 01189 timeval2ntp(now, &msw, &lsw); 01190 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 01191 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 01192 lsr = ntohl(rtcpheader[i + 4]); 01193 dlsr = ntohl(rtcpheader[i + 5]); 01194 rtt = comp - lsr - dlsr; 01195 01196 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 01197 sess->ee_delay = (eedelay * 1000) / 65536; */ 01198 if (rtt < 4294) { 01199 rtt = (rtt * 1000000) >> 16; 01200 } else { 01201 rtt = (rtt * 1000) >> 16; 01202 rtt *= 1000; 01203 } 01204 rtt = rtt / 1000.; 01205 rttsec = rtt / 1000.; 01206 01207 if (comp - dlsr >= lsr) { 01208 rtp->rtcp->accumulated_transit += rttsec; 01209 rtp->rtcp->rtt = rttsec; 01210 if (rtp->rtcp->maxrtt<rttsec) 01211 rtp->rtcp->maxrtt = rttsec; 01212 if (rtp->rtcp->minrtt>rttsec) 01213 rtp->rtcp->minrtt = rttsec; 01214 } else if (rtcp_debug_test_addr(&sin)) { 01215 ast_verbose("Internal RTCP NTP clock skew detected: " 01216 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 01217 "diff=%d\n", 01218 lsr, comp, dlsr, dlsr / 65536, 01219 (dlsr % 65536) * 1000 / 65536, 01220 dlsr - (comp - lsr)); 01221 } 01222 } 01223 01224 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 01225 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 01226 if (rtcp_debug_test_addr(&sin)) { 01227 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 01228 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 01229 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 01230 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 01231 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 01232 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 01233 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 01234 if (rtt) 01235 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 01236 } 01237 if (rtt) { 01238 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n" 01239 "PT: %d(%s)\r\n" 01240 "ReceptionReports: %d\r\n" 01241 "SenderSSRC: %u\r\n" 01242 "FractionLost: %ld\r\n" 01243 "PacketsLost: %d\r\n" 01244 "HighestSequence: %ld\r\n" 01245 "SequenceNumberCycles: %ld\r\n" 01246 "IAJitter: %u\r\n" 01247 "LastSR: %lu.%010lu\r\n" 01248 "DLSR: %4.4f(sec)\r\n" 01249 "RTT: %llu(sec)\r\n", 01250 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 01251 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01252 rc, 01253 rtcpheader[i + 1], 01254 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01255 rtp->rtcp->reported_lost, 01256 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01257 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01258 rtp->rtcp->reported_jitter, 01259 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01260 ntohl(rtcpheader[i + 5])/65536.0, 01261 (unsigned long long)rtt); 01262 } else { 01263 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n" 01264 "PT: %d(%s)\r\n" 01265 "ReceptionReports: %d\r\n" 01266 "SenderSSRC: %u\r\n" 01267 "FractionLost: %ld\r\n" 01268 "PacketsLost: %d\r\n" 01269 "HighestSequence: %ld\r\n" 01270 "SequenceNumberCycles: %ld\r\n" 01271 "IAJitter: %u\r\n" 01272 "LastSR: %lu.%010lu\r\n" 01273 "DLSR: %4.4f(sec)\r\n", 01274 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 01275 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01276 rc, 01277 rtcpheader[i + 1], 01278 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01279 rtp->rtcp->reported_lost, 01280 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01281 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01282 rtp->rtcp->reported_jitter, 01283 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, 01284 ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01285 ntohl(rtcpheader[i + 5])/65536.0); 01286 } 01287 break; 01288 case RTCP_PT_FUR: 01289 if (rtcp_debug_test_addr(&sin)) 01290 ast_verbose("Received an RTCP Fast Update Request\n"); 01291 rtp->f.frametype = AST_FRAME_CONTROL; 01292 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 01293 rtp->f.datalen = 0; 01294 rtp->f.samples = 0; 01295 rtp->f.mallocd = 0; 01296 rtp->f.src = "RTP"; 01297 f = &rtp->f; 01298 break; 01299 case RTCP_PT_SDES: 01300 if (rtcp_debug_test_addr(&sin)) 01301 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01302 break; 01303 case RTCP_PT_BYE: 01304 if (rtcp_debug_test_addr(&sin)) 01305 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01306 break; 01307 default: 01308 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)); 01309 break; 01310 } 01311 position += (length + 1); 01312 } 01313 01314 return f; 01315 }
int ast_rtcp_send_h261fur | ( | void * | data | ) |
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
Definition at line 2770 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02771 { 02772 struct ast_rtp *rtp = data; 02773 int res; 02774 02775 rtp->rtcp->sendfur = 1; 02776 res = ast_rtcp_write(data); 02777 02778 return res; 02779 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 3010 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().
03011 { 03012 struct ast_rtp *rtp = (struct ast_rtp *)data; 03013 int res; 03014 03015 if (!rtp || !rtp->rtcp) 03016 return 0; 03017 03018 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 03019 res = ast_rtcp_write_sr(data); 03020 else 03021 res = ast_rtcp_write_rr(data); 03022 03023 return res; 03024 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recipient's report.
Definition at line 2915 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::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::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, and timersub().
Referenced by ast_rtcp_write().
02916 { 02917 struct ast_rtp *rtp = (struct ast_rtp *)data; 02918 int res; 02919 int len = 32; 02920 unsigned int lost; 02921 unsigned int extended; 02922 unsigned int expected; 02923 unsigned int expected_interval; 02924 unsigned int received_interval; 02925 int lost_interval; 02926 struct timeval now; 02927 unsigned int *rtcpheader; 02928 char bdata[1024]; 02929 struct timeval dlsr; 02930 int fraction; 02931 02932 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02933 return 0; 02934 02935 if (!rtp->rtcp->them.sin_addr.s_addr) { 02936 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02937 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02938 return 0; 02939 } 02940 02941 extended = rtp->cycles + rtp->lastrxseqno; 02942 expected = extended - rtp->seedrxseqno + 1; 02943 lost = expected - rtp->rxcount; 02944 expected_interval = expected - rtp->rtcp->expected_prior; 02945 rtp->rtcp->expected_prior = expected; 02946 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02947 rtp->rtcp->received_prior = rtp->rxcount; 02948 lost_interval = expected_interval - received_interval; 02949 if (expected_interval == 0 || lost_interval <= 0) 02950 fraction = 0; 02951 else 02952 fraction = (lost_interval << 8) / expected_interval; 02953 gettimeofday(&now, NULL); 02954 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02955 rtcpheader = (unsigned int *)bdata; 02956 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02957 rtcpheader[1] = htonl(rtp->ssrc); 02958 rtcpheader[2] = htonl(rtp->themssrc); 02959 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02960 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02961 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02962 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02963 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02964 02965 if (rtp->rtcp->sendfur) { 02966 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02967 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02968 len += 8; 02969 rtp->rtcp->sendfur = 0; 02970 } 02971 02972 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02973 it can change mid call, and SDES can't) */ 02974 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02975 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02976 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02977 len += 12; 02978 02979 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02980 02981 if (res < 0) { 02982 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02983 /* Remove the scheduler */ 02984 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02985 return 0; 02986 } 02987 02988 rtp->rtcp->rr_count++; 02989 02990 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02991 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02992 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02993 " IA jitter: %.4f\n" 02994 " Their last SR: %u\n" 02995 " DLSR: %4.4f (sec)\n\n", 02996 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02997 ntohs(rtp->rtcp->them.sin_port), 02998 rtp->ssrc, rtp->themssrc, fraction, lost, 02999 rtp->rxjitter, 03000 rtp->rtcp->themrxlsr, 03001 (double)(ntohl(rtcpheader[7])/65536.0)); 03002 } 03003 03004 return res; 03005 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2782 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().
02783 { 02784 struct ast_rtp *rtp = (struct ast_rtp *)data; 02785 int res; 02786 int len = 0; 02787 struct timeval now; 02788 unsigned int now_lsw; 02789 unsigned int now_msw; 02790 unsigned int *rtcpheader; 02791 unsigned int lost; 02792 unsigned int extended; 02793 unsigned int expected; 02794 unsigned int expected_interval; 02795 unsigned int received_interval; 02796 int lost_interval; 02797 int fraction; 02798 struct timeval dlsr; 02799 char bdata[512]; 02800 02801 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02802 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02803 return 0; 02804 02805 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02806 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02807 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02808 return 0; 02809 } 02810 02811 gettimeofday(&now, NULL); 02812 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02813 rtcpheader = (unsigned int *)bdata; 02814 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02815 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02816 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02817 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02818 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02819 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02820 len += 28; 02821 02822 extended = rtp->cycles + rtp->lastrxseqno; 02823 expected = extended - rtp->seedrxseqno + 1; 02824 if (rtp->rxcount > expected) 02825 expected += rtp->rxcount - expected; 02826 lost = expected - rtp->rxcount; 02827 expected_interval = expected - rtp->rtcp->expected_prior; 02828 rtp->rtcp->expected_prior = expected; 02829 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02830 rtp->rtcp->received_prior = rtp->rxcount; 02831 lost_interval = expected_interval - received_interval; 02832 if (expected_interval == 0 || lost_interval <= 0) 02833 fraction = 0; 02834 else 02835 fraction = (lost_interval << 8) / expected_interval; 02836 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02837 rtcpheader[7] = htonl(rtp->themssrc); 02838 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02839 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02840 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02841 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02842 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02843 len += 24; 02844 02845 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02846 02847 if (rtp->rtcp->sendfur) { 02848 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02849 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02850 len += 8; 02851 rtp->rtcp->sendfur = 0; 02852 } 02853 02854 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02855 /* it can change mid call, and SDES can't) */ 02856 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02857 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02858 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02859 len += 12; 02860 02861 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02862 if (res < 0) { 02863 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)); 02864 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02865 return 0; 02866 } 02867 02868 /* FIXME Don't need to get a new one */ 02869 gettimeofday(&rtp->rtcp->txlsr, NULL); 02870 rtp->rtcp->sr_count++; 02871 02872 rtp->rtcp->lastsrtxcount = rtp->txcount; 02873 02874 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02875 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02876 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02877 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02878 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02879 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02880 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02881 ast_verbose(" Report block:\n"); 02882 ast_verbose(" Fraction lost: %u\n", fraction); 02883 ast_verbose(" Cumulative loss: %u\n", lost); 02884 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02885 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02886 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02887 } 02888 manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n" 02889 "OurSSRC: %u\r\n" 02890 "SentNTP: %u.%010u\r\n" 02891 "SentRTP: %u\r\n" 02892 "SentPackets: %u\r\n" 02893 "SentOctets: %u\r\n" 02894 "ReportBlock:\r\n" 02895 "FractionLost: %u\r\n" 02896 "CumulativeLoss: %u\r\n" 02897 "IAJitter: %.4f\r\n" 02898 "TheirLastSR: %u\r\n" 02899 "DLSR: %4.4f (sec)\r\n", 02900 ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), 02901 rtp->ssrc, 02902 (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096, 02903 rtp->lastts, 02904 rtp->txcount, 02905 rtp->txoctetcount, 02906 fraction, 02907 lost, 02908 rtp->rxjitter, 02909 rtp->rtcp->themrxlsr, 02910 (double)(ntohl(rtcpheader[12])/65536.0)); 02911 return res; 02912 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 449 of file rtp.c.
Referenced by process_sdp().
00450 { 00451 return sizeof(struct ast_rtp); 00452 }
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 | |||
) |
The RTP bridge.
Definition at line 3833 of file rtp.c.
References 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.
03834 { 03835 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03836 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03837 struct ast_rtp *tp0 = NULL, *tp1 = NULL; /* Text RTP channels */ 03838 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03839 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; 03840 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; 03841 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03842 int codec0 = 0, codec1 = 0; 03843 void *pvt0 = NULL, *pvt1 = NULL; 03844 03845 /* Lock channels */ 03846 ast_channel_lock(c0); 03847 while (ast_channel_trylock(c1)) { 03848 ast_channel_unlock(c0); 03849 usleep(1); 03850 ast_channel_lock(c0); 03851 } 03852 03853 /* Ensure neither channel got hungup during lock avoidance */ 03854 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03855 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03856 ast_channel_unlock(c0); 03857 ast_channel_unlock(c1); 03858 return AST_BRIDGE_FAILED; 03859 } 03860 03861 /* Find channel driver interfaces */ 03862 if (!(pr0 = get_proto(c0))) { 03863 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03864 ast_channel_unlock(c0); 03865 ast_channel_unlock(c1); 03866 return AST_BRIDGE_FAILED; 03867 } 03868 if (!(pr1 = get_proto(c1))) { 03869 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03870 ast_channel_unlock(c0); 03871 ast_channel_unlock(c1); 03872 return AST_BRIDGE_FAILED; 03873 } 03874 03875 /* Get channel specific interface structures */ 03876 pvt0 = c0->tech_pvt; 03877 pvt1 = c1->tech_pvt; 03878 03879 /* Get audio and video interface (if native bridge is possible) */ 03880 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03881 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03882 text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03883 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03884 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03885 text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03886 03887 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03888 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03889 audio_p0_res = AST_RTP_GET_FAILED; 03890 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03891 audio_p1_res = AST_RTP_GET_FAILED; 03892 03893 /* Check if a bridge is possible (partial/native) */ 03894 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03895 /* Somebody doesn't want to play... */ 03896 ast_channel_unlock(c0); 03897 ast_channel_unlock(c1); 03898 return AST_BRIDGE_FAILED_NOWARN; 03899 } 03900 03901 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03902 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03903 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03904 audio_p0_res = AST_RTP_TRY_PARTIAL; 03905 } 03906 03907 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03908 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03909 audio_p1_res = AST_RTP_TRY_PARTIAL; 03910 } 03911 03912 /* If both sides are not using the same method of DTMF transmission 03913 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03914 * -------------------------------------------------- 03915 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03916 * |-----------|------------|-----------------------| 03917 * | Inband | False | True | 03918 * | RFC2833 | True | True | 03919 * | SIP INFO | False | False | 03920 * -------------------------------------------------- 03921 * However, if DTMF from both channels is being monitored by the core, then 03922 * we can still do packet-to-packet bridging, because passing through the 03923 * core will handle DTMF mode translation. 03924 */ 03925 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03926 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03927 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03928 ast_channel_unlock(c0); 03929 ast_channel_unlock(c1); 03930 return AST_BRIDGE_FAILED_NOWARN; 03931 } 03932 audio_p0_res = AST_RTP_TRY_PARTIAL; 03933 audio_p1_res = AST_RTP_TRY_PARTIAL; 03934 } 03935 03936 /* If we need to feed frames into the core don't do a P2P bridge */ 03937 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 03938 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 03939 ast_channel_unlock(c0); 03940 ast_channel_unlock(c1); 03941 return AST_BRIDGE_FAILED_NOWARN; 03942 } 03943 03944 /* Get codecs from both sides */ 03945 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03946 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03947 if (codec0 && codec1 && !(codec0 & codec1)) { 03948 /* Hey, we can't do native bridging if both parties speak different codecs */ 03949 ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03950 ast_channel_unlock(c0); 03951 ast_channel_unlock(c1); 03952 return AST_BRIDGE_FAILED_NOWARN; 03953 } 03954 03955 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03956 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03957 struct ast_format_list fmt0, fmt1; 03958 03959 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03960 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03961 ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03962 ast_channel_unlock(c0); 03963 ast_channel_unlock(c1); 03964 return AST_BRIDGE_FAILED_NOWARN; 03965 } 03966 /* They must also be using the same packetization */ 03967 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03968 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03969 if (fmt0.cur_ms != fmt1.cur_ms) { 03970 ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03971 ast_channel_unlock(c0); 03972 ast_channel_unlock(c1); 03973 return AST_BRIDGE_FAILED_NOWARN; 03974 } 03975 03976 ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03977 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03978 } else { 03979 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 03980 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03981 } 03982 03983 return res; 03984 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
get format from predefined dynamic payload format
Definition at line 3227 of file rtp.c.
References rtpPayloadType::code, and static_RTP_PT.
Referenced by process_sdp().
03228 { 03229 if (pt < 0 || pt > MAX_RTP_PT) 03230 return 0; /* bogus payload type */ 03231 03232 if (static_RTP_PT[pt].isAstFormat) 03233 return static_RTP_PT[pt].code; 03234 else 03235 return 0; 03236 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) |
Get codec preference.
Definition at line 3222 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
03223 { 03224 return &rtp->pref; 03225 }
void ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Set codec preference.
Definition at line 3176 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, prefs, and ast_rtp::smoother.
Referenced by __oh323_rtp_create(), check_peer_ok(), check_user_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().
03177 { 03178 struct ast_format_list current_format_old, current_format_new; 03179 03180 /* if no packets have been sent through this session yet, then 03181 * changing preferences does not require any extra work 03182 */ 03183 if (rtp->lasttxformat == 0) { 03184 rtp->pref = *prefs; 03185 return; 03186 } 03187 03188 current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 03189 03190 rtp->pref = *prefs; 03191 03192 current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat); 03193 03194 /* if the framing desired for the current format has changed, we may have to create 03195 * or adjust the smoother for this session 03196 */ 03197 if ((current_format_new.inc_ms != 0) && 03198 (current_format_new.cur_ms != current_format_old.cur_ms)) { 03199 int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms; 03200 03201 if (rtp->smoother) { 03202 ast_smoother_reconfigure(rtp->smoother, new_size); 03203 if (option_debug) { 03204 ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size); 03205 } 03206 } else { 03207 if (!(rtp->smoother = ast_smoother_new(new_size))) { 03208 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 03209 return; 03210 } 03211 if (current_format_new.flags) { 03212 ast_smoother_set_flags(rtp->smoother, current_format_new.flags); 03213 } 03214 if (option_debug) { 03215 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size); 03216 } 03217 } 03218 } 03219 03220 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Destroy RTP session
Definition at line 2529 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_rtp::s, ast_rtcp::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(), check_user_ok(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), jingle_free_pvt(), mgcp_hangup(), oh323_alloc(), sip_alloc(), skinny_hangup(), start_rtp(), unalloc_sub(), and unistim_hangup().
02530 { 02531 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02532 /*Print some info on the call here */ 02533 ast_verbose(" RTP-stats\n"); 02534 ast_verbose("* Our Receiver:\n"); 02535 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02536 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02537 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0); 02538 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02539 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02540 ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0); 02541 ast_verbose("* Our Sender:\n"); 02542 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02543 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02544 ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0); 02545 ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0); 02546 ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0); 02547 ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0); 02548 } 02549 02550 manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n" 02551 "ReceivedPackets: %u\r\n" 02552 "LostPackets: %u\r\n" 02553 "Jitter: %.4f\r\n" 02554 "Transit: %.4f\r\n" 02555 "RRCount: %u\r\n", 02556 rtp->themssrc, 02557 rtp->rxcount, 02558 rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0, 02559 rtp->rxjitter, 02560 rtp->rxtransit, 02561 rtp->rtcp ? rtp->rtcp->rr_count : 0); 02562 manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n" 02563 "SentPackets: %u\r\n" 02564 "LostPackets: %u\r\n" 02565 "Jitter: %u\r\n" 02566 "SRCount: %u\r\n" 02567 "RTT: %f\r\n", 02568 rtp->ssrc, 02569 rtp->txcount, 02570 rtp->rtcp ? rtp->rtcp->reported_lost : 0, 02571 rtp->rtcp ? rtp->rtcp->reported_jitter : 0, 02572 rtp->rtcp ? rtp->rtcp->sr_count : 0, 02573 rtp->rtcp ? rtp->rtcp->rtt : 0); 02574 if (rtp->smoother) 02575 ast_smoother_free(rtp->smoother); 02576 if (rtp->ioid) 02577 ast_io_remove(rtp->io, rtp->ioid); 02578 if (rtp->s > -1) 02579 close(rtp->s); 02580 if (rtp->rtcp) { 02581 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02582 close(rtp->rtcp->s); 02583 ast_free(rtp->rtcp); 02584 rtp->rtcp=NULL; 02585 } 02586 #ifdef P2P_INTENSE 02587 ast_mutex_destroy(&rtp->bridge_lock); 02588 #endif 02589 ast_free(rtp); 02590 }
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 1855 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.
01856 { 01857 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01858 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01859 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 01860 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01861 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; 01862 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; 01863 int srccodec, destcodec, nat_active = 0; 01864 01865 /* Lock channels */ 01866 ast_channel_lock(c0); 01867 if (c1) { 01868 while (ast_channel_trylock(c1)) { 01869 ast_channel_unlock(c0); 01870 usleep(1); 01871 ast_channel_lock(c0); 01872 } 01873 } 01874 01875 /* Find channel driver interfaces */ 01876 destpr = get_proto(c0); 01877 if (c1) 01878 srcpr = get_proto(c1); 01879 if (!destpr) { 01880 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name); 01881 ast_channel_unlock(c0); 01882 if (c1) 01883 ast_channel_unlock(c1); 01884 return -1; 01885 } 01886 if (!srcpr) { 01887 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>"); 01888 ast_channel_unlock(c0); 01889 if (c1) 01890 ast_channel_unlock(c1); 01891 return -1; 01892 } 01893 01894 /* Get audio, video and text interface (if native bridge is possible) */ 01895 audio_dest_res = destpr->get_rtp_info(c0, &destp); 01896 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED; 01897 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED; 01898 if (srcpr) { 01899 audio_src_res = srcpr->get_rtp_info(c1, &srcp); 01900 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED; 01901 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED; 01902 } 01903 01904 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01905 if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) { 01906 /* Somebody doesn't want to play... */ 01907 ast_channel_unlock(c0); 01908 if (c1) 01909 ast_channel_unlock(c1); 01910 return -1; 01911 } 01912 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) 01913 srccodec = srcpr->get_codec(c1); 01914 else 01915 srccodec = 0; 01916 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) 01917 destcodec = destpr->get_codec(c0); 01918 else 01919 destcodec = 0; 01920 /* Ensure we have at least one matching codec */ 01921 if (srcp && !(srccodec & destcodec)) { 01922 ast_channel_unlock(c0); 01923 ast_channel_unlock(c1); 01924 return 0; 01925 } 01926 /* Consider empty media as non-existent */ 01927 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01928 srcp = NULL; 01929 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01930 nat_active = 1; 01931 /* Bridge media early */ 01932 if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active)) 01933 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 01934 ast_channel_unlock(c0); 01935 if (c1) 01936 ast_channel_unlock(c1); 01937 ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 01938 return 0; 01939 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 673 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().
00674 { 00675 return rtp->s; 00676 }
Definition at line 2436 of file rtp.c.
References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().
Referenced by __sip_destroy(), and ast_rtp_read().
02437 { 02438 struct ast_rtp *bridged = NULL; 02439 02440 rtp_bridge_lock(rtp); 02441 bridged = rtp->bridged; 02442 rtp_bridge_unlock(rtp); 02443 02444 return bridged; 02445 }
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 2077 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and rtp_bridge_lock().
Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().
02079 { 02080 int pt; 02081 02082 rtp_bridge_lock(rtp); 02083 02084 *astFormats = *nonAstFormats = 0; 02085 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02086 if (rtp->current_RTP_PT[pt].isAstFormat) { 02087 *astFormats |= rtp->current_RTP_PT[pt].code; 02088 } else { 02089 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 02090 } 02091 } 02092 02093 rtp_bridge_unlock(rtp); 02094 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2418 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().
02419 { 02420 if ((them->sin_family != AF_INET) || 02421 (them->sin_port != rtp->them.sin_port) || 02422 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02423 them->sin_family = AF_INET; 02424 them->sin_port = rtp->them.sin_port; 02425 them->sin_addr = rtp->them.sin_addr; 02426 return 1; 02427 } 02428 return 0; 02429 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2485 of file rtp.c.
References 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::quality, 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, ast_rtp_quality::rtt, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.
Referenced by acf_channel_read(), handle_request_bye(), and sip_hangup().
02486 { 02487 /* 02488 *ssrc our ssrc 02489 *themssrc their ssrc 02490 *lp lost packets 02491 *rxjitter our calculated jitter(rx) 02492 *rxcount no. received packets 02493 *txjitter reported jitter of the other end 02494 *txcount transmitted packets 02495 *rlp remote lost packets 02496 *rtt round trip time 02497 */ 02498 02499 if (qual && rtp) { 02500 qual->local_ssrc = rtp->ssrc; 02501 qual->local_jitter = rtp->rxjitter; 02502 qual->local_count = rtp->rxcount; 02503 qual->remote_ssrc = rtp->themssrc; 02504 qual->remote_count = rtp->txcount; 02505 if (rtp->rtcp) { 02506 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02507 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02508 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02509 qual->rtt = rtp->rtcp->rtt; 02510 } 02511 } 02512 if (rtp->rtcp) { 02513 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02514 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02515 rtp->ssrc, 02516 rtp->themssrc, 02517 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02518 rtp->rxjitter, 02519 rtp->rxcount, 02520 (double)rtp->rtcp->reported_jitter / 65536.0, 02521 rtp->txcount, 02522 rtp->rtcp->reported_lost, 02523 rtp->rtcp->rtt); 02524 return rtp->rtcp->quality; 02525 } else 02526 return "<Unknown> - RTP/RTCP has already been destroyed"; 02527 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 728 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by check_rtp_timeout().
00729 { 00730 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00731 return 0; 00732 return rtp->rtpholdtimeout; 00733 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 736 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by check_rtp_timeout().
00737 { 00738 return rtp->rtpkeepalive; 00739 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 720 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by check_rtp_timeout().
00721 { 00722 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00723 return 0; 00724 return rtp->rtptimeout; 00725 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2431 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 756 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00757 { 00758 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00759 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 4372 of file rtp.c.
References __ast_rtp_reload(), ast_cli_register_multiple(), and cli_rtp.
Referenced by main().
04373 { 04374 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 04375 __ast_rtp_reload(0); 04376 }
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 2118 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().
02119 { 02120 int pt = 0; 02121 02122 rtp_bridge_lock(rtp); 02123 02124 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 02125 code == rtp->rtp_lookup_code_cache_code) { 02126 /* Use our cached mapping, to avoid the overhead of the loop below */ 02127 pt = rtp->rtp_lookup_code_cache_result; 02128 rtp_bridge_unlock(rtp); 02129 return pt; 02130 } 02131 02132 /* Check the dynamic list first */ 02133 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02134 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 02135 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02136 rtp->rtp_lookup_code_cache_code = code; 02137 rtp->rtp_lookup_code_cache_result = pt; 02138 rtp_bridge_unlock(rtp); 02139 return pt; 02140 } 02141 } 02142 02143 /* Then the static list */ 02144 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 02145 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 02146 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 02147 rtp->rtp_lookup_code_cache_code = code; 02148 rtp->rtp_lookup_code_cache_result = pt; 02149 rtp_bridge_unlock(rtp); 02150 return pt; 02151 } 02152 } 02153 02154 rtp_bridge_unlock(rtp); 02155 02156 return -1; 02157 }
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 2178 of file rtp.c.
References ast_copy_string(), ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.
Referenced by process_sdp().
02180 { 02181 int format; 02182 unsigned len; 02183 char *end = buf; 02184 char *start = buf; 02185 02186 if (!buf || !size) 02187 return NULL; 02188 02189 snprintf(end, size, "0x%x (", capability); 02190 02191 len = strlen(end); 02192 end += len; 02193 size -= len; 02194 start = end; 02195 02196 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 02197 if (capability & format) { 02198 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 02199 02200 snprintf(end, size, "%s|", name); 02201 len = strlen(end); 02202 end += len; 02203 size -= len; 02204 } 02205 } 02206 02207 if (start == end) 02208 ast_copy_string(start, "nothing)", size); 02209 else if (size > 1) 02210 *(end -1) = ')'; 02211 02212 return buf; 02213 }
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 2159 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().
02161 { 02162 unsigned int i; 02163 02164 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02165 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 02166 if (isAstFormat && 02167 (code == AST_FORMAT_G726_AAL2) && 02168 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02169 return "G726-32"; 02170 else 02171 return mimeTypes[i].subtype; 02172 } 02173 } 02174 02175 return ""; 02176 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 2096 of file rtp.c.
References rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), and static_RTP_PT.
Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().
02097 { 02098 struct rtpPayloadType result; 02099 02100 result.isAstFormat = result.code = 0; 02101 02102 if (pt < 0 || pt > MAX_RTP_PT) 02103 return result; /* bogus payload type */ 02104 02105 /* Start with negotiated codecs */ 02106 rtp_bridge_lock(rtp); 02107 result = rtp->current_RTP_PT[pt]; 02108 rtp_bridge_unlock(rtp); 02109 02110 /* If it doesn't exist, check our static RTP type list, just in case */ 02111 if (!result.code) 02112 result = static_RTP_PT[pt]; 02113 02114 return result; 02115 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1941 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().
01942 { 01943 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01944 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01945 struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */ 01946 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01947 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; 01948 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; 01949 int srccodec, destcodec; 01950 01951 /* Lock channels */ 01952 ast_channel_lock(dest); 01953 while (ast_channel_trylock(src)) { 01954 ast_channel_unlock(dest); 01955 usleep(1); 01956 ast_channel_lock(dest); 01957 } 01958 01959 /* Find channel driver interfaces */ 01960 if (!(destpr = get_proto(dest))) { 01961 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01962 ast_channel_unlock(dest); 01963 ast_channel_unlock(src); 01964 return 0; 01965 } 01966 if (!(srcpr = get_proto(src))) { 01967 ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name); 01968 ast_channel_unlock(dest); 01969 ast_channel_unlock(src); 01970 return 0; 01971 } 01972 01973 /* Get audio and video interface (if native bridge is possible) */ 01974 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01975 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01976 text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED; 01977 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01978 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01979 text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED; 01980 01981 /* Ensure we have at least one matching codec */ 01982 if (srcpr->get_codec) 01983 srccodec = srcpr->get_codec(src); 01984 else 01985 srccodec = 0; 01986 if (destpr->get_codec) 01987 destcodec = destpr->get_codec(dest); 01988 else 01989 destcodec = 0; 01990 01991 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01992 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)) { 01993 /* Somebody doesn't want to play... */ 01994 ast_channel_unlock(dest); 01995 ast_channel_unlock(src); 01996 return 0; 01997 } 01998 ast_rtp_pt_copy(destp, srcp); 01999 if (vdestp && vsrcp) 02000 ast_rtp_pt_copy(vdestp, vsrcp); 02001 if (tdestp && tsrcp) 02002 ast_rtp_pt_copy(tdestp, tsrcp); 02003 if (media) { 02004 /* Bridge early */ 02005 if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 02006 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 02007 } 02008 ast_channel_unlock(dest); 02009 ast_channel_unlock(src); 02010 ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 02011 return 1; 02012 }
struct ast_rtp* ast_rtp_new | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode | |||
) |
Initializate a RTP session.
sched | ||
io | ||
rtcpenable | ||
callbackmode |
Definition at line 2373 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
02374 { 02375 struct in_addr ia; 02376 02377 memset(&ia, 0, sizeof(ia)); 02378 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02379 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
reload rtp configuration
Definition at line 2264 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().
02265 { 02266 #ifdef P2P_INTENSE 02267 ast_mutex_init(&rtp->bridge_lock); 02268 #endif 02269 02270 rtp->them.sin_family = AF_INET; 02271 rtp->us.sin_family = AF_INET; 02272 rtp->ssrc = ast_random(); 02273 rtp->seqno = ast_random() & 0xffff; 02274 ast_set_flag(rtp, FLAG_HAS_DTMF); 02275 rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN); 02276 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2386 of file rtp.c.
References ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_answer(), sip_indicate(), sip_write(), and skinny_indicate().
struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode, | |||
struct in_addr | in | |||
) |
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 2278 of file rtp.c.
References ast_calloc, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), errno, LOG_ERROR, rtp_socket(), and sched.
Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), jingle_alloc(), sip_alloc(), and start_rtp().
02279 { 02280 struct ast_rtp *rtp; 02281 int x; 02282 int startplace; 02283 02284 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 02285 return NULL; 02286 02287 ast_rtp_new_init(rtp); 02288 02289 rtp->s = rtp_socket("RTP"); 02290 if (rtp->s < 0) 02291 goto fail; 02292 if (sched && rtcpenable) { 02293 rtp->sched = sched; 02294 rtp->rtcp = ast_rtcp_new(); 02295 } 02296 02297 /* 02298 * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well. 02299 * Start from a random (even, by RTP spec) port number, and 02300 * iterate until success or no ports are available. 02301 * Note that the requirement of RTP port being even, or RTCP being the 02302 * next one, cannot be enforced in presence of a NAT box because the 02303 * mapping is not under our control. 02304 */ 02305 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 02306 x = x & ~1; /* make it an even number */ 02307 startplace = x; /* remember the starting point */ 02308 /* this is constant across the loop */ 02309 rtp->us.sin_addr = addr; 02310 if (rtp->rtcp) 02311 rtp->rtcp->us.sin_addr = addr; 02312 for (;;) { 02313 rtp->us.sin_port = htons(x); 02314 if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) { 02315 /* bind succeeded, if no rtcp then we are done */ 02316 if (!rtp->rtcp) 02317 break; 02318 /* have rtcp, try to bind it */ 02319 rtp->rtcp->us.sin_port = htons(x + 1); 02320 if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) 02321 break; /* success again, we are really done */ 02322 /* 02323 * RTCP bind failed, so close and recreate the 02324 * already bound RTP socket for the next round. 02325 */ 02326 close(rtp->s); 02327 rtp->s = rtp_socket("RTP"); 02328 if (rtp->s < 0) 02329 goto fail; 02330 } 02331 /* 02332 * If we get here, there was an error in one of the bind() 02333 * calls, so make sure it is nothing unexpected. 02334 */ 02335 if (errno != EADDRINUSE) { 02336 /* We got an error that wasn't expected, abort! */ 02337 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 02338 goto fail; 02339 } 02340 /* 02341 * One of the ports is in use. For the next iteration, 02342 * increment by two and handle wraparound. 02343 * If we reach the starting point, then declare failure. 02344 */ 02345 x += 2; 02346 if (x > rtpend) 02347 x = (rtpstart + 1) & ~1; 02348 if (x == startplace) { 02349 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 02350 goto fail; 02351 } 02352 } 02353 rtp->sched = sched; 02354 rtp->io = io; 02355 if (callbackmode) { 02356 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 02357 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 02358 } 02359 ast_rtp_pt_default(rtp); 02360 return rtp; 02361 02362 fail: 02363 if (rtp->s >= 0) 02364 close(rtp->s); 02365 if (rtp->rtcp) { 02366 close(rtp->rtcp->s); 02367 ast_free(rtp->rtcp); 02368 } 02369 ast_free(rtp); 02370 return NULL; 02371 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register an RTP channel client.
Definition at line 3331 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().
03332 { 03333 struct ast_rtp_protocol *cur; 03334 03335 AST_RWLIST_WRLOCK(&protos); 03336 AST_RWLIST_TRAVERSE(&protos, cur, list) { 03337 if (!strcmp(cur->type, proto->type)) { 03338 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 03339 AST_RWLIST_UNLOCK(&protos); 03340 return -1; 03341 } 03342 } 03343 AST_RWLIST_INSERT_HEAD(&protos, proto, list); 03344 AST_RWLIST_UNLOCK(&protos); 03345 03346 return 0; 03347 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister an RTP channel client.
Definition at line 3323 of file rtp.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by load_module(), and unload_module().
03324 { 03325 AST_RWLIST_WRLOCK(&protos); 03326 AST_RWLIST_REMOVE(&protos, proto, list); 03327 AST_RWLIST_UNLOCK(&protos); 03328 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1779 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().
01780 { 01781 int i; 01782 01783 if (!rtp) 01784 return; 01785 01786 rtp_bridge_lock(rtp); 01787 01788 for (i = 0; i < MAX_RTP_PT; ++i) { 01789 rtp->current_RTP_PT[i].isAstFormat = 0; 01790 rtp->current_RTP_PT[i].code = 0; 01791 } 01792 01793 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01794 rtp->rtp_lookup_code_cache_code = 0; 01795 rtp->rtp_lookup_code_cache_result = 0; 01796 01797 rtp_bridge_unlock(rtp); 01798 }
Copy payload types between RTP structures.
Definition at line 1819 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().
01820 { 01821 unsigned int i; 01822 01823 rtp_bridge_lock(dest); 01824 rtp_bridge_lock(src); 01825 01826 for (i = 0; i < MAX_RTP_PT; ++i) { 01827 dest->current_RTP_PT[i].isAstFormat = 01828 src->current_RTP_PT[i].isAstFormat; 01829 dest->current_RTP_PT[i].code = 01830 src->current_RTP_PT[i].code; 01831 } 01832 dest->rtp_lookup_code_cache_isAstFormat = 0; 01833 dest->rtp_lookup_code_cache_code = 0; 01834 dest->rtp_lookup_code_cache_result = 0; 01835 01836 rtp_bridge_unlock(src); 01837 rtp_bridge_unlock(dest); 01838 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1800 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, ast_rtp::rtp_lookup_code_cache_result, and static_RTP_PT.
01801 { 01802 int i; 01803 01804 rtp_bridge_lock(rtp); 01805 01806 /* Initialize to default payload types */ 01807 for (i = 0; i < MAX_RTP_PT; ++i) { 01808 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01809 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01810 } 01811 01812 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01813 rtp->rtp_lookup_code_cache_code = 0; 01814 rtp->rtp_lookup_code_cache_result = 0; 01815 01816 rtp_bridge_unlock(rtp); 01817 }
Write RTP packet with audio or video media frames into UDP packet.
Definition at line 3062 of file rtp.c.
References ast_debug, 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(), errno, f, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::set_marker_bit, ast_rtp::ssrc, ast_rtcp::them, ast_rtp::them, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
03063 { 03064 unsigned char *rtpheader; 03065 int hdrlen = 12; 03066 int res; 03067 unsigned int ms; 03068 int pred; 03069 int mark = 0; 03070 03071 if (rtp->sending_digit) { 03072 return 0; 03073 } 03074 03075 ms = calc_txstamp(rtp, &f->delivery); 03076 /* Default prediction */ 03077 if (f->frametype == AST_FRAME_VOICE) { 03078 pred = rtp->lastts + f->samples; 03079 03080 /* Re-calculate last TS */ 03081 rtp->lastts = rtp->lastts + ms * 8; 03082 if (ast_tvzero(f->delivery)) { 03083 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 03084 and if so, go with our prediction */ 03085 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 03086 rtp->lastts = pred; 03087 else { 03088 ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 03089 mark = 1; 03090 } 03091 } 03092 } else if (f->frametype == AST_FRAME_VIDEO) { 03093 mark = f->subclass & 0x1; 03094 pred = rtp->lastovidtimestamp + f->samples; 03095 /* Re-calculate last TS */ 03096 rtp->lastts = rtp->lastts + ms * 90; 03097 /* If it's close to our prediction, go for it */ 03098 if (ast_tvzero(f->delivery)) { 03099 if (abs(rtp->lastts - pred) < 7200) { 03100 rtp->lastts = pred; 03101 rtp->lastovidtimestamp += f->samples; 03102 } else { 03103 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); 03104 rtp->lastovidtimestamp = rtp->lastts; 03105 } 03106 } 03107 } else { 03108 pred = rtp->lastotexttimestamp + f->samples; 03109 /* Re-calculate last TS */ 03110 rtp->lastts = rtp->lastts + ms; 03111 /* If it's close to our prediction, go for it */ 03112 if (ast_tvzero(f->delivery)) { 03113 if (abs(rtp->lastts - pred) < 7200) { 03114 rtp->lastts = pred; 03115 rtp->lastotexttimestamp += f->samples; 03116 } else { 03117 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); 03118 rtp->lastotexttimestamp = rtp->lastts; 03119 } 03120 } 03121 } 03122 03123 /* If we have been explicitly told to set the marker bit do so */ 03124 if (rtp->set_marker_bit) { 03125 mark = 1; 03126 rtp->set_marker_bit = 0; 03127 } 03128 03129 /* If the timestamp for non-digit packets has moved beyond the timestamp 03130 for digits, update the digit timestamp. 03131 */ 03132 if (rtp->lastts > rtp->lastdigitts) 03133 rtp->lastdigitts = rtp->lastts; 03134 03135 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 03136 rtp->lastts = f->ts * 8; 03137 03138 /* Get a pointer to the header */ 03139 rtpheader = (unsigned char *)(f->data - hdrlen); 03140 03141 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 03142 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 03143 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 03144 03145 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 03146 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 03147 if (res < 0) { 03148 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 03149 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)); 03150 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 03151 /* Only give this error message once if we are not RTP debugging */ 03152 if (option_debug || rtpdebug) 03153 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)); 03154 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 03155 } 03156 } else { 03157 rtp->txcount++; 03158 rtp->txoctetcount +=(res - hdrlen); 03159 03160 /* Do not schedule RR if RTCP isn't run */ 03161 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 03162 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 03163 } 03164 } 03165 03166 if (rtp_debug_test_addr(&rtp->them)) 03167 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 03168 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 03169 } 03170 03171 rtp->seqno++; 03172 03173 return 0; 03174 }
Definition at line 1420 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_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, f, ast_rtp::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, len(), ast_frame::len, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, rtp_debug_test_addr(), 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_rtp::them, ast_rtcp::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().
01421 { 01422 int res; 01423 struct sockaddr_in sin; 01424 socklen_t len; 01425 unsigned int seqno; 01426 int version; 01427 int payloadtype; 01428 int hdrlen = 12; 01429 int padding; 01430 int mark; 01431 int ext; 01432 int cc; 01433 unsigned int ssrc; 01434 unsigned int timestamp; 01435 unsigned int *rtpheader; 01436 struct rtpPayloadType rtpPT; 01437 struct ast_rtp *bridged = NULL; 01438 01439 /* If time is up, kill it */ 01440 if (rtp->sending_digit) 01441 ast_rtp_senddigit_continuation(rtp); 01442 01443 len = sizeof(sin); 01444 01445 /* Cache where the header will go */ 01446 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01447 0, (struct sockaddr *)&sin, &len); 01448 01449 /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */ 01450 if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { 01451 /* Copy over address that this packet was received on */ 01452 memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address)); 01453 /* Now move over to actually protecting the RTP port */ 01454 rtp->strict_rtp_state = STRICT_RTP_CLOSED; 01455 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)); 01456 } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { 01457 /* If the address we previously learned doesn't match the address this packet came in on simply drop it */ 01458 if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) { 01459 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(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port)); 01460 return &ast_null_frame; 01461 } 01462 } 01463 01464 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01465 if (res < 0) { 01466 ast_assert(errno != EBADF); 01467 if (errno != EAGAIN) { 01468 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01469 return NULL; 01470 } 01471 return &ast_null_frame; 01472 } 01473 01474 if (res < hdrlen) { 01475 ast_log(LOG_WARNING, "RTP Read too short\n"); 01476 return &ast_null_frame; 01477 } 01478 01479 /* Get fields */ 01480 seqno = ntohl(rtpheader[0]); 01481 01482 /* Check RTP version */ 01483 version = (seqno & 0xC0000000) >> 30; 01484 if (!version) { 01485 /* If the two high bits are 0, this might be a 01486 * STUN message, so process it. stun_handle_packet() 01487 * answers to requests, and it returns STUN_ACCEPT 01488 * if the request is valid. 01489 */ 01490 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) && 01491 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01492 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01493 } 01494 return &ast_null_frame; 01495 } 01496 01497 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01498 /* If we don't have the other side's address, then ignore this */ 01499 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01500 return &ast_null_frame; 01501 #endif 01502 01503 /* Send to whoever send to us if NAT is turned on */ 01504 if (rtp->nat) { 01505 if (((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01506 (rtp->them.sin_port != sin.sin_port)) && 01507 ((rtp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) || 01508 (rtp->altthem.sin_port != sin.sin_port))) { 01509 rtp->them = sin; 01510 if (rtp->rtcp) { 01511 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01512 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01513 } 01514 rtp->rxseqno = 0; 01515 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01516 if (option_debug || rtpdebug) 01517 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)); 01518 } 01519 } 01520 01521 /* If we are bridged to another RTP stream, send direct */ 01522 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01523 return &ast_null_frame; 01524 01525 if (version != 2) 01526 return &ast_null_frame; 01527 01528 payloadtype = (seqno & 0x7f0000) >> 16; 01529 padding = seqno & (1 << 29); 01530 mark = seqno & (1 << 23); 01531 ext = seqno & (1 << 28); 01532 cc = (seqno & 0xF000000) >> 24; 01533 seqno &= 0xffff; 01534 timestamp = ntohl(rtpheader[1]); 01535 ssrc = ntohl(rtpheader[2]); 01536 01537 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01538 if (option_debug || rtpdebug) 01539 ast_debug(0, "Forcing Marker bit, because SSRC has changed\n"); 01540 mark = 1; 01541 } 01542 01543 rtp->rxssrc = ssrc; 01544 01545 if (padding) { 01546 /* Remove padding bytes */ 01547 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01548 } 01549 01550 if (cc) { 01551 /* CSRC fields present */ 01552 hdrlen += cc*4; 01553 } 01554 01555 if (ext) { 01556 /* RTP Extension present */ 01557 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01558 hdrlen += 4; 01559 if (option_debug) { 01560 int profile; 01561 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01562 if (profile == 0x505a) 01563 ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01564 else 01565 ast_debug(1, "Found unknown RTP Extensions %x\n", profile); 01566 } 01567 } 01568 01569 if (res < hdrlen) { 01570 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01571 return &ast_null_frame; 01572 } 01573 01574 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01575 01576 if (rtp->rxcount==1) { 01577 /* This is the first RTP packet successfully received from source */ 01578 rtp->seedrxseqno = seqno; 01579 } 01580 01581 /* Do not schedule RR if RTCP isn't run */ 01582 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01583 /* Schedule transmission of Receiver Report */ 01584 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01585 } 01586 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01587 rtp->cycles += RTP_SEQ_MOD; 01588 01589 rtp->lastrxseqno = seqno; 01590 01591 if (!rtp->themssrc) 01592 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01593 01594 if (rtp_debug_test_addr(&sin)) 01595 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01596 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01597 01598 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01599 if (!rtpPT.isAstFormat) { 01600 struct ast_frame *f = NULL; 01601 01602 /* This is special in-band data that's not one of our codecs */ 01603 if (rtpPT.code == AST_RTP_DTMF) { 01604 /* It's special -- rfc2833 process it */ 01605 if (rtp_debug_test_addr(&sin)) { 01606 unsigned char *data; 01607 unsigned int event; 01608 unsigned int event_end; 01609 unsigned int duration; 01610 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01611 event = ntohl(*((unsigned int *)(data))); 01612 event >>= 24; 01613 event_end = ntohl(*((unsigned int *)(data))); 01614 event_end <<= 8; 01615 event_end >>= 24; 01616 duration = ntohl(*((unsigned int *)(data))); 01617 duration &= 0xFFFF; 01618 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(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration); 01619 } 01620 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01621 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01622 /* It's really special -- process it the Cisco way */ 01623 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01624 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01625 rtp->lastevent = seqno; 01626 } 01627 } else if (rtpPT.code == AST_RTP_CN) { 01628 /* Comfort Noise */ 01629 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01630 } else { 01631 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01632 } 01633 return f ? f : &ast_null_frame; 01634 } 01635 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01636 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; 01637 01638 rtp->rxseqno = seqno; 01639 01640 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) { 01641 rtp->dtmf_timeout = 0; 01642 01643 if (rtp->resp) { 01644 struct ast_frame *f; 01645 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01646 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0)); 01647 rtp->resp = 0; 01648 rtp->dtmf_timeout = rtp->dtmf_duration = 0; 01649 return f; 01650 } 01651 } 01652 01653 /* Record received timestamp as last received now */ 01654 rtp->lastrxts = timestamp; 01655 01656 rtp->f.mallocd = 0; 01657 rtp->f.datalen = res - hdrlen; 01658 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01659 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01660 rtp->f.seqno = seqno; 01661 if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) { 01662 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01663 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01664 ast_frame_byteswap_be(&rtp->f); 01665 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01666 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01667 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01668 rtp->f.ts = timestamp / 8; 01669 rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 ); 01670 } else if(rtp->f.subclass & AST_FORMAT_VIDEO_MASK) { 01671 /* Video -- samples is # of samples vs. 90000 */ 01672 if (!rtp->lastividtimestamp) 01673 rtp->lastividtimestamp = timestamp; 01674 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01675 rtp->lastividtimestamp = timestamp; 01676 rtp->f.delivery.tv_sec = 0; 01677 rtp->f.delivery.tv_usec = 0; 01678 /* Pass the RTP marker bit as bit 0 in the subclass field. 01679 * This is ok because subclass is actually a bitmask, and 01680 * the low bits represent audio formats, that are not 01681 * involved here since we deal with video. 01682 */ 01683 if (mark) 01684 rtp->f.subclass |= 0x1; 01685 } else { 01686 /* TEXT -- samples is # of samples vs. 1000 */ 01687 if (!rtp->lastitexttimestamp) 01688 rtp->lastitexttimestamp = timestamp; 01689 rtp->f.samples = timestamp - rtp->lastitexttimestamp; 01690 rtp->lastitexttimestamp = timestamp; 01691 rtp->f.delivery.tv_sec = 0; 01692 rtp->f.delivery.tv_usec = 0; 01693 } 01694 rtp->f.src = "RTP"; 01695 return &rtp->f; 01696 }
int ast_rtp_reload | ( | void | ) |
Initialize RTP subsystem
Definition at line 4366 of file rtp.c.
References __ast_rtp_reload().
04367 { 04368 return __ast_rtp_reload(1); 04369 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2463 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.
02464 { 02465 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02466 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02467 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02468 rtp->lastts = 0; 02469 rtp->lastdigitts = 0; 02470 rtp->lastrxts = 0; 02471 rtp->lastividtimestamp = 0; 02472 rtp->lastovidtimestamp = 0; 02473 rtp->lastitexttimestamp = 0; 02474 rtp->lastotexttimestamp = 0; 02475 rtp->lasteventseqn = 0; 02476 rtp->lastevent = 0; 02477 rtp->lasttxformat = 0; 02478 rtp->lastrxformat = 0; 02479 rtp->dtmf_timeout = 0; 02480 rtp->dtmfsamples = 0; 02481 rtp->seqno = 0; 02482 rtp->rxseqno = 0; 02483 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 3027 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().
03028 { 03029 unsigned int *rtpheader; 03030 int hdrlen = 12; 03031 int res; 03032 int payload; 03033 char data[256]; 03034 level = 127 - (level & 0x7f); 03035 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 03036 03037 /* If we have no peer, return immediately */ 03038 if (!rtp->them.sin_addr.s_addr) 03039 return 0; 03040 03041 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 03042 03043 /* Get a pointer to the header */ 03044 rtpheader = (unsigned int *)data; 03045 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 03046 rtpheader[1] = htonl(rtp->lastts); 03047 rtpheader[2] = htonl(rtp->ssrc); 03048 data[12] = level; 03049 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 03050 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 03051 if (res <0) 03052 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)); 03053 if (rtp_debug_test_addr(&rtp->them)) 03054 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 03055 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 03056 03057 } 03058 return 0; 03059 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2612 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().
02613 { 02614 unsigned int *rtpheader; 02615 int hdrlen = 12, res = 0, i = 0, payload = 0; 02616 char data[256]; 02617 02618 if ((digit <= '9') && (digit >= '0')) 02619 digit -= '0'; 02620 else if (digit == '*') 02621 digit = 10; 02622 else if (digit == '#') 02623 digit = 11; 02624 else if ((digit >= 'A') && (digit <= 'D')) 02625 digit = digit - 'A' + 12; 02626 else if ((digit >= 'a') && (digit <= 'd')) 02627 digit = digit - 'a' + 12; 02628 else { 02629 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02630 return 0; 02631 } 02632 02633 /* If we have no peer, return immediately */ 02634 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02635 return 0; 02636 02637 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02638 02639 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02640 rtp->send_duration = 160; 02641 rtp->lastdigitts = rtp->lastts + rtp->send_duration; 02642 02643 /* Get a pointer to the header */ 02644 rtpheader = (unsigned int *)data; 02645 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02646 rtpheader[1] = htonl(rtp->lastdigitts); 02647 rtpheader[2] = htonl(rtp->ssrc); 02648 02649 for (i = 0; i < 2; i++) { 02650 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02651 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02652 if (res < 0) 02653 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02654 ast_inet_ntoa(rtp->them.sin_addr), 02655 ntohs(rtp->them.sin_port), strerror(errno)); 02656 if (rtp_debug_test_addr(&rtp->them)) 02657 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02658 ast_inet_ntoa(rtp->them.sin_addr), 02659 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02660 /* Increment sequence number */ 02661 rtp->seqno++; 02662 /* Increment duration */ 02663 rtp->send_duration += 160; 02664 /* Clear marker bit and set seqno */ 02665 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02666 } 02667 02668 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02669 rtp->sending_digit = 1; 02670 rtp->send_digit = digit; 02671 rtp->send_payload = payload; 02672 02673 return 0; 02674 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2677 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().
02678 { 02679 unsigned int *rtpheader; 02680 int hdrlen = 12, res = 0; 02681 char data[256]; 02682 02683 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02684 return 0; 02685 02686 /* Setup packet to send */ 02687 rtpheader = (unsigned int *)data; 02688 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02689 rtpheader[1] = htonl(rtp->lastdigitts); 02690 rtpheader[2] = htonl(rtp->ssrc); 02691 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02692 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02693 02694 /* Transmit */ 02695 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02696 if (res < 0) 02697 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02698 ast_inet_ntoa(rtp->them.sin_addr), 02699 ntohs(rtp->them.sin_port), strerror(errno)); 02700 if (rtp_debug_test_addr(&rtp->them)) 02701 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02702 ast_inet_ntoa(rtp->them.sin_addr), 02703 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02704 02705 /* Increment sequence number */ 02706 rtp->seqno++; 02707 /* Increment duration */ 02708 rtp->send_duration += 160; 02709 02710 return 0; 02711 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2714 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().
02715 { 02716 unsigned int *rtpheader; 02717 int hdrlen = 12, res = 0, i = 0; 02718 char data[256]; 02719 02720 /* If no address, then bail out */ 02721 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02722 return 0; 02723 02724 if ((digit <= '9') && (digit >= '0')) 02725 digit -= '0'; 02726 else if (digit == '*') 02727 digit = 10; 02728 else if (digit == '#') 02729 digit = 11; 02730 else if ((digit >= 'A') && (digit <= 'D')) 02731 digit = digit - 'A' + 12; 02732 else if ((digit >= 'a') && (digit <= 'd')) 02733 digit = digit - 'a' + 12; 02734 else { 02735 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02736 return 0; 02737 } 02738 02739 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02740 02741 rtpheader = (unsigned int *)data; 02742 rtpheader[1] = htonl(rtp->lastdigitts); 02743 rtpheader[2] = htonl(rtp->ssrc); 02744 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02745 /* Set end bit */ 02746 rtpheader[3] |= htonl((1 << 23)); 02747 02748 /* Send 3 termination packets */ 02749 for (i = 0; i < 3; i++) { 02750 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02751 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02752 rtp->seqno++; 02753 if (res < 0) 02754 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02755 ast_inet_ntoa(rtp->them.sin_addr), 02756 ntohs(rtp->them.sin_port), strerror(errno)); 02757 if (rtp_debug_test_addr(&rtp->them)) 02758 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02759 ast_inet_ntoa(rtp->them.sin_addr), 02760 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02761 } 02762 rtp->lastts += rtp->send_duration; 02763 rtp->sending_digit = 0; 02764 rtp->send_digit = 0; 02765 02766 return res; 02767 }
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 2408 of file rtp.c.
References ast_rtp::altthem, ast_rtcp::altthem, and ast_rtp::rtcp.
Referenced by handle_request_invite().
02409 { 02410 rtp->altthem.sin_port = alt->sin_port; 02411 rtp->altthem.sin_addr = alt->sin_addr; 02412 if (rtp->rtcp) { 02413 rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1); 02414 rtp->rtcp->altthem.sin_addr = alt->sin_addr; 02415 } 02416 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 746 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00747 { 00748 rtp->callback = callback; 00749 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Activate payload type.
Definition at line 2018 of file rtp.c.
References ast_rtp::current_RTP_PT, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), and static_RTP_PT.
Referenced by gtalk_is_answered(), gtalk_newcall(), jingle_newcall(), and process_sdp().
02019 { 02020 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 02021 return; /* bogus payload type */ 02022 02023 rtp_bridge_lock(rtp); 02024 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 02025 rtp_bridge_unlock(rtp); 02026 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2394 of file rtp.c.
References ast_rtp::rtcp, ast_rtp::rxseqno, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, ast_rtp::them, and ast_rtcp::them.
Referenced by handle_open_receive_channel_ack_message(), process_sdp(), setup_rtp_connection(), and start_rtp().
02395 { 02396 rtp->them.sin_port = them->sin_port; 02397 rtp->them.sin_addr = them->sin_addr; 02398 if (rtp->rtcp) { 02399 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02400 rtp->rtcp->them.sin_addr = them->sin_addr; 02401 } 02402 rtp->rxseqno = 0; 02403 /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */ 02404 if (strictrtp) 02405 rtp->strict_rtp_state = STRICT_RTP_LEARN; 02406 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 708 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().
00709 { 00710 rtp->rtpholdtimeout = timeout; 00711 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 714 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00715 { 00716 rtp->rtpkeepalive = period; 00717 }
int ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
int | pt, | |||
char * | mimeType, | |||
char * | mimeSubtype, | |||
enum ast_rtp_options | options | |||
) |
Initiate payload type to a known MIME media type for a codec.
Definition at line 2045 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().
02048 { 02049 unsigned int i; 02050 int found = 0; 02051 02052 if (pt < 0 || pt > MAX_RTP_PT) 02053 return -1; /* bogus payload type */ 02054 02055 rtp_bridge_lock(rtp); 02056 02057 for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) { 02058 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 02059 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 02060 found = 1; 02061 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 02062 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 02063 mimeTypes[i].payloadType.isAstFormat && 02064 (options & AST_RTP_OPT_G726_NONSTANDARD)) 02065 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 02066 break; 02067 } 02068 } 02069 02070 rtp_bridge_unlock(rtp); 02071 02072 return (found ? 0 : -1); 02073 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 702 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().
00703 { 00704 rtp->rtptimeout = timeout; 00705 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 695 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00696 { 00697 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00698 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00699 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 761 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().
00762 { 00763 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00764 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 766 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().
00767 { 00768 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00769 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 751 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 | tos, | |||
int | cos, | |||
char * | desc | |||
) |
Definition at line 2381 of file rtp.c.
References ast_netsock_set_qos(), and ast_rtp::s.
Referenced by __oh323_rtp_create(), sip_alloc(), and start_rtp().
02382 { 02383 return ast_netsock_set_qos(rtp->s, tos, cos, desc); 02384 }
void ast_rtp_setstun | ( | struct ast_rtp * | rtp, | |
int | stun_enable | |||
) |
Enable STUN capability.
Definition at line 771 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00772 { 00773 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00774 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Stop RTP session, do not destroy structure
Definition at line 2447 of file rtp.c.
References ast_clear_flag, AST_SCHED_DEL, FLAG_P2P_SENT_MARK, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::them, and ast_rtcp::them.
Referenced by process_sdp(), setup_rtp_connection(), and stop_media_flows().
02448 { 02449 if (rtp->rtcp) { 02450 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02451 } 02452 02453 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02454 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02455 if (rtp->rtcp) { 02456 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02457 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02458 } 02459 02460 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02461 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Send STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().
Definition at line 655 of file rtp.c.
References ast_stun_request(), and ast_rtp::s.
Referenced by gtalk_update_stun(), and jingle_update_stun().
00656 { 00657 ast_stun_request(rtp->s, suggestion, username, NULL); 00658 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
clear payload type
Definition at line 2030 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().
02031 { 02032 if (pt < 0 || pt > MAX_RTP_PT) 02033 return; /* bogus payload type */ 02034 02035 rtp_bridge_lock(rtp); 02036 rtp->current_RTP_PT[pt].isAstFormat = 0; 02037 rtp->current_RTP_PT[pt].code = 0; 02038 rtp_bridge_unlock(rtp); 02039 }
Definition at line 3238 of file rtp.c.
References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G722, 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::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_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
Referenced by gtalk_write(), jingle_write(), mgcp_write(), oh323_write(), sip_write(), skinny_write(), and unistim_write().
03239 { 03240 struct ast_frame *f; 03241 int codec; 03242 int hdrlen = 12; 03243 int subclass; 03244 03245 03246 /* If we have no peer, return immediately */ 03247 if (!rtp->them.sin_addr.s_addr) 03248 return 0; 03249 03250 /* If there is no data length, return immediately */ 03251 if (!_f->datalen) 03252 return 0; 03253 03254 /* Make sure we have enough space for RTP header */ 03255 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) { 03256 ast_log(LOG_WARNING, "RTP can only send voice, video and text\n"); 03257 return -1; 03258 } 03259 03260 /* The bottom bit of a video subclass contains the marker bit */ 03261 subclass = _f->subclass; 03262 if (_f->frametype == AST_FRAME_VIDEO) 03263 subclass &= ~0x1; 03264 03265 codec = ast_rtp_lookup_code(rtp, 1, subclass); 03266 if (codec < 0) { 03267 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 03268 return -1; 03269 } 03270 03271 if (rtp->lasttxformat != subclass) { 03272 /* New format, reset the smoother */ 03273 ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 03274 rtp->lasttxformat = subclass; 03275 if (rtp->smoother) 03276 ast_smoother_free(rtp->smoother); 03277 rtp->smoother = NULL; 03278 } 03279 03280 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 03281 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 03282 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 03283 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 03284 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)); 03285 return -1; 03286 } 03287 if (fmt.flags) 03288 ast_smoother_set_flags(rtp->smoother, fmt.flags); 03289 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)); 03290 } 03291 } 03292 if (rtp->smoother) { 03293 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 03294 ast_smoother_feed_be(rtp->smoother, _f); 03295 } else { 03296 ast_smoother_feed(rtp->smoother, _f); 03297 } 03298 03299 while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { 03300 if (f->subclass == AST_FORMAT_G722) { 03301 /* G.722 is silllllllllllllly */ 03302 f->samples /= 2; 03303 } 03304 03305 ast_rtp_raw_write(rtp, f, codec); 03306 } 03307 } else { 03308 /* Don't buffer outgoing frames; send them one-per-packet: */ 03309 if (_f->offset < hdrlen) 03310 f = ast_frdup(_f); /*! \bug XXX this might never be free'd. Why do we do this? */ 03311 else 03312 f = _f; 03313 if (f->data) 03314 ast_rtp_raw_write(rtp, f, codec); 03315 if (f != _f) 03316 ast_frfree(f); 03317 } 03318 03319 return 0; 03320 }
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.
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 589 of file rtp.c.
References append_attr_string(), ast_log(), ast_select(), stun_attr::attr, LOG_WARNING, STUN_BINDREQ, stun_get_mapped(), stun_handle_packet(), stun_req_id(), stun_send(), and STUN_USERNAME.
Referenced by ast_rtp_stun_request(), and ast_sip_ouraddrfor().
00591 { 00592 struct stun_header *req; 00593 unsigned char reqdata[1024]; 00594 int reqlen, reqleft; 00595 struct stun_attr *attr; 00596 int res = 0; 00597 int retry; 00598 00599 req = (struct stun_header *)reqdata; 00600 stun_req_id(req); 00601 reqlen = 0; 00602 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00603 req->msgtype = 0; 00604 req->msglen = 0; 00605 attr = (struct stun_attr *)req->ies; 00606 if (username) 00607 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00608 req->msglen = htons(reqlen); 00609 req->msgtype = htons(STUN_BINDREQ); 00610 for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */ 00611 /* send request, possibly wait for reply */ 00612 unsigned char reply_buf[1024]; 00613 fd_set rfds; 00614 struct timeval to = { 3, 0 }; /* timeout, make it configurable */ 00615 struct sockaddr_in src; 00616 socklen_t srclen; 00617 00618 res = stun_send(s, dst, req); 00619 if (res < 0) { 00620 ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n", 00621 retry, res); 00622 continue; 00623 } 00624 if (answer == NULL) 00625 break; 00626 FD_ZERO(&rfds); 00627 FD_SET(s, &rfds); 00628 res = ast_select(s + 1, &rfds, NULL, NULL, &to); 00629 if (res <= 0) /* timeout or error */ 00630 continue; 00631 memset(&src, '\0', sizeof(src)); 00632 srclen = sizeof(src); 00633 /* XXX pass -1 in the size, because stun_handle_packet might 00634 * write past the end of the buffer. 00635 */ 00636 res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1, 00637 0, (struct sockaddr *)&src, &srclen); 00638 if (res < 0) { 00639 ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n", 00640 retry, res); 00641 continue; 00642 } 00643 memset(answer, '\0', sizeof(struct sockaddr_in)); 00644 stun_handle_packet(s, &src, reply_buf, res, 00645 stun_get_mapped, answer); 00646 res = 0; /* signal regular exit */ 00647 break; 00648 } 00649 return res; 00650 }
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 3350 of file rtp.c.
References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38, 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_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
03351 { 03352 struct ast_frame *fr = NULL; 03353 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03354 int oldcodec0 = codec0, oldcodec1 = codec1; 03355 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,}; 03356 struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,}; 03357 03358 /* Set it up so audio goes directly between the two endpoints */ 03359 03360 /* Test the first channel */ 03361 if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 03362 ast_rtp_get_peer(p1, &ac1); 03363 if (vp1) 03364 ast_rtp_get_peer(vp1, &vac1); 03365 if (tp1) 03366 ast_rtp_get_peer(tp1, &tac1); 03367 } else 03368 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 03369 03370 /* Test the second channel */ 03371 if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 03372 ast_rtp_get_peer(p0, &ac0); 03373 if (vp0) 03374 ast_rtp_get_peer(vp0, &vac0); 03375 if (tp0) 03376 ast_rtp_get_peer(tp0, &tac0); 03377 } else 03378 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 03379 03380 /* Now we can unlock and move into our loop */ 03381 ast_channel_unlock(c0); 03382 ast_channel_unlock(c1); 03383 03384 ast_poll_channel_add(c0, c1); 03385 03386 /* Throw our channels into the structure and enter the loop */ 03387 cs[0] = c0; 03388 cs[1] = c1; 03389 cs[2] = NULL; 03390 for (;;) { 03391 /* Check if anything changed */ 03392 if ((c0->tech_pvt != pvt0) || 03393 (c1->tech_pvt != pvt1) || 03394 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03395 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03396 ast_debug(1, "Oooh, something is weird, backing out\n"); 03397 if (c0->tech_pvt == pvt0) 03398 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03399 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03400 if (c1->tech_pvt == pvt1) 03401 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03402 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03403 ast_poll_channel_del(c0, c1); 03404 return AST_BRIDGE_RETRY; 03405 } 03406 03407 /* Check if they have changed their address */ 03408 ast_rtp_get_peer(p1, &t1); 03409 if (vp1) 03410 ast_rtp_get_peer(vp1, &vt1); 03411 if (tp1) 03412 ast_rtp_get_peer(tp1, &tt1); 03413 if (pr1->get_codec) 03414 codec1 = pr1->get_codec(c1); 03415 ast_rtp_get_peer(p0, &t0); 03416 if (vp0) 03417 ast_rtp_get_peer(vp0, &vt0); 03418 if (tp0) 03419 ast_rtp_get_peer(tp0, &tt0); 03420 if (pr0->get_codec) 03421 codec0 = pr0->get_codec(c0); 03422 if ((inaddrcmp(&t1, &ac1)) || 03423 (vp1 && inaddrcmp(&vt1, &vac1)) || 03424 (tp1 && inaddrcmp(&tt1, &tac1)) || 03425 (codec1 != oldcodec1)) { 03426 ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03427 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 03428 ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 03429 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 03430 ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n", 03431 c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1); 03432 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03433 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 03434 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03435 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 03436 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03437 c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1); 03438 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))) 03439 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 03440 memcpy(&ac1, &t1, sizeof(ac1)); 03441 memcpy(&vac1, &vt1, sizeof(vac1)); 03442 memcpy(&tac1, &tt1, sizeof(tac1)); 03443 oldcodec1 = codec1; 03444 } 03445 if ((inaddrcmp(&t0, &ac0)) || 03446 (vp0 && inaddrcmp(&vt0, &vac0)) || 03447 (tp0 && inaddrcmp(&tt0, &tac0)) || 03448 (codec0 != oldcodec0)) { 03449 ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 03450 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 03451 ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n", 03452 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 03453 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))) 03454 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 03455 memcpy(&ac0, &t0, sizeof(ac0)); 03456 memcpy(&vac0, &vt0, sizeof(vac0)); 03457 memcpy(&tac0, &tt0, sizeof(tac0)); 03458 oldcodec0 = codec0; 03459 } 03460 03461 /* Wait for frame to come in on the channels */ 03462 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03463 if (!timeoutms) { 03464 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03465 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03466 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03467 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03468 return AST_BRIDGE_RETRY; 03469 } 03470 ast_debug(1, "Ooh, empty read...\n"); 03471 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03472 break; 03473 continue; 03474 } 03475 fr = ast_read(who); 03476 other = (who == c0) ? c1 : c0; 03477 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03478 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 03479 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 03480 /* Break out of bridge */ 03481 *fo = fr; 03482 *rc = who; 03483 ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03484 if (c0->tech_pvt == pvt0) 03485 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03486 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03487 if (c1->tech_pvt == pvt1) 03488 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03489 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03490 ast_poll_channel_del(c0, c1); 03491 return AST_BRIDGE_COMPLETE; 03492 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03493 if ((fr->subclass == AST_CONTROL_HOLD) || 03494 (fr->subclass == AST_CONTROL_UNHOLD) || 03495 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03496 (fr->subclass == AST_CONTROL_T38) || 03497 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03498 if (fr->subclass == AST_CONTROL_HOLD) { 03499 /* If we someone went on hold we want the other side to reinvite back to us */ 03500 if (who == c0) 03501 pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0); 03502 else 03503 pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0); 03504 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03505 /* If they went off hold they should go back to being direct */ 03506 if (who == c0) 03507 pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 03508 else 03509 pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 03510 } 03511 /* Update local address information */ 03512 ast_rtp_get_peer(p0, &t0); 03513 memcpy(&ac0, &t0, sizeof(ac0)); 03514 ast_rtp_get_peer(p1, &t1); 03515 memcpy(&ac1, &t1, sizeof(ac1)); 03516 /* Update codec information */ 03517 if (pr0->get_codec && c0->tech_pvt) 03518 oldcodec0 = codec0 = pr0->get_codec(c0); 03519 if (pr1->get_codec && c1->tech_pvt) 03520 oldcodec1 = codec1 = pr1->get_codec(c1); 03521 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03522 ast_frfree(fr); 03523 } else { 03524 *fo = fr; 03525 *rc = who; 03526 ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03527 return AST_BRIDGE_COMPLETE; 03528 } 03529 } else { 03530 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03531 (fr->frametype == AST_FRAME_DTMF_END) || 03532 (fr->frametype == AST_FRAME_VOICE) || 03533 (fr->frametype == AST_FRAME_VIDEO) || 03534 (fr->frametype == AST_FRAME_IMAGE) || 03535 (fr->frametype == AST_FRAME_HTML) || 03536 (fr->frametype == AST_FRAME_MODEM) || 03537 (fr->frametype == AST_FRAME_TEXT)) { 03538 ast_write(other, fr); 03539 } 03540 ast_frfree(fr); 03541 } 03542 /* Swap priority */ 03543 #ifndef HAVE_EPOLL 03544 cs[2] = cs[0]; 03545 cs[0] = cs[1]; 03546 cs[1] = cs[2]; 03547 #endif 03548 } 03549 03550 ast_poll_channel_del(c0, c1); 03551 03552 if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) 03553 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03554 if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0)) 03555 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03556 03557 return AST_BRIDGE_FAILED; 03558 }
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 3658 of file rtp.c.
References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_unlock, ast_clear_flag, ast_debug, ast_frfree, ast_poll_channel_add(), ast_read(), ast_channel::audiohooks, FLAG_P2P_SENT_MARK, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, p2p_callback_enable(), p2p_set_bridge(), ast_channel::rawreadformat, ast_channel::rawwriteformat, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
03659 { 03660 struct ast_frame *fr = NULL; 03661 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03662 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03663 int p0_callback = 0, p1_callback = 0; 03664 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03665 03666 /* Okay, setup each RTP structure to do P2P forwarding */ 03667 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03668 p2p_set_bridge(p0, p1); 03669 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03670 p2p_set_bridge(p1, p0); 03671 03672 /* Activate callback modes if possible */ 03673 p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]); 03674 p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]); 03675 03676 /* Now let go of the channel locks and be on our way */ 03677 ast_channel_unlock(c0); 03678 ast_channel_unlock(c1); 03679 03680 ast_poll_channel_add(c0, c1); 03681 03682 /* Go into a loop forwarding frames until we don't need to anymore */ 03683 cs[0] = c0; 03684 cs[1] = c1; 03685 cs[2] = NULL; 03686 for (;;) { 03687 /* If the underlying formats have changed force this bridge to break */ 03688 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 03689 ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n"); 03690 res = AST_BRIDGE_FAILED_NOWARN; 03691 break; 03692 } 03693 /* Check if anything changed */ 03694 if ((c0->tech_pvt != pvt0) || 03695 (c1->tech_pvt != pvt1) || 03696 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03697 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03698 ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n"); 03699 /* 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 */ 03700 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03701 ast_frfree(fr); 03702 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03703 ast_frfree(fr); 03704 res = AST_BRIDGE_RETRY; 03705 break; 03706 } 03707 /* Wait on a channel to feed us a frame */ 03708 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03709 if (!timeoutms) { 03710 res = AST_BRIDGE_RETRY; 03711 break; 03712 } 03713 if (option_debug > 2) 03714 ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n"); 03715 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03716 break; 03717 continue; 03718 } 03719 /* Read in frame from channel */ 03720 fr = ast_read(who); 03721 other = (who == c0) ? c1 : c0; 03722 /* Depending on the frame we may need to break out of our bridge */ 03723 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03724 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03725 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03726 /* Record received frame and who */ 03727 *fo = fr; 03728 *rc = who; 03729 ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup"); 03730 res = AST_BRIDGE_COMPLETE; 03731 break; 03732 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03733 if ((fr->subclass == AST_CONTROL_HOLD) || 03734 (fr->subclass == AST_CONTROL_UNHOLD) || 03735 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03736 (fr->subclass == AST_CONTROL_T38) || 03737 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03738 /* If we are going on hold, then break callback mode and P2P bridging */ 03739 if (fr->subclass == AST_CONTROL_HOLD) { 03740 if (p0_callback) 03741 p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]); 03742 if (p1_callback) 03743 p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]); 03744 p2p_set_bridge(p0, NULL); 03745 p2p_set_bridge(p1, NULL); 03746 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03747 /* If we are off hold, then go back to callback mode and P2P bridging */ 03748 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03749 p2p_set_bridge(p0, p1); 03750 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03751 p2p_set_bridge(p1, p0); 03752 p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]); 03753 p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]); 03754 } 03755 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03756 ast_frfree(fr); 03757 } else { 03758 *fo = fr; 03759 *rc = who; 03760 ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03761 res = AST_BRIDGE_COMPLETE; 03762 break; 03763 } 03764 } else { 03765 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03766 (fr->frametype == AST_FRAME_DTMF_END) || 03767 (fr->frametype == AST_FRAME_VOICE) || 03768 (fr->frametype == AST_FRAME_VIDEO) || 03769 (fr->frametype == AST_FRAME_IMAGE) || 03770 (fr->frametype == AST_FRAME_HTML) || 03771 (fr->frametype == AST_FRAME_MODEM) || 03772 (fr->frametype == AST_FRAME_TEXT)) { 03773 ast_write(other, fr); 03774 } 03775 03776 ast_frfree(fr); 03777 } 03778 /* Swap priority */ 03779 #ifndef HAVE_EPOLL 03780 cs[2] = cs[0]; 03781 cs[0] = cs[1]; 03782 cs[1] = cs[2]; 03783 #endif 03784 } 03785 03786 /* If we are totally avoiding the core, then restore our link to it */ 03787 if (p0_callback) 03788 p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]); 03789 if (p1_callback) 03790 p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]); 03791 03792 /* Break out of the direct bridge */ 03793 p2p_set_bridge(p0, NULL); 03794 p2p_set_bridge(p1, NULL); 03795 03796 ast_poll_channel_del(c0, c1); 03797 03798 return res; 03799 }
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 1366 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().
01367 { 01368 int res = 0, payload = 0, bridged_payload = 0, mark; 01369 struct rtpPayloadType rtpPT; 01370 int reconstruct = ntohl(rtpheader[0]); 01371 01372 /* Get fields from packet */ 01373 payload = (reconstruct & 0x7f0000) >> 16; 01374 mark = (((reconstruct & 0x800000) >> 23) != 0); 01375 01376 /* Check what the payload value should be */ 01377 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01378 01379 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01380 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01381 return -1; 01382 01383 /* Otherwise adjust bridged payload to match */ 01384 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01385 01386 /* 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 */ 01387 if (!bridged->current_RTP_PT[bridged_payload].code) 01388 return -1; 01389 01390 01391 /* If the mark bit has not been sent yet... do it now */ 01392 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01393 mark = 1; 01394 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01395 } 01396 01397 /* Reconstruct part of the packet */ 01398 reconstruct &= 0xFF80FFFF; 01399 reconstruct |= (bridged_payload << 16); 01400 reconstruct |= (mark << 23); 01401 rtpheader[0] = htonl(reconstruct); 01402 01403 /* Send the packet back out */ 01404 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01405 if (res < 0) { 01406 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01407 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)); 01408 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01409 if (option_debug || rtpdebug) 01410 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)); 01411 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01412 } 01413 return 0; 01414 } else if (rtp_debug_test_addr(&bridged->them)) 01415 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); 01416 01417 return 0; 01418 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1317 of file rtp.c.
References ast_rtp::drxcore, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtp::rtcp, ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtp::rxtransit, and ast_rtp::seedrxts.
Referenced by ast_rtp_read(), and schedule_delivery().
01318 { 01319 struct timeval now; 01320 double transit; 01321 double current_time; 01322 double d; 01323 double dtv; 01324 double prog; 01325 01326 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01327 gettimeofday(&rtp->rxcore, NULL); 01328 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01329 /* map timestamp to a real time */ 01330 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01331 rtp->rxcore.tv_sec -= timestamp / 8000; 01332 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01333 /* Round to 0.1ms for nice, pretty timestamps */ 01334 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01335 if (rtp->rxcore.tv_usec < 0) { 01336 /* Adjust appropriately if necessary */ 01337 rtp->rxcore.tv_usec += 1000000; 01338 rtp->rxcore.tv_sec -= 1; 01339 } 01340 } 01341 01342 gettimeofday(&now,NULL); 01343 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01344 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01345 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01346 if (tv->tv_usec >= 1000000) { 01347 tv->tv_usec -= 1000000; 01348 tv->tv_sec += 1; 01349 } 01350 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01351 dtv = (double)rtp->drxcore + (double)(prog); 01352 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01353 transit = current_time - dtv; 01354 d = transit - rtp->rxtransit; 01355 rtp->rxtransit = transit; 01356 if (d<0) 01357 d=-d; 01358 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01359 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01360 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01361 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01362 rtp->rtcp->minrxjitter = rtp->rxjitter; 01363 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2592 of file rtp.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02593 { 02594 struct timeval t; 02595 long ms; 02596 if (ast_tvzero(rtp->txcore)) { 02597 rtp->txcore = ast_tvnow(); 02598 /* Round to 20ms for nice, pretty timestamps */ 02599 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02600 } 02601 /* Use previous txcore if available */ 02602 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02603 ms = ast_tvdiff_ms(t, rtp->txcore); 02604 if (ms < 0) 02605 ms = 0; 02606 /* Use what we just got for next time */ 02607 rtp->txcore = t; 02608 return (unsigned int) ms; 02609 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Get channel driver interface structure.
Definition at line 1841 of file rtp.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, chan, 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().
01842 { 01843 struct ast_rtp_protocol *cur = NULL; 01844 01845 AST_RWLIST_RDLOCK(&protos); 01846 AST_RWLIST_TRAVERSE(&protos, cur, list) { 01847 if (cur->type == chan->tech->type) 01848 break; 01849 } 01850 AST_RWLIST_UNLOCK(&protos); 01851 01852 return cur; 01853 }
static char* handle_cli_rtcp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4114 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(), and ast_cli_entry::usage.
04115 { 04116 switch (cmd) { 04117 case CLI_INIT: 04118 e->command = "rtcp debug [off|ip]"; 04119 e->usage = 04120 "Usage: rtcp debug [off]|[ip host[:port]]\n" 04121 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04122 " specified, limit the dumped packets to those to and from\n" 04123 " the specified 'host' with optional port.\n"; 04124 return NULL; 04125 case CLI_GENERATE: 04126 return NULL; 04127 } 04128 04129 if (a->argc < 2 || a->argc > 4) 04130 return CLI_SHOWUSAGE; 04131 if (a->argc == 2) { 04132 rtcpdebug = 1; 04133 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04134 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04135 } else if (a->argc == 3) { 04136 if (strncasecmp(a->argv[2], "off", 3)) 04137 return CLI_SHOWUSAGE; 04138 rtcpdebug = 0; 04139 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04140 } else { 04141 if (strncasecmp(a->argv[2], "ip", 2)) 04142 return CLI_SHOWUSAGE; 04143 return rtcp_do_debug_ip(a); 04144 } 04145 04146 return CLI_SUCCESS; 04147 }
static char* handle_cli_rtcp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4149 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(), and ast_cli_entry::usage.
04150 { 04151 switch (cmd) { 04152 case CLI_INIT: 04153 e->command = "rtcp set debug {on|off|ip}"; 04154 e->usage = 04155 "Usage: rtcp set debug {on|off|ip host[:port]}\n" 04156 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 04157 " specified, limit the dumped packets to those to and from\n" 04158 " the specified 'host' with optional port.\n"; 04159 return NULL; 04160 case CLI_GENERATE: 04161 return NULL; 04162 } 04163 04164 if (a->argc == e->args) { /* set on or off */ 04165 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04166 rtcpdebug = 1; 04167 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 04168 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 04169 return CLI_SUCCESS; 04170 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04171 rtcpdebug = 0; 04172 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 04173 return CLI_SUCCESS; 04174 } 04175 } else if (a->argc == e->args +1) { /* ip */ 04176 return rtcp_do_debug_ip(a); 04177 } 04178 04179 return CLI_SHOWUSAGE; /* default, failure */ 04180 }
static char* handle_cli_rtcp_set_stats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4205 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.
04206 { 04207 switch (cmd) { 04208 case CLI_INIT: 04209 e->command = "rtcp set stats {on|off}"; 04210 e->usage = 04211 "Usage: rtcp set stats {on|off}\n" 04212 " Enable/Disable dumping of RTCP stats.\n"; 04213 return NULL; 04214 case CLI_GENERATE: 04215 return NULL; 04216 } 04217 04218 if (a->argc != e->args) 04219 return CLI_SHOWUSAGE; 04220 04221 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04222 rtcpstats = 1; 04223 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04224 rtcpstats = 0; 04225 else 04226 return CLI_SHOWUSAGE; 04227 04228 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04229 return CLI_SUCCESS; 04230 }
static char* handle_cli_rtcp_stats_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4182 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.
04183 { 04184 switch (cmd) { 04185 case CLI_INIT: 04186 e->command = "rtcp stats [off]"; 04187 e->usage = 04188 "Usage: rtcp stats [off]\n" 04189 " Enable/Disable dumping of RTCP stats.\n"; 04190 return NULL; 04191 case CLI_GENERATE: 04192 return NULL; 04193 } 04194 04195 if (a->argc < 2 || a->argc > 3) 04196 return CLI_SHOWUSAGE; 04197 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04198 return CLI_SHOWUSAGE; 04199 04200 rtcpstats = (a->argc == 3) ? 0 : 1; 04201 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 04202 return CLI_SUCCESS; 04203 }
static char* handle_cli_rtp_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4046 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(), and ast_cli_entry::usage.
04047 { 04048 switch (cmd) { 04049 case CLI_INIT: 04050 e->command = "rtp debug [off|ip]"; 04051 e->usage = 04052 "Usage: rtp debug [off]|[ip host[:port]]\n" 04053 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04054 " specified, limit the dumped packets to those to and from\n" 04055 " the specified 'host' with optional port.\n"; 04056 return NULL; 04057 case CLI_GENERATE: 04058 return NULL; 04059 } 04060 04061 if (a->argc < 2 || a->argc > 4) 04062 return CLI_SHOWUSAGE; 04063 if (a->argc == 2) { 04064 rtpdebug = 1; 04065 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04066 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04067 } else if (a->argc == 3) { 04068 if (strncasecmp(a->argv[2], "off", 3)) 04069 return CLI_SHOWUSAGE; 04070 rtpdebug = 0; 04071 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04072 } else { 04073 if (strncasecmp(a->argv[2], "ip", 2)) 04074 return CLI_SHOWUSAGE; 04075 return rtp_do_debug_ip(a); 04076 } 04077 04078 return CLI_SUCCESS; 04079 }
static char* handle_cli_rtp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4081 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(), and ast_cli_entry::usage.
04082 { 04083 switch (cmd) { 04084 case CLI_INIT: 04085 e->command = "rtp set debug {on|off|ip}"; 04086 e->usage = 04087 "Usage: rtp set debug {on|off|ip host[:port]}\n" 04088 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 04089 " specified, limit the dumped packets to those to and from\n" 04090 " the specified 'host' with optional port.\n"; 04091 return NULL; 04092 case CLI_GENERATE: 04093 return NULL; 04094 } 04095 04096 if (a->argc == e->args) { /* set on or off */ 04097 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 04098 rtpdebug = 1; 04099 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 04100 ast_cli(a->fd, "RTP Debugging Enabled\n"); 04101 return CLI_SUCCESS; 04102 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 04103 rtpdebug = 0; 04104 ast_cli(a->fd, "RTP Debugging Disabled\n"); 04105 return CLI_SUCCESS; 04106 } 04107 } else if (a->argc == e->args +1) { /* ip */ 04108 return rtp_do_debug_ip(a); 04109 } 04110 04111 return CLI_SHOWUSAGE; /* default, failure */ 04112 }
static char* handle_cli_stun_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4232 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.
04233 { 04234 switch (cmd) { 04235 case CLI_INIT: 04236 e->command = "stun debug [off]"; 04237 e->usage = 04238 "Usage: stun debug [off]\n" 04239 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04240 " debugging\n"; 04241 return NULL; 04242 case CLI_GENERATE: 04243 return NULL; 04244 } 04245 04246 if (a->argc < 2 || a->argc > 3) 04247 return CLI_SHOWUSAGE; 04248 if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3)) 04249 return CLI_SHOWUSAGE; 04250 04251 stundebug = (a->argc == 3) ? 0 : 1; 04252 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04253 return CLI_SUCCESS; 04254 }
static char* handle_cli_stun_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4256 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.
04257 { 04258 switch (cmd) { 04259 case CLI_INIT: 04260 e->command = "stun set debug {on|off}"; 04261 e->usage = 04262 "Usage: stun set debug {on|off}\n" 04263 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 04264 " debugging\n"; 04265 return NULL; 04266 case CLI_GENERATE: 04267 return NULL; 04268 } 04269 04270 if (a->argc != e->args) 04271 return CLI_SHOWUSAGE; 04272 04273 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 04274 stundebug = 1; 04275 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 04276 stundebug = 0; 04277 else 04278 return CLI_SHOWUSAGE; 04279 04280 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled"); 04281 return CLI_SUCCESS; 04282 }
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 3626 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, chan, ast_channel::fds, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, and rtpread().
03627 { 03628 ast_channel_lock(chan); 03629 03630 /* Remove the callback from the IO context */ 03631 ast_io_remove(rtp->io, iod[0]); 03632 03633 /* Restore file descriptors */ 03634 chan->fds[0] = ast_rtp_fd(rtp); 03635 ast_channel_unlock(chan); 03636 03637 /* Restore callback mode if previously used */ 03638 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03639 rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp); 03640 03641 return 0; 03642 }
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 3645 of file rtp.c.
References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().
Referenced by bridge_p2p_loop().
03646 { 03647 rtp_bridge_lock(rtp0); 03648 rtp0->bridged = rtp1; 03649 rtp_bridge_unlock(rtp0); 03650 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 844 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, send_dtmf(), and seq.
Referenced by ast_rtp_read().
00845 { 00846 unsigned int event; 00847 char resp = 0; 00848 struct ast_frame *f = NULL; 00849 unsigned char seq; 00850 unsigned int flags; 00851 unsigned int power; 00852 00853 /* We should have at least 4 bytes in RTP data */ 00854 if (len < 4) 00855 return f; 00856 00857 /* The format of Cisco RTP DTMF packet looks like next: 00858 +0 - sequence number of DTMF RTP packet (begins from 1, 00859 wrapped to 0) 00860 +1 - set of flags 00861 +1 (bit 0) - flaps by different DTMF digits delimited by audio 00862 or repeated digit without audio??? 00863 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone 00864 then falls to 0 at its end) 00865 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...) 00866 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right 00867 by each new packet and thus provides some redudancy. 00868 00869 Sample of Cisco RTP DTMF packet is (all data in hex): 00870 19 07 00 02 12 02 20 02 00871 showing end of DTMF digit '2'. 00872 00873 The packets 00874 27 07 00 02 0A 02 20 02 00875 28 06 20 02 00 02 0A 02 00876 shows begin of new digit '2' with very short pause (20 ms) after 00877 previous digit '2'. Bit +1.0 flips at begin of new digit. 00878 00879 Cisco RTP DTMF packets comes as replacement of audio RTP packets 00880 so its uses the same sequencing and timestamping rules as replaced 00881 audio packets. Repeat interval of DTMF packets is 20 ms and not rely 00882 on audio framing parameters. Marker bit isn't used within stream of 00883 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps 00884 are not sequential at borders between DTMF and audio streams, 00885 */ 00886 00887 seq = data[0]; 00888 flags = data[1]; 00889 power = data[2]; 00890 event = data[3] & 0x1f; 00891 00892 if (option_debug > 2 || rtpdebug) 00893 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); 00894 if (event < 10) { 00895 resp = '0' + event; 00896 } else if (event < 11) { 00897 resp = '*'; 00898 } else if (event < 12) { 00899 resp = '#'; 00900 } else if (event < 16) { 00901 resp = 'A' + (event - 12); 00902 } else if (event < 17) { 00903 resp = 'X'; 00904 } 00905 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) { 00906 rtp->resp = resp; 00907 /* Why we should care on DTMF compensation at reception? */ 00908 if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00909 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00910 rtp->dtmfsamples = 0; 00911 } 00912 } else if ((rtp->resp == resp) && !power) { 00913 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00914 f->samples = rtp->dtmfsamples * 8; 00915 rtp->resp = 0; 00916 } else if (rtp->resp == resp) 00917 rtp->dtmfsamples += 20 * 8; 00918 rtp->dtmf_timeout = dtmftimeout; 00919 return f; 00920 }
static struct ast_frame* process_rfc2833 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp | |||
) | [static] |
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 934 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, LOG_DEBUG, option_debug, ast_rtp::resp, ast_frame::samples, and send_dtmf().
Referenced by ast_rtp_read().
00935 { 00936 unsigned int event; 00937 unsigned int event_end; 00938 unsigned int samples; 00939 char resp = 0; 00940 struct ast_frame *f = NULL; 00941 00942 /* Figure out event, event end, and samples */ 00943 event = ntohl(*((unsigned int *)(data))); 00944 event >>= 24; 00945 event_end = ntohl(*((unsigned int *)(data))); 00946 event_end <<= 8; 00947 event_end >>= 24; 00948 samples = ntohl(*((unsigned int *)(data))); 00949 samples &= 0xFFFF; 00950 00951 /* Print out debug if turned on */ 00952 if (rtpdebug || option_debug > 2) 00953 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00954 00955 /* Figure out what digit was pressed */ 00956 if (event < 10) { 00957 resp = '0' + event; 00958 } else if (event < 11) { 00959 resp = '*'; 00960 } else if (event < 12) { 00961 resp = '#'; 00962 } else if (event < 16) { 00963 resp = 'A' + (event - 12); 00964 } else if (event < 17) { /* Event 16: Hook flash */ 00965 resp = 'X'; 00966 } else { 00967 /* Not a supported event */ 00968 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 00969 return &ast_null_frame; 00970 } 00971 00972 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00973 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 00974 rtp->resp = resp; 00975 rtp->dtmf_timeout = 0; 00976 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00977 f->len = 0; 00978 rtp->lastevent = timestamp; 00979 } 00980 } else { 00981 /* The duration parameter measures the complete 00982 duration of the event (from the beginning) - RFC2833. 00983 Account for the fact that duration is only 16 bits long 00984 (about 8 seconds at 8000 Hz) and can wrap is digit 00985 is hold for too long. */ 00986 unsigned int new_duration = rtp->dtmf_duration; 00987 unsigned int last_duration = new_duration & 0xFFFF; 00988 00989 if (last_duration > 64000 && samples < last_duration) 00990 new_duration += 0xFFFF + 1; 00991 new_duration = (new_duration & ~0xFFFF) | samples; 00992 00993 if (event_end & 0x80) { 00994 /* End event */ 00995 if ((rtp->lastevent != seqno) && rtp->resp) { 00996 rtp->dtmf_duration = new_duration; 00997 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00998 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0)); 00999 rtp->resp = 0; 01000 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01001 } 01002 } else { 01003 /* Begin/continuation */ 01004 01005 if (rtp->resp && rtp->resp != resp) { 01006 /* Another digit already began. End it */ 01007 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 01008 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0)); 01009 rtp->resp = 0; 01010 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01011 } 01012 01013 01014 if (rtp->resp) { 01015 /* Digit continues */ 01016 rtp->dtmf_duration = new_duration; 01017 } else { 01018 /* New digit began */ 01019 rtp->resp = resp; 01020 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 01021 rtp->dtmf_duration = samples; 01022 } 01023 01024 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout; 01025 } 01026 01027 rtp->lastevent = seqno; 01028 } 01029 01030 rtp->dtmfsamples = samples; 01031 01032 return f; 01033 }
static struct ast_frame* process_rfc3389 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Process Comfort Noise RTP.
This is incomplete at the moment.
Definition at line 1041 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_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read().
01042 { 01043 struct ast_frame *f = NULL; 01044 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 01045 totally help us out becuase we don't have an engine to keep it going and we are not 01046 guaranteed to have it every 20ms or anything */ 01047 if (rtpdebug) 01048 ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 01049 01050 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 01051 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 01052 ast_inet_ntoa(rtp->them.sin_addr)); 01053 ast_set_flag(rtp, FLAG_3389_WARNING); 01054 } 01055 01056 /* Must have at least one byte */ 01057 if (!len) 01058 return NULL; 01059 if (len < 24) { 01060 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 01061 rtp->f.datalen = len - 1; 01062 rtp->f.offset = AST_FRIENDLY_OFFSET; 01063 memcpy(rtp->f.data, data + 1, len - 1); 01064 } else { 01065 rtp->f.data = NULL; 01066 rtp->f.offset = 0; 01067 rtp->f.datalen = 0; 01068 } 01069 rtp->f.frametype = AST_FRAME_CNG; 01070 rtp->f.subclass = data[0] & 0x7f; 01071 rtp->f.datalen = len - 1; 01072 rtp->f.samples = 0; 01073 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 01074 f = &rtp->f; 01075 return f; 01076 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 830 of file rtp.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00831 { 00832 if (rtcpdebug == 0) 00833 return 0; 00834 if (rtcpdebugaddr.sin_addr.s_addr) { 00835 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00836 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00837 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00838 return 0; 00839 } 00840 return 1; 00841 }
static char* rtcp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 4016 of file rtp.c.
References ahp, ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, and hp.
Referenced by handle_cli_rtcp_debug_deprecated(), and handle_cli_rtcp_set_debug().
04017 { 04018 struct hostent *hp; 04019 struct ast_hostent ahp; 04020 int port = 0; 04021 char *p, *arg; 04022 04023 arg = a->argv[3]; 04024 p = strstr(arg, ":"); 04025 if (p) { 04026 *p = '\0'; 04027 p++; 04028 port = atoi(p); 04029 } 04030 hp = ast_gethostbyname(arg, &ahp); 04031 if (hp == NULL) { 04032 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04033 return CLI_FAILURE; 04034 } 04035 rtcpdebugaddr.sin_family = AF_INET; 04036 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 04037 rtcpdebugaddr.sin_port = htons(port); 04038 if (port == 0) 04039 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 04040 else 04041 ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 04042 rtcpdebug = 1; 04043 return CLI_SUCCESS; 04044 }
static void rtp_bridge_lock | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 776 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().
00777 { 00778 #ifdef P2P_INTENSE 00779 ast_mutex_lock(&rtp->bridge_lock); 00780 #endif 00781 return; 00782 }
static void rtp_bridge_unlock | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 784 of file rtp.c.
References ast_mutex_unlock().
Referenced by ast_rtp_get_bridged(), 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().
00785 { 00786 #ifdef P2P_INTENSE 00787 ast_mutex_unlock(&rtp->bridge_lock); 00788 #endif 00789 return; 00790 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 817 of file rtp.c.
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().
00818 { 00819 if (rtpdebug == 0) 00820 return 0; 00821 if (rtpdebugaddr.sin_addr.s_addr) { 00822 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00823 && (rtpdebugaddr.sin_port != addr->sin_port)) 00824 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00825 return 0; 00826 } 00827 return 1; 00828 }
static char* rtp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 3986 of file rtp.c.
References ahp, ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, and hp.
Referenced by handle_cli_rtp_debug_deprecated(), and handle_cli_rtp_set_debug().
03987 { 03988 struct hostent *hp; 03989 struct ast_hostent ahp; 03990 int port = 0; 03991 char *p, *arg; 03992 03993 arg = a->argv[3]; 03994 p = strstr(arg, ":"); 03995 if (p) { 03996 *p = '\0'; 03997 p++; 03998 port = atoi(p); 03999 } 04000 hp = ast_gethostbyname(arg, &ahp); 04001 if (hp == NULL) { 04002 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 04003 return CLI_FAILURE; 04004 } 04005 rtpdebugaddr.sin_family = AF_INET; 04006 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 04007 rtpdebugaddr.sin_port = htons(port); 04008 if (port == 0) 04009 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 04010 else 04011 ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 04012 rtpdebug = 1; 04013 return CLI_SUCCESS; 04014 }
static int rtp_socket | ( | const char * | type | ) | [static] |
Open RTP or RTCP socket for a session. Print a message on failure.
Definition at line 2218 of file rtp.c.
References ast_log(), errno, LOG_WARNING, and s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
02219 { 02220 int s = socket(AF_INET, SOCK_DGRAM, 0); 02221 if (s < 0) { 02222 if (type == NULL) 02223 type = "RTP/RTCP"; 02224 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno)); 02225 } else { 02226 long flags = fcntl(s, F_GETFL); 02227 fcntl(s, F_SETFL, flags | O_NONBLOCK); 02228 #ifdef SO_NO_CHECK 02229 if (nochecksums) 02230 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 02231 #endif 02232 } 02233 return s; 02234 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 1078 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and f.
Referenced by p2p_callback_disable().
01079 { 01080 struct ast_rtp *rtp = cbdata; 01081 struct ast_frame *f; 01082 f = ast_rtp_read(rtp); 01083 if (f) { 01084 if (rtp->callback) 01085 rtp->callback(rtp, f, rtp->data); 01086 } 01087 return 1; 01088 }
static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static] |
Definition at line 792 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().
00793 { 00794 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00795 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00796 ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00797 rtp->resp = 0; 00798 rtp->dtmfsamples = 0; 00799 return &ast_null_frame; 00800 } 00801 ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00802 if (rtp->resp == 'X') { 00803 rtp->f.frametype = AST_FRAME_CONTROL; 00804 rtp->f.subclass = AST_CONTROL_FLASH; 00805 } else { 00806 rtp->f.frametype = type; 00807 rtp->f.subclass = rtp->resp; 00808 } 00809 rtp->f.datalen = 0; 00810 rtp->f.samples = 0; 00811 rtp->f.mallocd = 0; 00812 rtp->f.src = "RTP"; 00813 return &rtp->f; 00814 00815 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
helper function to print attribute names
Definition at line 346 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().
00347 { 00348 switch (msg) { 00349 case STUN_MAPPED_ADDRESS: 00350 return "Mapped Address"; 00351 case STUN_RESPONSE_ADDRESS: 00352 return "Response Address"; 00353 case STUN_CHANGE_REQUEST: 00354 return "Change Request"; 00355 case STUN_SOURCE_ADDRESS: 00356 return "Source Address"; 00357 case STUN_CHANGED_ADDRESS: 00358 return "Changed Address"; 00359 case STUN_USERNAME: 00360 return "Username"; 00361 case STUN_PASSWORD: 00362 return "Password"; 00363 case STUN_MESSAGE_INTEGRITY: 00364 return "Message Integrity"; 00365 case STUN_ERROR_CODE: 00366 return "Error Code"; 00367 case STUN_UNKNOWN_ATTRIBUTES: 00368 return "Unknown Attributes"; 00369 case STUN_REFLECTED_FROM: 00370 return "Reflected From"; 00371 } 00372 return "Non-RFC3489 Attribute"; 00373 }
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 563 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().
00564 { 00565 struct stun_addr *addr = (struct stun_addr *)(attr + 1); 00566 struct sockaddr_in *sa = (struct sockaddr_in *)arg; 00567 00568 if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8) 00569 return 1; /* not us. */ 00570 sa->sin_port = addr->port; 00571 sa->sin_addr.s_addr = addr->addr; 00572 return 0; 00573 }
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 465 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_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(), and STUN_USERNAME.
Referenced by ast_rtp_read(), and ast_stun_request().
00467 { 00468 struct stun_header *hdr = (struct stun_header *)data; 00469 struct stun_attr *attr; 00470 struct stun_state st; 00471 int ret = STUN_IGNORE; 00472 int x; 00473 00474 /* On entry, 'len' is the length of the udp payload. After the 00475 * initial checks it becomes the size of unprocessed options, 00476 * while 'data' is advanced accordingly. 00477 */ 00478 if (len < sizeof(struct stun_header)) { 00479 ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header)); 00480 return -1; 00481 } 00482 len -= sizeof(struct stun_header); 00483 data += sizeof(struct stun_header); 00484 x = ntohs(hdr->msglen); /* len as advertised in the message */ 00485 if (stundebug) 00486 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x); 00487 if (x > len) { 00488 ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len); 00489 } else 00490 len = x; 00491 memset(&st, 0, sizeof(st)); 00492 while (len) { 00493 if (len < sizeof(struct stun_attr)) { 00494 ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr)); 00495 break; 00496 } 00497 attr = (struct stun_attr *)data; 00498 /* compute total attribute length */ 00499 x = ntohs(attr->len) + sizeof(struct stun_attr); 00500 if (x > len) { 00501 ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len); 00502 break; 00503 } 00504 if (stun_cb) 00505 stun_cb(attr, arg); 00506 if (stun_process_attr(&st, attr)) { 00507 ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00508 break; 00509 } 00510 /* Clear attribute id: in case previous entry was a string, 00511 * this will act as the terminator for the string. 00512 */ 00513 attr->attr = 0; 00514 data += x; 00515 len -= x; 00516 } 00517 /* Null terminate any string. 00518 * XXX NOTE, we write past the size of the buffer passed by the 00519 * caller, so this is potentially dangerous. The only thing that 00520 * saves us is that usually we read the incoming message in a 00521 * much larger buffer in the struct ast_rtp 00522 */ 00523 *data = '\0'; 00524 00525 /* Now prepare to generate a reply, which at the moment is done 00526 * only for properly formed (len == 0) STUN_BINDREQ messages. 00527 */ 00528 if (len == 0) { 00529 unsigned char respdata[1024]; 00530 struct stun_header *resp = (struct stun_header *)respdata; 00531 int resplen = 0; /* len excluding header */ 00532 int respleft = sizeof(respdata) - sizeof(struct stun_header); 00533 00534 resp->id = hdr->id; 00535 resp->msgtype = 0; 00536 resp->msglen = 0; 00537 attr = (struct stun_attr *)resp->ies; 00538 switch (ntohs(hdr->msgtype)) { 00539 case STUN_BINDREQ: 00540 if (stundebug) 00541 ast_verbose("STUN Bind Request, username: %s\n", 00542 st.username ? st.username : "<none>"); 00543 if (st.username) 00544 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00545 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00546 resp->msglen = htons(resplen); 00547 resp->msgtype = htons(STUN_BINDRESP); 00548 stun_send(s, src, resp); 00549 ret = STUN_ACCEPT; 00550 break; 00551 default: 00552 if (stundebug) 00553 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00554 } 00555 } 00556 return ret; 00557 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
helper function to print message names
Definition at line 326 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00327 { 00328 switch (msg) { 00329 case STUN_BINDREQ: 00330 return "Binding Request"; 00331 case STUN_BINDRESP: 00332 return "Binding Response"; 00333 case STUN_BINDERR: 00334 return "Binding Error Response"; 00335 case STUN_SECREQ: 00336 return "Shared Secret Request"; 00337 case STUN_SECRESP: 00338 return "Shared Secret Response"; 00339 case STUN_SECERR: 00340 return "Shared Secret Error Response"; 00341 } 00342 return "Non-RFC3489 Message"; 00343 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 381 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().
00382 { 00383 if (stundebug) 00384 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00385 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00386 switch (ntohs(attr->attr)) { 00387 case STUN_USERNAME: 00388 state->username = (const char *) (attr->value); 00389 break; 00390 case STUN_PASSWORD: 00391 state->password = (const char *) (attr->value); 00392 break; 00393 default: 00394 if (stundebug) 00395 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00396 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00397 } 00398 return 0; 00399 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
helper function to generate a random request id
Definition at line 442 of file rtp.c.
References ast_random(), stun_trans_id::id, and stun_header::id.
Referenced by ast_stun_request().
00443 { 00444 int x; 00445 for (x = 0; x < 4; x++) 00446 req->id.id[x] = ast_random(); 00447 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
wrapper to send an STUN message
Definition at line 435 of file rtp.c.
References stun_header::msglen.
Referenced by ast_stun_request(), and stun_handle_packet().
00436 { 00437 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00438 (struct sockaddr *)dst, sizeof(*dst)); 00439 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 663 of file rtp.c.
References sec.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00664 { 00665 unsigned int sec, usec, frac; 00666 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00667 usec = tv.tv_usec; 00668 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00669 *msw = sec; 00670 *lsw = frac; 00671 }
struct ast_cli_entry cli_rtcp_debug_deprecated = { .handler = handle_cli_rtcp_debug_deprecated , .summary = "Enable/Disable RTCP debugging" ,__VA_ARGS__ } [static] |
struct ast_cli_entry cli_rtcp_stats_deprecated = { .handler = handle_cli_rtcp_stats_deprecated , .summary = "Enable/Disable RTCP stats" ,__VA_ARGS__ } [static] |
struct ast_cli_entry cli_rtp[] [static] |
struct ast_cli_entry cli_rtp_debug_deprecated = { .handler = handle_cli_rtp_debug_deprecated , .summary = "Enable/Disable RTP debugging" ,__VA_ARGS__ } [static] |
struct ast_cli_entry cli_stun_debug_deprecated = { .handler = handle_cli_stun_debug_deprecated , .summary = "Enable/Disable STUN debugging" ,__VA_ARGS__ } [static] |
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
struct { ... } mimeTypes[] [static] |
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
struct rtpPayloadType payloadType |
Definition at line 1701 of file rtp.c.
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
struct sockaddr_in rtcpdebugaddr [static] |
int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static] |
struct sockaddr_in rtpdebugaddr [static] |
int rtpend = 31000 [static] |
int rtpstart = 5000 [static] |
struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static] |
Mapping between Asterisk codecs and rtp payload types.
Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s: also, our own choices for dynamic payload types. This is our master table for transmission
See http://www.iana.org/assignments/rtp-parameters for a list of assigned values
Definition at line 1744 of file rtp.c.
Referenced by ast_rtp_codec_getformat(), ast_rtp_lookup_pt(), ast_rtp_pt_default(), and ast_rtp_set_m_type().
char* subtype |
char* type |
Definition at line 1702 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), amixer_max(), ast_call_forward(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), eventhandler(), find_subscription_type(), g723_len(), h264_decap(), load_module(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), osp_lookup(), parse_information(), parse_setup(), parse_uri(), setamixer(), sla_load_config(), subscription_type2str(), and yyparse().