#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"
Go to the source code of this file.
Data Structures | |
struct | __attribute__ |
struct | ast_rtcp |
Structure defining an RTCP session. More... | |
struct | ast_rtp |
RTP session description. More... | |
struct | rtpPayloadType |
Structure representing a RTP session. More... | |
struct | stun_addr |
struct | stun_attr |
struct | stun_header |
struct | stun_state |
Defines | |
#define | DEFAULT_DTMF_TIMEOUT 3000 |
#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 |
#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 |
#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 |
Functions | |
static void | append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left) |
static void | append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left) |
static | AST_LIST_HEAD_STATIC (protos, ast_rtp_protocol) |
List of current sessions. | |
static unsigned int | ast_rtcp_calc_interval (struct ast_rtp *rtp) |
int | ast_rtcp_fd (struct ast_rtp *rtp) |
static struct ast_rtcp * | ast_rtcp_new (void) |
Initialize a new RTCP session. | |
struct ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
int | ast_rtcp_send_h261fur (void *data) |
Public function: Send an H.261 fast update request, some devices need this rather than SIP XML. | |
static int | ast_rtcp_write (const void *data) |
Write and RTCP packet to the far end. | |
static int | ast_rtcp_write_rr (const void *data) |
Send RTCP recepient's report. | |
static int | ast_rtcp_write_sr (const void *data) |
Send RTCP sender's report. | |
size_t | ast_rtp_alloc_size (void) |
Get the amount of space required to hold an RTP session. | |
enum ast_bridge_result | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk. | |
void | ast_rtp_change_source (struct ast_rtp *rtp) |
Indicate a new source of audio has dropped in and the ssrc should change. | |
int | ast_rtp_codec_getformat (int pt) |
struct ast_codec_pref * | ast_rtp_codec_getpref (struct ast_rtp *rtp) |
int | ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs) |
void | ast_rtp_destroy (struct ast_rtp *rtp) |
int | ast_rtp_early_bridge (struct ast_channel *dest, struct ast_channel *src) |
If possible, create an early bridge directly between the devices without having to send a re-invite later. | |
int | ast_rtp_fd (struct ast_rtp *rtp) |
struct ast_rtp * | ast_rtp_get_bridged (struct ast_rtp *rtp) |
void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs. | |
int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
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):. | |
struct rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
Mapping between RTP payload format codes and Asterisk codes:. | |
int | ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media) |
struct ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
Initializate a RTP session. | |
void | ast_rtp_new_init (struct ast_rtp *rtp) |
Initialize a new RTP structure. | |
struct ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr) |
Initializate a RTP session using an in_addr structure. | |
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
Register interface to channel driver. | |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
Unregister interface to channel driver. | |
void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
Setting RTP payload types from lines in a SDP description:. | |
void | ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src) |
Copy payload types between RTP structures. | |
void | ast_rtp_pt_default (struct ast_rtp *rtp) |
Set payload types to defaults. | |
static int | ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec) |
struct ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
int | ast_rtp_reload (void) |
void | ast_rtp_reset (struct ast_rtp *rtp) |
int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
generate comfort noice (CNG) | |
int | ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit) |
Send begin frames for DTMF. | |
static int | ast_rtp_senddigit_continuation (struct ast_rtp *rtp) |
Send continuation frame for DTMF. | |
int | ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit) |
Send end packets for DTMF. | |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line). | |
void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
void | ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout) |
Set rtp hold timeout. | |
void | ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period) |
set RTP keepalive interval | |
int | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options) |
Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line. | |
void | ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout) |
Set rtp timeout. | |
void | ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp) |
void | ast_rtp_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) |
void | ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable) |
Enable STUN capability. | |
int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
void | ast_rtp_stop (struct ast_rtp *rtp) |
void | ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username) |
void | ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt) |
remove setting from payload type list if the rtpmap header indicates an unknown media type | |
void | ast_rtp_update_source (struct ast_rtp *rtp) |
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f) |
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_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 int | p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int *fds, 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 *fds, 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 int | rtcp_do_debug (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_ip (int fd, int argc, char *argv[]) |
static int | rtcp_do_debug_ip_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_do_stats (int fd, int argc, char *argv[]) |
static int | rtcp_do_stats_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_no_debug (int fd, int argc, char *argv[]) |
static int | rtcp_no_debug_deprecated (int fd, int argc, char *argv[]) |
static int | rtcp_no_stats (int fd, int argc, char *argv[]) |
static int | rtcp_no_stats_deprecated (int fd, int argc, char *argv[]) |
static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
static int | rtp_do_debug (int fd, int argc, char *argv[]) |
static int | rtp_do_debug_ip (int fd, int argc, char *argv[]) |
static int | rtp_no_debug (int fd, int argc, char *argv[]) |
static int | rtp_socket (void) |
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) |
static int | stun_do_debug (int fd, int argc, char *argv[]) |
static int | stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len) |
static const char * | stun_msg2str (int msg) |
static int | stun_no_debug (int fd, int argc, char *argv[]) |
static int | stun_process_attr (struct stun_state *state, struct stun_attr *attr) |
static void | stun_req_id (struct stun_header *req) |
static int | stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp) |
static void | timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw) |
Variables | |
static struct ast_cli_entry | cli_rtp [] |
static struct ast_cli_entry | cli_rtp_no_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_debug_ip_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_no_debug_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_no_stats_deprecated |
static struct ast_cli_entry | cli_rtp_rtcp_stats_deprecated |
static struct ast_cli_entry | cli_stun_no_debug_deprecated |
static char | debug_usage [] |
static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
struct { | |
struct rtpPayloadType payloadType | |
char * subtype | |
char * type | |
} | mimeTypes [] |
static char | no_debug_usage [] |
struct stun_header | packed |
static char | rtcp_debug_usage [] |
static char | rtcp_no_debug_usage [] |
static char | rtcp_no_stats_usage [] |
static char | rtcp_stats_usage [] |
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 |
static int | rtpstart |
static struct rtpPayloadType | static_RTP_PT [MAX_RTP_PT] |
static char | stun_debug_usage [] |
static char | stun_no_debug_usage [] |
static int | stundebug |
Definition in file rtp.c.
#define DEFAULT_DTMF_TIMEOUT 3000 |
#define FLAG_3389_WARNING (1 << 0) |
#define FLAG_CALLBACK_MODE (1 << 6) |
Definition at line 194 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 195 of file rtp.c.
Referenced by ast_rtp_setdtmfcompensate(), process_rfc2833(), and send_dtmf().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 191 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 188 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 189 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 190 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 192 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 60 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 65 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 64 of file rtp.c.
Referenced by ast_rtp_reload().
#define RTCP_PT_BYE 203 |
#define RTCP_PT_FUR 192 |
Definition at line 67 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 70 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 62 of file rtp.c.
Referenced by ast_rtp_read().
#define STUN_ACCEPT (1) |
#define STUN_BINDERR 0x0111 |
#define STUN_BINDREQ 0x0001 |
Definition at line 262 of file rtp.c.
Referenced by ast_rtp_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 |
#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 274 of file rtp.c.
Referenced by ast_rtp_stun_request(), stun_attr2str(), stun_handle_packet(), and stun_process_attr().
static void append_attr_address | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
struct sockaddr_in * | sin, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 367 of file rtp.c.
References stun_addr::addr, stun_addr::family, stun_addr::port, and stun_addr::unused.
Referenced by stun_handle_packet().
00368 { 00369 int size = sizeof(**attr) + 8; 00370 struct stun_addr *addr; 00371 if (*left > size) { 00372 (*attr)->attr = htons(attrval); 00373 (*attr)->len = htons(8); 00374 addr = (struct stun_addr *)((*attr)->value); 00375 addr->unused = 0; 00376 addr->family = 0x01; 00377 addr->port = sin->sin_port; 00378 addr->addr = sin->sin_addr.s_addr; 00379 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00380 *len += size; 00381 *left -= size; 00382 } 00383 }
static void append_attr_string | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
const char * | s, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 354 of file rtp.c.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00355 { 00356 int size = sizeof(**attr) + strlen(s); 00357 if (*left > size) { 00358 (*attr)->attr = htons(attrval); 00359 (*attr)->len = htons(strlen(s)); 00360 memcpy((*attr)->value, s, strlen(s)); 00361 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00362 *len += size; 00363 *left -= size; 00364 } 00365 }
static AST_LIST_HEAD_STATIC | ( | protos | , | |
ast_rtp_protocol | ||||
) | [static] |
List of current sessions.
unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 525 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00526 { 00527 unsigned int interval; 00528 /*! \todo XXX Do a more reasonable calculation on this one 00529 * Look in RFC 3550 Section A.7 for an example*/ 00530 interval = rtcpinterval; 00531 return interval; 00532 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 518 of file rtp.c.
References ast_rtp::rtcp, and ast_rtcp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), sip_new(), and start_rtp().
static struct ast_rtcp* ast_rtcp_new | ( | void | ) | [static, read] |
Initialize a new RTCP session.
Definition at line 1874 of file rtp.c.
References ast_calloc, ast_log(), errno, free, LOG_WARNING, rtp_socket(), ast_rtcp::s, ast_rtcp::schedid, ast_rtcp::them, and ast_rtcp::us.
Referenced by ast_rtp_new_with_bindaddr().
01875 { 01876 struct ast_rtcp *rtcp; 01877 01878 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01879 return NULL; 01880 rtcp->s = rtp_socket(); 01881 rtcp->us.sin_family = AF_INET; 01882 rtcp->them.sin_family = AF_INET; 01883 rtcp->schedid = -1; 01884 01885 if (rtcp->s < 0) { 01886 free(rtcp); 01887 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01888 return NULL; 01889 } 01890 01891 return rtcp; 01892 }
Definition at line 827 of file rtp.c.
References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, ast_rtp::f, f, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, 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(), and skinny_rtp_read().
00828 { 00829 socklen_t len; 00830 int position, i, packetwords; 00831 int res; 00832 struct sockaddr_in sin; 00833 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00834 unsigned int *rtcpheader; 00835 int pt; 00836 struct timeval now; 00837 unsigned int length; 00838 int rc; 00839 double rttsec; 00840 uint64_t rtt = 0; 00841 unsigned int dlsr; 00842 unsigned int lsr; 00843 unsigned int msw; 00844 unsigned int lsw; 00845 unsigned int comp; 00846 struct ast_frame *f = &ast_null_frame; 00847 00848 if (!rtp || !rtp->rtcp) 00849 return &ast_null_frame; 00850 00851 len = sizeof(sin); 00852 00853 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00854 0, (struct sockaddr *)&sin, &len); 00855 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00856 00857 if (res < 0) { 00858 ast_assert(errno != EBADF); 00859 if (errno != EAGAIN) { 00860 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00861 return NULL; 00862 } 00863 return &ast_null_frame; 00864 } 00865 00866 packetwords = res / 4; 00867 00868 if (rtp->nat) { 00869 /* Send to whoever sent to us */ 00870 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00871 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00872 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00873 if (option_debug || rtpdebug) 00874 ast_log(LOG_DEBUG, "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)); 00875 } 00876 } 00877 00878 if (option_debug) 00879 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00880 00881 /* Process a compound packet */ 00882 position = 0; 00883 while (position < packetwords) { 00884 i = position; 00885 length = ntohl(rtcpheader[i]); 00886 pt = (length & 0xff0000) >> 16; 00887 rc = (length & 0x1f000000) >> 24; 00888 length &= 0xffff; 00889 00890 if ((i + length) > packetwords) { 00891 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00892 return &ast_null_frame; 00893 } 00894 00895 if (rtcp_debug_test_addr(&sin)) { 00896 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00897 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00898 ast_verbose("Reception reports: %d\n", rc); 00899 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00900 } 00901 00902 i += 2; /* Advance past header and ssrc */ 00903 00904 switch (pt) { 00905 case RTCP_PT_SR: 00906 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00907 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00908 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00909 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00910 00911 if (rtcp_debug_test_addr(&sin)) { 00912 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00913 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00914 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00915 } 00916 i += 5; 00917 if (rc < 1) 00918 break; 00919 /* Intentional fall through */ 00920 case RTCP_PT_RR: 00921 /* Don't handle multiple reception reports (rc > 1) yet */ 00922 /* Calculate RTT per RFC */ 00923 gettimeofday(&now, NULL); 00924 timeval2ntp(now, &msw, &lsw); 00925 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00926 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00927 lsr = ntohl(rtcpheader[i + 4]); 00928 dlsr = ntohl(rtcpheader[i + 5]); 00929 rtt = comp - lsr - dlsr; 00930 00931 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00932 sess->ee_delay = (eedelay * 1000) / 65536; */ 00933 if (rtt < 4294) { 00934 rtt = (rtt * 1000000) >> 16; 00935 } else { 00936 rtt = (rtt * 1000) >> 16; 00937 rtt *= 1000; 00938 } 00939 rtt = rtt / 1000.; 00940 rttsec = rtt / 1000.; 00941 00942 if (comp - dlsr >= lsr) { 00943 rtp->rtcp->accumulated_transit += rttsec; 00944 rtp->rtcp->rtt = rttsec; 00945 if (rtp->rtcp->maxrtt<rttsec) 00946 rtp->rtcp->maxrtt = rttsec; 00947 if (rtp->rtcp->minrtt>rttsec) 00948 rtp->rtcp->minrtt = rttsec; 00949 } else if (rtcp_debug_test_addr(&sin)) { 00950 ast_verbose("Internal RTCP NTP clock skew detected: " 00951 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 00952 "diff=%d\n", 00953 lsr, comp, dlsr, dlsr / 65536, 00954 (dlsr % 65536) * 1000 / 65536, 00955 dlsr - (comp - lsr)); 00956 } 00957 } 00958 00959 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00960 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00961 if (rtcp_debug_test_addr(&sin)) { 00962 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00963 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00964 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00965 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00966 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00967 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00968 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00969 if (rtt) 00970 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 00971 } 00972 break; 00973 case RTCP_PT_FUR: 00974 if (rtcp_debug_test_addr(&sin)) 00975 ast_verbose("Received an RTCP Fast Update Request\n"); 00976 rtp->f.frametype = AST_FRAME_CONTROL; 00977 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00978 rtp->f.datalen = 0; 00979 rtp->f.samples = 0; 00980 rtp->f.mallocd = 0; 00981 rtp->f.src = "RTP"; 00982 f = &rtp->f; 00983 break; 00984 case RTCP_PT_SDES: 00985 if (rtcp_debug_test_addr(&sin)) 00986 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00987 break; 00988 case RTCP_PT_BYE: 00989 if (rtcp_debug_test_addr(&sin)) 00990 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00991 break; 00992 default: 00993 if (option_debug) 00994 ast_log(LOG_DEBUG, "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)); 00995 break; 00996 } 00997 position += (length + 1); 00998 } 00999 01000 return f; 01001 }
int ast_rtcp_send_h261fur | ( | void * | data | ) |
Public function: Send an H.261 fast update request, some devices need this rather than SIP XML.
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
Definition at line 2366 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02367 { 02368 struct ast_rtp *rtp = data; 02369 int res; 02370 02371 rtp->rtcp->sendfur = 1; 02372 res = ast_rtcp_write(data); 02373 02374 return res; 02375 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2583 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().
02584 { 02585 struct ast_rtp *rtp = (struct ast_rtp *)data; 02586 int res; 02587 02588 if (!rtp || !rtp->rtcp) 02589 return 0; 02590 02591 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02592 res = ast_rtcp_write_sr(data); 02593 else 02594 res = ast_rtcp_write_rr(data); 02595 02596 return res; 02597 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recepient's report.
Definition at line 2488 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, and ast_rtp::themssrc.
Referenced by ast_rtcp_write().
02489 { 02490 struct ast_rtp *rtp = (struct ast_rtp *)data; 02491 int res; 02492 int len = 32; 02493 unsigned int lost; 02494 unsigned int extended; 02495 unsigned int expected; 02496 unsigned int expected_interval; 02497 unsigned int received_interval; 02498 int lost_interval; 02499 struct timeval now; 02500 unsigned int *rtcpheader; 02501 char bdata[1024]; 02502 struct timeval dlsr; 02503 int fraction; 02504 02505 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02506 return 0; 02507 02508 if (!rtp->rtcp->them.sin_addr.s_addr) { 02509 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02510 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02511 return 0; 02512 } 02513 02514 extended = rtp->cycles + rtp->lastrxseqno; 02515 expected = extended - rtp->seedrxseqno + 1; 02516 lost = expected - rtp->rxcount; 02517 expected_interval = expected - rtp->rtcp->expected_prior; 02518 rtp->rtcp->expected_prior = expected; 02519 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02520 rtp->rtcp->received_prior = rtp->rxcount; 02521 lost_interval = expected_interval - received_interval; 02522 if (expected_interval == 0 || lost_interval <= 0) 02523 fraction = 0; 02524 else 02525 fraction = (lost_interval << 8) / expected_interval; 02526 gettimeofday(&now, NULL); 02527 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02528 rtcpheader = (unsigned int *)bdata; 02529 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02530 rtcpheader[1] = htonl(rtp->ssrc); 02531 rtcpheader[2] = htonl(rtp->themssrc); 02532 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02533 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02534 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02535 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02536 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02537 02538 if (rtp->rtcp->sendfur) { 02539 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02540 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02541 len += 8; 02542 rtp->rtcp->sendfur = 0; 02543 } 02544 02545 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02546 it can change mid call, and SDES can't) */ 02547 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02548 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02549 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02550 len += 12; 02551 02552 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02553 02554 if (res < 0) { 02555 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02556 /* Remove the scheduler */ 02557 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02558 return 0; 02559 } 02560 02561 rtp->rtcp->rr_count++; 02562 02563 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02564 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02565 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02566 " IA jitter: %.4f\n" 02567 " Their last SR: %u\n" 02568 " DLSR: %4.4f (sec)\n\n", 02569 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02570 ntohs(rtp->rtcp->them.sin_port), 02571 rtp->ssrc, rtp->themssrc, fraction, lost, 02572 rtp->rxjitter, 02573 rtp->rtcp->themrxlsr, 02574 (double)(ntohl(rtcpheader[7])/65536.0)); 02575 } 02576 02577 return res; 02578 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2378 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, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len, LOG_ERROR, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.
Referenced by ast_rtcp_write().
02379 { 02380 struct ast_rtp *rtp = (struct ast_rtp *)data; 02381 int res; 02382 int len = 0; 02383 struct timeval now; 02384 unsigned int now_lsw; 02385 unsigned int now_msw; 02386 unsigned int *rtcpheader; 02387 unsigned int lost; 02388 unsigned int extended; 02389 unsigned int expected; 02390 unsigned int expected_interval; 02391 unsigned int received_interval; 02392 int lost_interval; 02393 int fraction; 02394 struct timeval dlsr; 02395 char bdata[512]; 02396 02397 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02398 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02399 return 0; 02400 02401 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02402 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02403 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02404 return 0; 02405 } 02406 02407 gettimeofday(&now, NULL); 02408 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02409 rtcpheader = (unsigned int *)bdata; 02410 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02411 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02412 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02413 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02414 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02415 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02416 len += 28; 02417 02418 extended = rtp->cycles + rtp->lastrxseqno; 02419 expected = extended - rtp->seedrxseqno + 1; 02420 if (rtp->rxcount > expected) 02421 expected += rtp->rxcount - expected; 02422 lost = expected - rtp->rxcount; 02423 expected_interval = expected - rtp->rtcp->expected_prior; 02424 rtp->rtcp->expected_prior = expected; 02425 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02426 rtp->rtcp->received_prior = rtp->rxcount; 02427 lost_interval = expected_interval - received_interval; 02428 if (expected_interval == 0 || lost_interval <= 0) 02429 fraction = 0; 02430 else 02431 fraction = (lost_interval << 8) / expected_interval; 02432 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02433 rtcpheader[7] = htonl(rtp->themssrc); 02434 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02435 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02436 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02437 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02438 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02439 len += 24; 02440 02441 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02442 02443 if (rtp->rtcp->sendfur) { 02444 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02445 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02446 len += 8; 02447 rtp->rtcp->sendfur = 0; 02448 } 02449 02450 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02451 /* it can change mid call, and SDES can't) */ 02452 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02453 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02454 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02455 len += 12; 02456 02457 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02458 if (res < 0) { 02459 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)); 02460 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02461 return 0; 02462 } 02463 02464 /* FIXME Don't need to get a new one */ 02465 gettimeofday(&rtp->rtcp->txlsr, NULL); 02466 rtp->rtcp->sr_count++; 02467 02468 rtp->rtcp->lastsrtxcount = rtp->txcount; 02469 02470 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02471 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02472 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02473 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02474 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02475 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02476 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02477 ast_verbose(" Report block:\n"); 02478 ast_verbose(" Fraction lost: %u\n", fraction); 02479 ast_verbose(" Cumulative loss: %u\n", lost); 02480 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02481 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02482 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02483 } 02484 return res; 02485 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 398 of file rtp.c.
Referenced by process_sdp().
00399 { 00400 return sizeof(struct ast_rtp); 00401 }
enum ast_bridge_result ast_rtp_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
int | timeoutms | |||
) |
Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
Definition at line 3304 of file rtp.c.
References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), 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_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
03305 { 03306 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03307 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03308 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03309 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03310 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03311 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03312 int codec0 = 0, codec1 = 0; 03313 void *pvt0 = NULL, *pvt1 = NULL; 03314 03315 /* Lock channels */ 03316 ast_channel_lock(c0); 03317 while(ast_channel_trylock(c1)) { 03318 ast_channel_unlock(c0); 03319 usleep(1); 03320 ast_channel_lock(c0); 03321 } 03322 03323 /* Ensure neither channel got hungup during lock avoidance */ 03324 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03325 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03326 ast_channel_unlock(c0); 03327 ast_channel_unlock(c1); 03328 return AST_BRIDGE_FAILED; 03329 } 03330 03331 /* Find channel driver interfaces */ 03332 if (!(pr0 = get_proto(c0))) { 03333 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03334 ast_channel_unlock(c0); 03335 ast_channel_unlock(c1); 03336 return AST_BRIDGE_FAILED; 03337 } 03338 if (!(pr1 = get_proto(c1))) { 03339 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03340 ast_channel_unlock(c0); 03341 ast_channel_unlock(c1); 03342 return AST_BRIDGE_FAILED; 03343 } 03344 03345 /* Get channel specific interface structures */ 03346 pvt0 = c0->tech_pvt; 03347 pvt1 = c1->tech_pvt; 03348 03349 /* Get audio and video interface (if native bridge is possible) */ 03350 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03351 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03352 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03353 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03354 03355 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03356 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03357 audio_p0_res = AST_RTP_GET_FAILED; 03358 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03359 audio_p1_res = AST_RTP_GET_FAILED; 03360 03361 /* Check if a bridge is possible (partial/native) */ 03362 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03363 /* Somebody doesn't want to play... */ 03364 ast_channel_unlock(c0); 03365 ast_channel_unlock(c1); 03366 return AST_BRIDGE_FAILED_NOWARN; 03367 } 03368 03369 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03370 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03371 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03372 audio_p0_res = AST_RTP_TRY_PARTIAL; 03373 } 03374 03375 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03376 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03377 audio_p1_res = AST_RTP_TRY_PARTIAL; 03378 } 03379 03380 /* If both sides are not using the same method of DTMF transmission 03381 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03382 * -------------------------------------------------- 03383 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03384 * |-----------|------------|-----------------------| 03385 * | Inband | False | True | 03386 * | RFC2833 | True | True | 03387 * | SIP INFO | False | False | 03388 * -------------------------------------------------- 03389 * However, if DTMF from both channels is being monitored by the core, then 03390 * we can still do packet-to-packet bridging, because passing through the 03391 * core will handle DTMF mode translation. 03392 */ 03393 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03394 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03395 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03396 ast_channel_unlock(c0); 03397 ast_channel_unlock(c1); 03398 return AST_BRIDGE_FAILED_NOWARN; 03399 } 03400 audio_p0_res = AST_RTP_TRY_PARTIAL; 03401 audio_p1_res = AST_RTP_TRY_PARTIAL; 03402 } 03403 03404 /* If we need to feed frames into the core don't do a P2P bridge */ 03405 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 03406 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 03407 ast_channel_unlock(c0); 03408 ast_channel_unlock(c1); 03409 return AST_BRIDGE_FAILED_NOWARN; 03410 } 03411 03412 /* Get codecs from both sides */ 03413 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03414 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03415 if (codec0 && codec1 && !(codec0 & codec1)) { 03416 /* Hey, we can't do native bridging if both parties speak different codecs */ 03417 if (option_debug) 03418 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03419 ast_channel_unlock(c0); 03420 ast_channel_unlock(c1); 03421 return AST_BRIDGE_FAILED_NOWARN; 03422 } 03423 03424 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03425 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03426 struct ast_format_list fmt0, fmt1; 03427 03428 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03429 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03430 if (option_debug) 03431 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03432 ast_channel_unlock(c0); 03433 ast_channel_unlock(c1); 03434 return AST_BRIDGE_FAILED_NOWARN; 03435 } 03436 /* They must also be using the same packetization */ 03437 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03438 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03439 if (fmt0.cur_ms != fmt1.cur_ms) { 03440 if (option_debug) 03441 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03442 ast_channel_unlock(c0); 03443 ast_channel_unlock(c1); 03444 return AST_BRIDGE_FAILED_NOWARN; 03445 } 03446 03447 if (option_verbose > 2) 03448 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03449 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03450 } else { 03451 if (option_verbose > 2) 03452 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03453 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03454 } 03455 03456 return res; 03457 }
void ast_rtp_change_source | ( | struct ast_rtp * | instance | ) |
Indicate a new source of audio has dropped in and the ssrc should change.
instance | Instance that the new media source is feeding into |
ast_rtp_instance_change_source(instance);
This indicates that the source of media that is feeding the instance pointed to by instance has changed and that the marker bit should be set and the SSRC updated.
Definition at line 2021 of file rtp.c.
References ast_log(), ast_random(), LOG_DEBUG, ast_rtp::set_marker_bit, and ast_rtp::ssrc.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), and skinny_indicate().
02022 { 02023 unsigned int ssrc = ast_random(); 02024 /* We simply set this bit so that the next packet sent will have the marker bit turned on */ 02025 rtp->set_marker_bit = 1; 02026 ast_log(LOG_DEBUG, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc); 02027 02028 rtp->ssrc = ssrc; 02029 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2748 of file rtp.c.
References rtpPayloadType::code, and MAX_RTP_PT.
Referenced by process_sdp().
02749 { 02750 if (pt < 0 || pt > MAX_RTP_PT) 02751 return 0; /* bogus payload type */ 02752 02753 if (static_RTP_PT[pt].isAstFormat) 02754 return static_RTP_PT[pt].code; 02755 else 02756 return 0; 02757 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) | [read] |
Definition at line 2743 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
02744 { 02745 return &rtp->pref; 02746 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2730 of file rtp.c.
References ast_smoother_free(), ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, and ast_rtp::smoother.
Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().
02731 { 02732 int x; 02733 for (x = 0; x < 32; x++) { /* Ugly way */ 02734 rtp->pref.order[x] = prefs->order[x]; 02735 rtp->pref.framing[x] = prefs->framing[x]; 02736 } 02737 if (rtp->smoother) 02738 ast_smoother_free(rtp->smoother); 02739 rtp->smoother = NULL; 02740 return 0; 02741 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2149 of file rtp.c.
References ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose(), ast_rtp::bridge_lock, ast_rtcp::expected_prior, free, ast_rtp::io, ast_rtp::ioid, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.
Referenced by __oh323_destroy(), __sip_destroy(), check_user_full(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().
02150 { 02151 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02152 /*Print some info on the call here */ 02153 ast_verbose(" RTP-stats\n"); 02154 ast_verbose("* Our Receiver:\n"); 02155 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02156 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02157 ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02158 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02159 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02160 ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count); 02161 ast_verbose("* Our Sender:\n"); 02162 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02163 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02164 ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost); 02165 ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0); 02166 ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count); 02167 ast_verbose(" RTT: %f\n", rtp->rtcp->rtt); 02168 } 02169 02170 if (rtp->smoother) 02171 ast_smoother_free(rtp->smoother); 02172 if (rtp->ioid) 02173 ast_io_remove(rtp->io, rtp->ioid); 02174 if (rtp->s > -1) 02175 close(rtp->s); 02176 if (rtp->rtcp) { 02177 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02178 close(rtp->rtcp->s); 02179 free(rtp->rtcp); 02180 rtp->rtcp=NULL; 02181 } 02182 02183 ast_mutex_destroy(&rtp->bridge_lock); 02184 02185 free(rtp); 02186 }
int ast_rtp_early_bridge | ( | struct ast_channel * | dest, | |
struct ast_channel * | src | |||
) |
If possible, create an early bridge directly between the devices without having to send a re-invite later.
Definition at line 1491 of file rtp.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, 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_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01492 { 01493 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01494 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01495 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01496 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01497 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01498 int srccodec, destcodec, nat_active = 0; 01499 01500 /* Lock channels */ 01501 ast_channel_lock(dest); 01502 if (src) { 01503 while(ast_channel_trylock(src)) { 01504 ast_channel_unlock(dest); 01505 usleep(1); 01506 ast_channel_lock(dest); 01507 } 01508 } 01509 01510 /* Find channel driver interfaces */ 01511 destpr = get_proto(dest); 01512 if (src) 01513 srcpr = get_proto(src); 01514 if (!destpr) { 01515 if (option_debug) 01516 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01517 ast_channel_unlock(dest); 01518 if (src) 01519 ast_channel_unlock(src); 01520 return 0; 01521 } 01522 if (!srcpr) { 01523 if (option_debug) 01524 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01525 ast_channel_unlock(dest); 01526 if (src) 01527 ast_channel_unlock(src); 01528 return 0; 01529 } 01530 01531 /* Get audio and video interface (if native bridge is possible) */ 01532 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01533 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01534 if (srcpr) { 01535 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01536 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01537 } 01538 01539 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01540 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01541 /* Somebody doesn't want to play... */ 01542 ast_channel_unlock(dest); 01543 if (src) 01544 ast_channel_unlock(src); 01545 return 0; 01546 } 01547 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01548 srccodec = srcpr->get_codec(src); 01549 else 01550 srccodec = 0; 01551 if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec) 01552 destcodec = destpr->get_codec(dest); 01553 else 01554 destcodec = 0; 01555 /* Ensure we have at least one matching codec */ 01556 if (!(srccodec & destcodec)) { 01557 ast_channel_unlock(dest); 01558 if (src) 01559 ast_channel_unlock(src); 01560 return 0; 01561 } 01562 /* Consider empty media as non-existant */ 01563 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01564 srcp = NULL; 01565 /* If the client has NAT stuff turned on then just safe NAT is active */ 01566 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01567 nat_active = 1; 01568 /* Bridge media early */ 01569 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01570 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01571 ast_channel_unlock(dest); 01572 if (src) 01573 ast_channel_unlock(src); 01574 if (option_debug) 01575 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01576 return 1; 01577 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 513 of file rtp.c.
References ast_rtp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().
00514 { 00515 return rtp->s; 00516 }
Definition at line 2060 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by __sip_destroy(), and ast_rtp_read().
02061 { 02062 struct ast_rtp *bridged = NULL; 02063 02064 ast_mutex_lock(&rtp->bridge_lock); 02065 bridged = rtp->bridged; 02066 ast_mutex_unlock(&rtp->bridge_lock); 02067 02068 return bridged; 02069 }
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 1713 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().
01715 { 01716 int pt; 01717 01718 ast_mutex_lock(&rtp->bridge_lock); 01719 01720 *astFormats = *nonAstFormats = 0; 01721 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01722 if (rtp->current_RTP_PT[pt].isAstFormat) { 01723 *astFormats |= rtp->current_RTP_PT[pt].code; 01724 } else { 01725 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01726 } 01727 } 01728 01729 ast_mutex_unlock(&rtp->bridge_lock); 01730 01731 return; 01732 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2042 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), bridge_native_loop(), do_monitor(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
02043 { 02044 if ((them->sin_family != AF_INET) || 02045 (them->sin_port != rtp->them.sin_port) || 02046 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02047 them->sin_family = AF_INET; 02048 them->sin_port = rtp->them.sin_port; 02049 them->sin_addr = rtp->them.sin_addr; 02050 return 1; 02051 } 02052 return 0; 02053 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2105 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_rtcp::rtt, ast_rtp_quality::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.
Referenced by acf_channel_read(), handle_request_bye(), and sip_hangup().
02106 { 02107 /* 02108 *ssrc our ssrc 02109 *themssrc their ssrc 02110 *lp lost packets 02111 *rxjitter our calculated jitter(rx) 02112 *rxcount no. received packets 02113 *txjitter reported jitter of the other end 02114 *txcount transmitted packets 02115 *rlp remote lost packets 02116 *rtt round trip time 02117 */ 02118 02119 if (qual && rtp) { 02120 qual->local_ssrc = rtp->ssrc; 02121 qual->local_jitter = rtp->rxjitter; 02122 qual->local_count = rtp->rxcount; 02123 qual->remote_ssrc = rtp->themssrc; 02124 qual->remote_count = rtp->txcount; 02125 if (rtp->rtcp) { 02126 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02127 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02128 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02129 qual->rtt = rtp->rtcp->rtt; 02130 } 02131 } 02132 if (rtp->rtcp) { 02133 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02134 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02135 rtp->ssrc, 02136 rtp->themssrc, 02137 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02138 rtp->rxjitter, 02139 rtp->rxcount, 02140 (double)rtp->rtcp->reported_jitter / 65536.0, 02141 rtp->txcount, 02142 rtp->rtcp->reported_lost, 02143 rtp->rtcp->rtt); 02144 return rtp->rtcp->quality; 02145 } else 02146 return "<Unknown> - RTP/RTCP has already been destroyed"; 02147 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 568 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by do_monitor().
00569 { 00570 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00571 return 0; 00572 return rtp->rtpholdtimeout; 00573 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 576 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by do_monitor().
00577 { 00578 return rtp->rtpkeepalive; 00579 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 560 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by do_monitor().
00561 { 00562 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00563 return 0; 00564 return rtp->rtptimeout; 00565 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2055 of file rtp.c.
References ast_rtp::us.
Referenced by add_sdp(), external_rtp_create(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), and oh323_set_rtp_peer().
int ast_rtp_getnat | ( | struct ast_rtp * | rtp | ) |
Definition at line 596 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00597 { 00598 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00599 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 3842 of file rtp.c.
References ast_cli_register_multiple(), and ast_rtp_reload().
Referenced by main().
03843 { 03844 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03845 ast_rtp_reload(); 03846 }
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 1756 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), and bridge_p2p_rtp_write().
01757 { 01758 int pt = 0; 01759 01760 ast_mutex_lock(&rtp->bridge_lock); 01761 01762 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01763 code == rtp->rtp_lookup_code_cache_code) { 01764 /* Use our cached mapping, to avoid the overhead of the loop below */ 01765 pt = rtp->rtp_lookup_code_cache_result; 01766 ast_mutex_unlock(&rtp->bridge_lock); 01767 return pt; 01768 } 01769 01770 /* Check the dynamic list first */ 01771 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01772 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01773 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01774 rtp->rtp_lookup_code_cache_code = code; 01775 rtp->rtp_lookup_code_cache_result = pt; 01776 ast_mutex_unlock(&rtp->bridge_lock); 01777 return pt; 01778 } 01779 } 01780 01781 /* Then the static list */ 01782 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01783 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01784 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01785 rtp->rtp_lookup_code_cache_code = code; 01786 rtp->rtp_lookup_code_cache_result = pt; 01787 ast_mutex_unlock(&rtp->bridge_lock); 01788 return pt; 01789 } 01790 } 01791 01792 ast_mutex_unlock(&rtp->bridge_lock); 01793 01794 return -1; 01795 }
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 1816 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len, and name.
Referenced by process_sdp().
01818 { 01819 int format; 01820 unsigned len; 01821 char *end = buf; 01822 char *start = buf; 01823 01824 if (!buf || !size) 01825 return NULL; 01826 01827 snprintf(end, size, "0x%x (", capability); 01828 01829 len = strlen(end); 01830 end += len; 01831 size -= len; 01832 start = end; 01833 01834 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01835 if (capability & format) { 01836 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01837 01838 snprintf(end, size, "%s|", name); 01839 len = strlen(end); 01840 end += len; 01841 size -= len; 01842 } 01843 } 01844 01845 if (start == end) 01846 snprintf(start, size, "nothing)"); 01847 else if (size > 1) 01848 *(end -1) = ')'; 01849 01850 return buf; 01851 }
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 1797 of file rtp.c.
References 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(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().
01799 { 01800 unsigned int i; 01801 01802 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01803 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01804 if (isAstFormat && 01805 (code == AST_FORMAT_G726_AAL2) && 01806 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01807 return "G726-32"; 01808 else 01809 return mimeTypes[i].subtype; 01810 } 01811 } 01812 01813 return ""; 01814 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) | [read] |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1734 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().
01735 { 01736 struct rtpPayloadType result; 01737 01738 result.isAstFormat = result.code = 0; 01739 01740 if (pt < 0 || pt > MAX_RTP_PT) 01741 return result; /* bogus payload type */ 01742 01743 /* Start with negotiated codecs */ 01744 ast_mutex_lock(&rtp->bridge_lock); 01745 result = rtp->current_RTP_PT[pt]; 01746 ast_mutex_unlock(&rtp->bridge_lock); 01747 01748 /* If it doesn't exist, check our static RTP type list, just in case */ 01749 if (!result.code) 01750 result = static_RTP_PT[pt]; 01751 01752 return result; 01753 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1579 of file rtp.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, 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_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01580 { 01581 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01582 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01583 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01584 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01585 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01586 int srccodec, destcodec; 01587 01588 /* Lock channels */ 01589 ast_channel_lock(dest); 01590 while(ast_channel_trylock(src)) { 01591 ast_channel_unlock(dest); 01592 usleep(1); 01593 ast_channel_lock(dest); 01594 } 01595 01596 /* Find channel driver interfaces */ 01597 if (!(destpr = get_proto(dest))) { 01598 if (option_debug) 01599 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01600 ast_channel_unlock(dest); 01601 ast_channel_unlock(src); 01602 return 0; 01603 } 01604 if (!(srcpr = get_proto(src))) { 01605 if (option_debug) 01606 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01607 ast_channel_unlock(dest); 01608 ast_channel_unlock(src); 01609 return 0; 01610 } 01611 01612 /* Get audio and video interface (if native bridge is possible) */ 01613 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01614 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01615 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01616 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01617 01618 /* Ensure we have at least one matching codec */ 01619 if (srcpr->get_codec) 01620 srccodec = srcpr->get_codec(src); 01621 else 01622 srccodec = 0; 01623 if (destpr->get_codec) 01624 destcodec = destpr->get_codec(dest); 01625 else 01626 destcodec = 0; 01627 01628 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01629 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) { 01630 /* Somebody doesn't want to play... */ 01631 ast_channel_unlock(dest); 01632 ast_channel_unlock(src); 01633 return 0; 01634 } 01635 ast_rtp_pt_copy(destp, srcp); 01636 if (vdestp && vsrcp) 01637 ast_rtp_pt_copy(vdestp, vsrcp); 01638 if (media) { 01639 /* Bridge early */ 01640 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01641 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01642 } 01643 ast_channel_unlock(dest); 01644 ast_channel_unlock(src); 01645 if (option_debug) 01646 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01647 return 1; 01648 }
struct ast_rtp* ast_rtp_new | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode | |||
) | [read] |
Initializate a RTP session.
sched | ||
io | ||
rtcpenable | ||
callbackmode |
Definition at line 1998 of file rtp.c.
References ast_rtp_new_with_bindaddr().
01999 { 02000 struct in_addr ia; 02001 02002 memset(&ia, 0, sizeof(ia)); 02003 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02004 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1898 of file rtp.c.
References ast_mutex_init(), ast_random(), ast_set_flag, ast_rtp::bridge_lock, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, and ast_rtp::us.
Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().
01899 { 01900 ast_mutex_init(&rtp->bridge_lock); 01901 01902 rtp->them.sin_family = AF_INET; 01903 rtp->us.sin_family = AF_INET; 01904 rtp->ssrc = ast_random(); 01905 rtp->seqno = ast_random() & 0xffff; 01906 ast_set_flag(rtp, FLAG_HAS_DTMF); 01907 01908 return; 01909 }
struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode, | |||
struct in_addr | in | |||
) | [read] |
Initializate a RTP session using an in_addr structure.
This fuction gets called by ast_rtp_new().
sched | ||
io | ||
rtcpenable | ||
callbackmode | ||
in |
Definition at line 1911 of file rtp.c.
References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, errno, FLAG_CALLBACK_MODE, free, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::us, and ast_rtp::us.
Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), sip_alloc(), and start_rtp().
01912 { 01913 struct ast_rtp *rtp; 01914 int x; 01915 int first; 01916 int startplace; 01917 01918 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01919 return NULL; 01920 01921 ast_rtp_new_init(rtp); 01922 01923 rtp->s = rtp_socket(); 01924 if (rtp->s < 0) { 01925 free(rtp); 01926 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01927 return NULL; 01928 } 01929 if (sched && rtcpenable) { 01930 rtp->sched = sched; 01931 rtp->rtcp = ast_rtcp_new(); 01932 } 01933 01934 /* Select a random port number in the range of possible RTP */ 01935 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01936 x = x & ~1; 01937 /* Save it for future references. */ 01938 startplace = x; 01939 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01940 for (;;) { 01941 /* Must be an even port number by RTP spec */ 01942 rtp->us.sin_port = htons(x); 01943 rtp->us.sin_addr = addr; 01944 /* If there's rtcp, initialize it as well. */ 01945 if (rtp->rtcp) { 01946 rtp->rtcp->us.sin_port = htons(x + 1); 01947 rtp->rtcp->us.sin_addr = addr; 01948 } 01949 /* Try to bind it/them. */ 01950 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01951 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01952 break; 01953 if (!first) { 01954 /* Primary bind succeeded! Gotta recreate it */ 01955 close(rtp->s); 01956 rtp->s = rtp_socket(); 01957 } 01958 if (errno != EADDRINUSE) { 01959 /* We got an error that wasn't expected, abort! */ 01960 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01961 close(rtp->s); 01962 if (rtp->rtcp) { 01963 close(rtp->rtcp->s); 01964 free(rtp->rtcp); 01965 } 01966 free(rtp); 01967 return NULL; 01968 } 01969 /* The port was used, increment it (by two). */ 01970 x += 2; 01971 /* Did we go over the limit ? */ 01972 if (x > rtpend) 01973 /* then, start from the begingig. */ 01974 x = (rtpstart + 1) & ~1; 01975 /* Check if we reached the place were we started. */ 01976 if (x == startplace) { 01977 /* If so, there's no ports available. */ 01978 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01979 close(rtp->s); 01980 if (rtp->rtcp) { 01981 close(rtp->rtcp->s); 01982 free(rtp->rtcp); 01983 } 01984 free(rtp); 01985 return NULL; 01986 } 01987 } 01988 rtp->sched = sched; 01989 rtp->io = io; 01990 if (callbackmode) { 01991 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01992 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01993 } 01994 ast_rtp_pt_default(rtp); 01995 return rtp; 01996 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2859 of file rtp.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, protos, and ast_rtp_protocol::type.
Referenced by load_module().
02860 { 02861 struct ast_rtp_protocol *cur; 02862 02863 AST_LIST_LOCK(&protos); 02864 AST_LIST_TRAVERSE(&protos, cur, list) { 02865 if (!strcmp(cur->type, proto->type)) { 02866 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02867 AST_LIST_UNLOCK(&protos); 02868 return -1; 02869 } 02870 } 02871 AST_LIST_INSERT_HEAD(&protos, proto, list); 02872 AST_LIST_UNLOCK(&protos); 02873 02874 return 0; 02875 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2851 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.
Referenced by load_module(), and unload_module().
02852 { 02853 AST_LIST_LOCK(&protos); 02854 AST_LIST_REMOVE(&protos, proto, list); 02855 AST_LIST_UNLOCK(&protos); 02856 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1415 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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().
01416 { 01417 int i; 01418 01419 if (!rtp) 01420 return; 01421 01422 ast_mutex_lock(&rtp->bridge_lock); 01423 01424 for (i = 0; i < MAX_RTP_PT; ++i) { 01425 rtp->current_RTP_PT[i].isAstFormat = 0; 01426 rtp->current_RTP_PT[i].code = 0; 01427 } 01428 01429 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01430 rtp->rtp_lookup_code_cache_code = 0; 01431 rtp->rtp_lookup_code_cache_result = 0; 01432 01433 ast_mutex_unlock(&rtp->bridge_lock); 01434 }
Copy payload types between RTP structures.
Definition at line 1455 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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().
01456 { 01457 unsigned int i; 01458 01459 ast_mutex_lock(&dest->bridge_lock); 01460 ast_mutex_lock(&src->bridge_lock); 01461 01462 for (i=0; i < MAX_RTP_PT; ++i) { 01463 dest->current_RTP_PT[i].isAstFormat = 01464 src->current_RTP_PT[i].isAstFormat; 01465 dest->current_RTP_PT[i].code = 01466 src->current_RTP_PT[i].code; 01467 } 01468 dest->rtp_lookup_code_cache_isAstFormat = 0; 01469 dest->rtp_lookup_code_cache_code = 0; 01470 dest->rtp_lookup_code_cache_result = 0; 01471 01472 ast_mutex_unlock(&src->bridge_lock); 01473 ast_mutex_unlock(&dest->bridge_lock); 01474 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1436 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by ast_rtp_new_with_bindaddr().
01437 { 01438 int i; 01439 01440 ast_mutex_lock(&rtp->bridge_lock); 01441 01442 /* Initialize to default payload types */ 01443 for (i = 0; i < MAX_RTP_PT; ++i) { 01444 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01445 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01446 } 01447 01448 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01449 rtp->rtp_lookup_code_cache_code = 0; 01450 rtp->rtp_lookup_code_cache_result = 0; 01451 01452 ast_mutex_unlock(&rtp->bridge_lock); 01453 }
Definition at line 2634 of file rtp.c.
References AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_frame::frametype, ast_rtp::lastdigitts, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_DEBUG, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seqno, ast_rtp::set_marker_bit, ast_rtp::ssrc, ast_frame::subclass, ast_rtp::them, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
02635 { 02636 unsigned char *rtpheader; 02637 int hdrlen = 12; 02638 int res; 02639 unsigned int ms; 02640 int pred; 02641 int mark = 0; 02642 02643 ms = calc_txstamp(rtp, &f->delivery); 02644 /* Default prediction */ 02645 if (f->frametype == AST_FRAME_VOICE) { 02646 pred = rtp->lastts + f->samples; 02647 02648 /* Re-calculate last TS */ 02649 rtp->lastts = rtp->lastts + ms * 8; 02650 if (ast_tvzero(f->delivery)) { 02651 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02652 and if so, go with our prediction */ 02653 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02654 rtp->lastts = pred; 02655 else { 02656 if (option_debug > 2) 02657 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02658 mark = 1; 02659 } 02660 } 02661 } else if (f->frametype == AST_FRAME_VIDEO) { 02662 mark = f->subclass & 0x1; 02663 pred = rtp->lastovidtimestamp + f->samples; 02664 /* Re-calculate last TS */ 02665 rtp->lastts = rtp->lastts + ms * 90; 02666 /* If it's close to our prediction, go for it */ 02667 if (ast_tvzero(f->delivery)) { 02668 if (abs(rtp->lastts - pred) < 7200) { 02669 rtp->lastts = pred; 02670 rtp->lastovidtimestamp += f->samples; 02671 } else { 02672 if (option_debug > 2) 02673 ast_log(LOG_DEBUG, "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); 02674 rtp->lastovidtimestamp = rtp->lastts; 02675 } 02676 } 02677 } 02678 02679 /* If we have been explicitly told to set the marker bit do so */ 02680 if (rtp->set_marker_bit) { 02681 mark = 1; 02682 rtp->set_marker_bit = 0; 02683 } 02684 02685 /* If the timestamp for non-digit packets has moved beyond the timestamp 02686 for digits, update the digit timestamp. 02687 */ 02688 if (rtp->lastts > rtp->lastdigitts) 02689 rtp->lastdigitts = rtp->lastts; 02690 02691 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 02692 rtp->lastts = f->ts * 8; 02693 02694 /* Get a pointer to the header */ 02695 rtpheader = (unsigned char *)(f->data - hdrlen); 02696 02697 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02698 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02699 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02700 02701 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02702 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02703 if (res <0) { 02704 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02705 ast_log(LOG_DEBUG, "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)); 02706 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02707 /* Only give this error message once if we are not RTP debugging */ 02708 if (option_debug || rtpdebug) 02709 ast_log(LOG_DEBUG, "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)); 02710 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02711 } 02712 } else { 02713 rtp->txcount++; 02714 rtp->txoctetcount +=(res - hdrlen); 02715 02716 if (rtp->rtcp && rtp->rtcp->schedid < 1) 02717 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02718 } 02719 02720 if (rtp_debug_test_addr(&rtp->them)) 02721 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02722 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02723 } 02724 02725 rtp->seqno++; 02726 02727 return 0; 02728 }
Definition at line 1105 of file rtp.c.
References ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_inet_ntoa(), AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_TAIL, 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_sched_add(), ast_set_flag, 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, errno, event, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, frames, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, len, LOG_DEBUG, 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::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, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtcp::them, ast_rtp::them, ast_rtp::themssrc, and ast_frame::ts.
Referenced by gtalk_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().
01106 { 01107 int res; 01108 struct sockaddr_in sin; 01109 socklen_t len; 01110 unsigned int seqno; 01111 int version; 01112 int payloadtype; 01113 int hdrlen = 12; 01114 int padding; 01115 int mark; 01116 int ext; 01117 int cc; 01118 unsigned int ssrc; 01119 unsigned int timestamp; 01120 unsigned int *rtpheader; 01121 struct rtpPayloadType rtpPT; 01122 struct ast_rtp *bridged = NULL; 01123 AST_LIST_HEAD_NOLOCK(, ast_frame) frames; 01124 01125 /* If time is up, kill it */ 01126 if (rtp->sending_digit) 01127 ast_rtp_senddigit_continuation(rtp); 01128 01129 len = sizeof(sin); 01130 01131 /* Cache where the header will go */ 01132 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01133 0, (struct sockaddr *)&sin, &len); 01134 01135 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01136 if (res < 0) { 01137 ast_assert(errno != EBADF); 01138 if (errno != EAGAIN) { 01139 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01140 return NULL; 01141 } 01142 return &ast_null_frame; 01143 } 01144 01145 if (res < hdrlen) { 01146 ast_log(LOG_WARNING, "RTP Read too short\n"); 01147 return &ast_null_frame; 01148 } 01149 01150 /* Get fields */ 01151 seqno = ntohl(rtpheader[0]); 01152 01153 /* Check RTP version */ 01154 version = (seqno & 0xC0000000) >> 30; 01155 if (!version) { 01156 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01157 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01158 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01159 } 01160 return &ast_null_frame; 01161 } 01162 01163 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01164 /* If we don't have the other side's address, then ignore this */ 01165 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01166 return &ast_null_frame; 01167 #endif 01168 01169 /* Send to whoever send to us if NAT is turned on */ 01170 if (rtp->nat) { 01171 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01172 (rtp->them.sin_port != sin.sin_port)) { 01173 rtp->them = sin; 01174 if (rtp->rtcp) { 01175 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01176 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01177 } 01178 rtp->rxseqno = 0; 01179 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01180 if (option_debug || rtpdebug) 01181 ast_log(LOG_DEBUG, "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)); 01182 } 01183 } 01184 01185 /* If we are bridged to another RTP stream, send direct */ 01186 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01187 return &ast_null_frame; 01188 01189 if (version != 2) 01190 return &ast_null_frame; 01191 01192 payloadtype = (seqno & 0x7f0000) >> 16; 01193 padding = seqno & (1 << 29); 01194 mark = seqno & (1 << 23); 01195 ext = seqno & (1 << 28); 01196 cc = (seqno & 0xF000000) >> 24; 01197 seqno &= 0xffff; 01198 timestamp = ntohl(rtpheader[1]); 01199 ssrc = ntohl(rtpheader[2]); 01200 01201 AST_LIST_HEAD_INIT_NOLOCK(&frames); 01202 /* Force a marker bit and change SSRC if the SSRC changes */ 01203 if (rtp->rxssrc && rtp->rxssrc != ssrc) { 01204 struct ast_frame *f, srcupdate; 01205 srcupdate.frametype = AST_FRAME_CONTROL; 01206 srcupdate.subclass = AST_CONTROL_SRCCHANGE; 01207 if (!mark) { 01208 if (option_debug || rtpdebug) 01209 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01210 mark = 1; 01211 } 01212 01213 f = ast_frisolate(&srcupdate); 01214 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01215 } 01216 01217 rtp->rxssrc = ssrc; 01218 01219 if (padding) { 01220 /* Remove padding bytes */ 01221 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01222 } 01223 01224 if (cc) { 01225 /* CSRC fields present */ 01226 hdrlen += cc*4; 01227 } 01228 01229 if (ext) { 01230 /* RTP Extension present */ 01231 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01232 hdrlen += 4; 01233 } 01234 01235 if (res < hdrlen) { 01236 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01237 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 01238 } 01239 01240 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01241 01242 if (rtp->rxcount==1) { 01243 /* This is the first RTP packet successfully received from source */ 01244 rtp->seedrxseqno = seqno; 01245 } 01246 01247 /* Do not schedule RR if RTCP isn't run */ 01248 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01249 /* Schedule transmission of Receiver Report */ 01250 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01251 } 01252 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01253 rtp->cycles += RTP_SEQ_MOD; 01254 01255 rtp->lastrxseqno = seqno; 01256 01257 if (rtp->themssrc==0) 01258 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01259 01260 if (rtp_debug_test_addr(&sin)) 01261 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01262 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01263 01264 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01265 if (!rtpPT.isAstFormat) { 01266 struct ast_frame *f = NULL; 01267 01268 /* This is special in-band data that's not one of our codecs */ 01269 if (rtpPT.code == AST_RTP_DTMF) { 01270 /* It's special -- rfc2833 process it */ 01271 if (rtp_debug_test_addr(&sin)) { 01272 unsigned char *data; 01273 unsigned int event; 01274 unsigned int event_end; 01275 unsigned int duration; 01276 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01277 event = ntohl(*((unsigned int *)(data))); 01278 event >>= 24; 01279 event_end = ntohl(*((unsigned int *)(data))); 01280 event_end <<= 8; 01281 event_end >>= 24; 01282 duration = ntohl(*((unsigned int *)(data))); 01283 duration &= 0xFFFF; 01284 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); 01285 } 01286 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01287 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01288 /* It's really special -- process it the Cisco way */ 01289 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01290 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01291 rtp->lastevent = seqno; 01292 } 01293 } else if (rtpPT.code == AST_RTP_CN) { 01294 /* Comfort Noise */ 01295 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01296 } else { 01297 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01298 } 01299 if (f) { 01300 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01301 return AST_LIST_FIRST(&frames); 01302 } 01303 return &ast_null_frame; 01304 } 01305 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01306 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01307 01308 if (!rtp->lastrxts) 01309 rtp->lastrxts = timestamp; 01310 01311 rtp->rxseqno = seqno; 01312 01313 /* Record received timestamp as last received now */ 01314 rtp->lastrxts = timestamp; 01315 01316 rtp->f.mallocd = 0; 01317 rtp->f.datalen = res - hdrlen; 01318 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01319 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01320 rtp->f.seqno = seqno; 01321 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01322 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01323 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01324 ast_frame_byteswap_be(&rtp->f); 01325 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01326 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01327 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01328 rtp->f.ts = timestamp / 8; 01329 rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000); 01330 } else { 01331 /* Video -- samples is # of samples vs. 90000 */ 01332 if (!rtp->lastividtimestamp) 01333 rtp->lastividtimestamp = timestamp; 01334 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01335 rtp->lastividtimestamp = timestamp; 01336 rtp->f.delivery.tv_sec = 0; 01337 rtp->f.delivery.tv_usec = 0; 01338 if (mark) 01339 rtp->f.subclass |= 0x1; 01340 01341 } 01342 rtp->f.src = "RTP"; 01343 return &rtp->f; 01344 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3777 of file rtp.c.
References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and VERBOSE_PREFIX_2.
Referenced by ast_rtp_init().
03778 { 03779 struct ast_config *cfg; 03780 const char *s; 03781 03782 rtpstart = 5000; 03783 rtpend = 31000; 03784 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03785 cfg = ast_config_load("rtp.conf"); 03786 if (cfg) { 03787 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03788 rtpstart = atoi(s); 03789 if (rtpstart < 1024) 03790 rtpstart = 1024; 03791 if (rtpstart > 65535) 03792 rtpstart = 65535; 03793 } 03794 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03795 rtpend = atoi(s); 03796 if (rtpend < 1024) 03797 rtpend = 1024; 03798 if (rtpend > 65535) 03799 rtpend = 65535; 03800 } 03801 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03802 rtcpinterval = atoi(s); 03803 if (rtcpinterval == 0) 03804 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03805 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03806 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03807 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03808 rtcpinterval = RTCP_MAX_INTERVALMS; 03809 } 03810 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03811 #ifdef SO_NO_CHECK 03812 if (ast_false(s)) 03813 nochecksums = 1; 03814 else 03815 nochecksums = 0; 03816 #else 03817 if (ast_false(s)) 03818 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03819 #endif 03820 } 03821 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03822 dtmftimeout = atoi(s); 03823 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03824 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03825 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03826 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03827 }; 03828 } 03829 ast_config_destroy(cfg); 03830 } 03831 if (rtpstart >= rtpend) { 03832 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03833 rtpstart = 5000; 03834 rtpend = 31000; 03835 } 03836 if (option_verbose > 1) 03837 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03838 return 0; 03839 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2085 of file rtp.c.
References ast_rtp::dtmfcount, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, 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.
02086 { 02087 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02088 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02089 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02090 rtp->lastts = 0; 02091 rtp->lastdigitts = 0; 02092 rtp->lastrxts = 0; 02093 rtp->lastividtimestamp = 0; 02094 rtp->lastovidtimestamp = 0; 02095 rtp->lasteventseqn = 0; 02096 rtp->lastevent = 0; 02097 rtp->lasttxformat = 0; 02098 rtp->lastrxformat = 0; 02099 rtp->dtmfcount = 0; 02100 rtp->dtmfsamples = 0; 02101 rtp->seqno = 0; 02102 rtp->rxseqno = 0; 02103 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2600 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), 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 do_monitor().
02601 { 02602 unsigned int *rtpheader; 02603 int hdrlen = 12; 02604 int res; 02605 int payload; 02606 char data[256]; 02607 level = 127 - (level & 0x7f); 02608 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02609 02610 /* If we have no peer, return immediately */ 02611 if (!rtp->them.sin_addr.s_addr) 02612 return 0; 02613 02614 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02615 02616 /* Get a pointer to the header */ 02617 rtpheader = (unsigned int *)data; 02618 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02619 rtpheader[1] = htonl(rtp->lastts); 02620 rtpheader[2] = htonl(rtp->ssrc); 02621 data[12] = level; 02622 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02623 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02624 if (res <0) 02625 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)); 02626 if (rtp_debug_test_addr(&rtp->them)) 02627 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02628 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02629 02630 } 02631 return 0; 02632 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2208 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, 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().
02209 { 02210 unsigned int *rtpheader; 02211 int hdrlen = 12, res = 0, i = 0, payload = 0; 02212 char data[256]; 02213 02214 if ((digit <= '9') && (digit >= '0')) 02215 digit -= '0'; 02216 else if (digit == '*') 02217 digit = 10; 02218 else if (digit == '#') 02219 digit = 11; 02220 else if ((digit >= 'A') && (digit <= 'D')) 02221 digit = digit - 'A' + 12; 02222 else if ((digit >= 'a') && (digit <= 'd')) 02223 digit = digit - 'a' + 12; 02224 else { 02225 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02226 return 0; 02227 } 02228 02229 /* If we have no peer, return immediately */ 02230 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02231 return 0; 02232 02233 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02234 02235 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02236 rtp->send_duration = 160; 02237 02238 /* Get a pointer to the header */ 02239 rtpheader = (unsigned int *)data; 02240 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02241 rtpheader[1] = htonl(rtp->lastdigitts); 02242 rtpheader[2] = htonl(rtp->ssrc); 02243 02244 for (i = 0; i < 2; i++) { 02245 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02246 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02247 if (res < 0) 02248 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02249 ast_inet_ntoa(rtp->them.sin_addr), 02250 ntohs(rtp->them.sin_port), strerror(errno)); 02251 if (rtp_debug_test_addr(&rtp->them)) 02252 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02253 ast_inet_ntoa(rtp->them.sin_addr), 02254 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02255 /* Increment sequence number */ 02256 rtp->seqno++; 02257 /* Increment duration */ 02258 rtp->send_duration += 160; 02259 /* Clear marker bit and set seqno */ 02260 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02261 } 02262 02263 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02264 rtp->sending_digit = 1; 02265 rtp->send_digit = digit; 02266 rtp->send_payload = payload; 02267 02268 return 0; 02269 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2272 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().
02273 { 02274 unsigned int *rtpheader; 02275 int hdrlen = 12, res = 0; 02276 char data[256]; 02277 02278 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02279 return 0; 02280 02281 /* Setup packet to send */ 02282 rtpheader = (unsigned int *)data; 02283 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02284 rtpheader[1] = htonl(rtp->lastdigitts); 02285 rtpheader[2] = htonl(rtp->ssrc); 02286 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02287 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02288 02289 /* Transmit */ 02290 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02291 if (res < 0) 02292 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02293 ast_inet_ntoa(rtp->them.sin_addr), 02294 ntohs(rtp->them.sin_port), strerror(errno)); 02295 if (rtp_debug_test_addr(&rtp->them)) 02296 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02297 ast_inet_ntoa(rtp->them.sin_addr), 02298 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02299 02300 /* Increment sequence number */ 02301 rtp->seqno++; 02302 /* Increment duration */ 02303 rtp->send_duration += 160; 02304 02305 return 0; 02306 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2309 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, 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().
02310 { 02311 unsigned int *rtpheader; 02312 int hdrlen = 12, res = 0, i = 0; 02313 char data[256]; 02314 02315 /* If no address, then bail out */ 02316 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02317 return 0; 02318 02319 if ((digit <= '9') && (digit >= '0')) 02320 digit -= '0'; 02321 else if (digit == '*') 02322 digit = 10; 02323 else if (digit == '#') 02324 digit = 11; 02325 else if ((digit >= 'A') && (digit <= 'D')) 02326 digit = digit - 'A' + 12; 02327 else if ((digit >= 'a') && (digit <= 'd')) 02328 digit = digit - 'a' + 12; 02329 else { 02330 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02331 return 0; 02332 } 02333 02334 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02335 02336 rtpheader = (unsigned int *)data; 02337 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02338 rtpheader[1] = htonl(rtp->lastdigitts); 02339 rtpheader[2] = htonl(rtp->ssrc); 02340 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02341 /* Set end bit */ 02342 rtpheader[3] |= htonl((1 << 23)); 02343 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02344 /* Send 3 termination packets */ 02345 for (i = 0; i < 3; i++) { 02346 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02347 if (res < 0) 02348 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02349 ast_inet_ntoa(rtp->them.sin_addr), 02350 ntohs(rtp->them.sin_port), strerror(errno)); 02351 if (rtp_debug_test_addr(&rtp->them)) 02352 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02353 ast_inet_ntoa(rtp->them.sin_addr), 02354 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02355 } 02356 rtp->sending_digit = 0; 02357 rtp->send_digit = 0; 02358 /* Increment lastdigitts */ 02359 rtp->lastdigitts += 960; 02360 rtp->seqno++; 02361 02362 return res; 02363 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 586 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00587 { 00588 rtp->callback = callback; 00589 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 581 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00582 { 00583 rtp->data = data; 00584 }
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
Activate payload type.
Definition at line 1654 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, ast_rtp::current_RTP_PT, and MAX_RTP_PT.
Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().
01655 { 01656 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01657 return; /* bogus payload type */ 01658 01659 ast_mutex_lock(&rtp->bridge_lock); 01660 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01661 ast_mutex_unlock(&rtp->bridge_lock); 01662 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2031 of file rtp.c.
References ast_rtp::rtcp, ast_rtp::rxseqno, ast_rtcp::them, and ast_rtp::them.
Referenced by handle_open_receive_channel_ack_message(), process_sdp(), and setup_rtp_connection().
02032 { 02033 rtp->them.sin_port = them->sin_port; 02034 rtp->them.sin_addr = them->sin_addr; 02035 if (rtp->rtcp) { 02036 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02037 rtp->rtcp->them.sin_addr = them->sin_addr; 02038 } 02039 rtp->rxseqno = 0; 02040 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 548 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00549 { 00550 rtp->rtpholdtimeout = timeout; 00551 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 554 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00555 { 00556 rtp->rtpkeepalive = period; 00557 }
int ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
int | pt, | |||
char * | mimeType, | |||
char * | mimeSubtype, | |||
enum ast_rtp_options | options | |||
) |
Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
Initiate payload type to a known MIME media type for a codec.
Definition at line 1681 of file rtp.c.
References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, subtype, and type.
Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), process_sdp(), and set_dtmf_payload().
01684 { 01685 unsigned int i; 01686 int found = 0; 01687 01688 if (pt < 0 || pt > MAX_RTP_PT) 01689 return -1; /* bogus payload type */ 01690 01691 ast_mutex_lock(&rtp->bridge_lock); 01692 01693 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01694 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01695 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01696 found = 1; 01697 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01698 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01699 mimeTypes[i].payloadType.isAstFormat && 01700 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01701 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01702 break; 01703 } 01704 } 01705 01706 ast_mutex_unlock(&rtp->bridge_lock); 01707 01708 return (found ? 0 : -1); 01709 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 542 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00543 { 00544 rtp->rtptimeout = timeout; 00545 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 535 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00536 { 00537 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00538 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00539 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 601 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().
00602 { 00603 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00604 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 606 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().
00607 { 00608 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00609 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 591 of file rtp.c.
References ast_rtp::nat.
Referenced by __oh323_rtp_create(), do_setnat(), oh323_rtp_read(), and start_rtp().
void ast_rtp_setstun | ( | struct ast_rtp * | rtp, | |
int | stun_enable | |||
) |
Enable STUN capability.
Definition at line 611 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00612 { 00613 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00614 }
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 2006 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
02007 { 02008 int res; 02009 02010 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 02011 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 02012 return res; 02013 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2071 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_rtcp::them, and ast_rtp::them.
Referenced by process_sdp(), setup_rtp_connection(), and stop_media_flows().
02072 { 02073 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02074 02075 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02076 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02077 if (rtp->rtcp) { 02078 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02079 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02080 } 02081 02082 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02083 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Definition at line 403 of file rtp.c.
References append_attr_string(), stun_attr::attr, stun_header::ies, stun_header::msglen, stun_header::msgtype, ast_rtp::s, STUN_BINDREQ, stun_req_id(), stun_send(), and STUN_USERNAME.
Referenced by gtalk_update_stun().
00404 { 00405 struct stun_header *req; 00406 unsigned char reqdata[1024]; 00407 int reqlen, reqleft; 00408 struct stun_attr *attr; 00409 00410 req = (struct stun_header *)reqdata; 00411 stun_req_id(req); 00412 reqlen = 0; 00413 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00414 req->msgtype = 0; 00415 req->msglen = 0; 00416 attr = (struct stun_attr *)req->ies; 00417 if (username) 00418 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00419 req->msglen = htons(reqlen); 00420 req->msgtype = htons(STUN_BINDREQ); 00421 stun_send(rtp->s, suggestion, req); 00422 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
remove setting from payload type list if the rtpmap header indicates an unknown media type
clear payload type
Definition at line 1666 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by process_sdp().
01667 { 01668 if (pt < 0 || pt > MAX_RTP_PT) 01669 return; /* bogus payload type */ 01670 01671 ast_mutex_lock(&rtp->bridge_lock); 01672 rtp->current_RTP_PT[pt].isAstFormat = 0; 01673 rtp->current_RTP_PT[pt].code = 0; 01674 ast_mutex_unlock(&rtp->bridge_lock); 01675 }
void ast_rtp_update_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2015 of file rtp.c.
References ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), sip_write(), and skinny_indicate().
02016 { 02017 rtp->set_marker_bit = 1; 02018 return; 02019 }
Definition at line 2759 of file rtp.c.
References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_frame::samples, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
Referenced by gtalk_write(), mgcp_write(), oh323_write(), sip_write(), and skinny_write().
02760 { 02761 struct ast_frame *f; 02762 int codec; 02763 int hdrlen = 12; 02764 int subclass; 02765 02766 02767 /* If we have no peer, return immediately */ 02768 if (!rtp->them.sin_addr.s_addr) 02769 return 0; 02770 02771 /* If there is no data length, return immediately */ 02772 if (!_f->datalen) 02773 return 0; 02774 02775 /* Make sure we have enough space for RTP header */ 02776 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02777 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02778 return -1; 02779 } 02780 02781 subclass = _f->subclass; 02782 if (_f->frametype == AST_FRAME_VIDEO) 02783 subclass &= ~0x1; 02784 02785 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02786 if (codec < 0) { 02787 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02788 return -1; 02789 } 02790 02791 if (rtp->lasttxformat != subclass) { 02792 /* New format, reset the smoother */ 02793 if (option_debug) 02794 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02795 rtp->lasttxformat = subclass; 02796 if (rtp->smoother) 02797 ast_smoother_free(rtp->smoother); 02798 rtp->smoother = NULL; 02799 } 02800 02801 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 02802 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02803 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02804 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02805 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)); 02806 return -1; 02807 } 02808 if (fmt.flags) 02809 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02810 if (option_debug) 02811 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); 02812 } 02813 } 02814 if (rtp->smoother) { 02815 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02816 ast_smoother_feed_be(rtp->smoother, _f); 02817 } else { 02818 ast_smoother_feed(rtp->smoother, _f); 02819 } 02820 02821 while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { 02822 if (f->subclass == AST_FORMAT_G722) { 02823 /* G.722 is silllllllllllllly */ 02824 f->samples /= 2; 02825 } 02826 02827 ast_rtp_raw_write(rtp, f, codec); 02828 } 02829 } else { 02830 /* Don't buffer outgoing frames; send them one-per-packet: */ 02831 if (_f->offset < hdrlen) { 02832 f = ast_frdup(_f); 02833 } else { 02834 f = _f; 02835 } 02836 if (f->data) { 02837 if (f->subclass == AST_FORMAT_G722) { 02838 /* G.722 is silllllllllllllly */ 02839 f->samples /= 2; 02840 } 02841 ast_rtp_raw_write(rtp, f, codec); 02842 } 02843 if (f != _f) 02844 ast_frfree(f); 02845 } 02846 02847 return 0; 02848 }
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_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 2878 of file rtp.c.
References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, 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_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_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
02879 { 02880 struct ast_frame *fr = NULL; 02881 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02882 int oldcodec0 = codec0, oldcodec1 = codec1; 02883 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02884 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02885 02886 /* Set it up so audio goes directly between the two endpoints */ 02887 02888 /* Test the first channel */ 02889 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02890 ast_rtp_get_peer(p1, &ac1); 02891 if (vp1) 02892 ast_rtp_get_peer(vp1, &vac1); 02893 } else 02894 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 02895 02896 /* Test the second channel */ 02897 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 02898 ast_rtp_get_peer(p0, &ac0); 02899 if (vp0) 02900 ast_rtp_get_peer(vp0, &vac0); 02901 } else 02902 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 02903 02904 /* Now we can unlock and move into our loop */ 02905 ast_channel_unlock(c0); 02906 ast_channel_unlock(c1); 02907 02908 /* Throw our channels into the structure and enter the loop */ 02909 cs[0] = c0; 02910 cs[1] = c1; 02911 cs[2] = NULL; 02912 for (;;) { 02913 /* Check if anything changed */ 02914 if ((c0->tech_pvt != pvt0) || 02915 (c1->tech_pvt != pvt1) || 02916 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 02917 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 02918 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 02919 if (c0->tech_pvt == pvt0) 02920 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02921 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02922 if (c1->tech_pvt == pvt1) 02923 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02924 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02925 return AST_BRIDGE_RETRY; 02926 } 02927 02928 /* Check if they have changed their address */ 02929 ast_rtp_get_peer(p1, &t1); 02930 if (vp1) 02931 ast_rtp_get_peer(vp1, &vt1); 02932 if (pr1->get_codec) 02933 codec1 = pr1->get_codec(c1); 02934 ast_rtp_get_peer(p0, &t0); 02935 if (vp0) 02936 ast_rtp_get_peer(vp0, &vt0); 02937 if (pr0->get_codec) 02938 codec0 = pr0->get_codec(c0); 02939 if ((inaddrcmp(&t1, &ac1)) || 02940 (vp1 && inaddrcmp(&vt1, &vac1)) || 02941 (codec1 != oldcodec1)) { 02942 if (option_debug > 1) { 02943 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02944 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 02945 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 02946 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 02947 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02948 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 02949 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02950 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 02951 } 02952 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 02953 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 02954 memcpy(&ac1, &t1, sizeof(ac1)); 02955 memcpy(&vac1, &vt1, sizeof(vac1)); 02956 oldcodec1 = codec1; 02957 } 02958 if ((inaddrcmp(&t0, &ac0)) || 02959 (vp0 && inaddrcmp(&vt0, &vac0))) { 02960 if (option_debug > 1) { 02961 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02962 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 02963 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02964 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 02965 } 02966 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 02967 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 02968 memcpy(&ac0, &t0, sizeof(ac0)); 02969 memcpy(&vac0, &vt0, sizeof(vac0)); 02970 oldcodec0 = codec0; 02971 } 02972 02973 /* Wait for frame to come in on the channels */ 02974 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 02975 if (!timeoutms) { 02976 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02977 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02978 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02979 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02980 return AST_BRIDGE_RETRY; 02981 } 02982 if (option_debug) 02983 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 02984 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 02985 break; 02986 continue; 02987 } 02988 fr = ast_read(who); 02989 other = (who == c0) ? c1 : c0; 02990 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 02991 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 02992 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 02993 /* Break out of bridge */ 02994 *fo = fr; 02995 *rc = who; 02996 if (option_debug) 02997 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 02998 if (c0->tech_pvt == pvt0) 02999 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03000 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03001 if (c1->tech_pvt == pvt1) 03002 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03003 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03004 return AST_BRIDGE_COMPLETE; 03005 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03006 if ((fr->subclass == AST_CONTROL_HOLD) || 03007 (fr->subclass == AST_CONTROL_UNHOLD) || 03008 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03009 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03010 if (fr->subclass == AST_CONTROL_HOLD) { 03011 /* If we someone went on hold we want the other side to reinvite back to us */ 03012 if (who == c0) 03013 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 03014 else 03015 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 03016 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03017 /* If they went off hold they should go back to being direct */ 03018 if (who == c0) 03019 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 03020 else 03021 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 03022 } 03023 /* Update local address information */ 03024 ast_rtp_get_peer(p0, &t0); 03025 memcpy(&ac0, &t0, sizeof(ac0)); 03026 ast_rtp_get_peer(p1, &t1); 03027 memcpy(&ac1, &t1, sizeof(ac1)); 03028 /* Update codec information */ 03029 if (pr0->get_codec && c0->tech_pvt) 03030 oldcodec0 = codec0 = pr0->get_codec(c0); 03031 if (pr1->get_codec && c1->tech_pvt) 03032 oldcodec1 = codec1 = pr1->get_codec(c1); 03033 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03034 ast_frfree(fr); 03035 } else { 03036 *fo = fr; 03037 *rc = who; 03038 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03039 return AST_BRIDGE_COMPLETE; 03040 } 03041 } else { 03042 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03043 (fr->frametype == AST_FRAME_DTMF_END) || 03044 (fr->frametype == AST_FRAME_VOICE) || 03045 (fr->frametype == AST_FRAME_VIDEO) || 03046 (fr->frametype == AST_FRAME_IMAGE) || 03047 (fr->frametype == AST_FRAME_HTML) || 03048 (fr->frametype == AST_FRAME_MODEM) || 03049 (fr->frametype == AST_FRAME_TEXT)) { 03050 ast_write(other, fr); 03051 } 03052 ast_frfree(fr); 03053 } 03054 /* Swap priority */ 03055 cs[2] = cs[0]; 03056 cs[0] = cs[1]; 03057 cs[1] = cs[2]; 03058 } 03059 03060 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03061 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03062 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03063 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03064 03065 return AST_BRIDGE_FAILED; 03066 }
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).
Definition at line 3164 of file rtp.c.
References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate_data(), ast_log(), ast_read(), ast_waitfor_n(), ast_write(), ast_channel::audiohooks, ast_frame::data, ast_frame::datalen, FLAG_P2P_SENT_MARK, ast_frame::frametype, LOG_DEBUG, LOG_NOTICE, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, option_debug, p2p_callback_disable(), p2p_callback_enable(), p2p_set_bridge(), ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
03165 { 03166 struct ast_frame *fr = NULL; 03167 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03168 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03169 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03170 int p0_callback = 0, p1_callback = 0; 03171 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03172 03173 /* Okay, setup each RTP structure to do P2P forwarding */ 03174 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03175 p2p_set_bridge(p0, p1); 03176 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03177 p2p_set_bridge(p1, p0); 03178 03179 /* Activate callback modes if possible */ 03180 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03181 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03182 03183 /* Now let go of the channel locks and be on our way */ 03184 ast_channel_unlock(c0); 03185 ast_channel_unlock(c1); 03186 03187 /* Go into a loop forwarding frames until we don't need to anymore */ 03188 cs[0] = c0; 03189 cs[1] = c1; 03190 cs[2] = NULL; 03191 for (;;) { 03192 /* If the underlying formats have changed force this bridge to break */ 03193 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 03194 ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n"); 03195 res = AST_BRIDGE_FAILED_NOWARN; 03196 break; 03197 } 03198 /* Check if anything changed */ 03199 if ((c0->tech_pvt != pvt0) || 03200 (c1->tech_pvt != pvt1) || 03201 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03202 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03203 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03204 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03205 ast_frfree(fr); 03206 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03207 ast_frfree(fr); 03208 res = AST_BRIDGE_RETRY; 03209 break; 03210 } 03211 /* Wait on a channel to feed us a frame */ 03212 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03213 if (!timeoutms) { 03214 res = AST_BRIDGE_RETRY; 03215 break; 03216 } 03217 if (option_debug) 03218 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03219 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03220 break; 03221 continue; 03222 } 03223 /* Read in frame from channel */ 03224 fr = ast_read(who); 03225 other = (who == c0) ? c1 : c0; 03226 /* Dependong on the frame we may need to break out of our bridge */ 03227 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03228 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03229 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03230 /* Record received frame and who */ 03231 *fo = fr; 03232 *rc = who; 03233 if (option_debug) 03234 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03235 res = AST_BRIDGE_COMPLETE; 03236 break; 03237 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03238 if ((fr->subclass == AST_CONTROL_HOLD) || 03239 (fr->subclass == AST_CONTROL_UNHOLD) || 03240 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03241 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03242 /* If we are going on hold, then break callback mode and P2P bridging */ 03243 if (fr->subclass == AST_CONTROL_HOLD) { 03244 if (p0_callback) 03245 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03246 if (p1_callback) 03247 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03248 p2p_set_bridge(p0, NULL); 03249 p2p_set_bridge(p1, NULL); 03250 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03251 /* If we are off hold, then go back to callback mode and P2P bridging */ 03252 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03253 p2p_set_bridge(p0, p1); 03254 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03255 p2p_set_bridge(p1, p0); 03256 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03257 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03258 } 03259 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03260 ast_frfree(fr); 03261 } else { 03262 *fo = fr; 03263 *rc = who; 03264 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03265 res = AST_BRIDGE_COMPLETE; 03266 break; 03267 } 03268 } else { 03269 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03270 (fr->frametype == AST_FRAME_DTMF_END) || 03271 (fr->frametype == AST_FRAME_VOICE) || 03272 (fr->frametype == AST_FRAME_VIDEO) || 03273 (fr->frametype == AST_FRAME_IMAGE) || 03274 (fr->frametype == AST_FRAME_HTML) || 03275 (fr->frametype == AST_FRAME_MODEM) || 03276 (fr->frametype == AST_FRAME_TEXT)) { 03277 ast_write(other, fr); 03278 } 03279 03280 ast_frfree(fr); 03281 } 03282 /* Swap priority */ 03283 cs[2] = cs[0]; 03284 cs[0] = cs[1]; 03285 cs[1] = cs[2]; 03286 } 03287 03288 /* If we are totally avoiding the core, then restore our link to it */ 03289 if (p0_callback) 03290 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03291 if (p1_callback) 03292 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03293 03294 /* Break out of the direct bridge */ 03295 p2p_set_bridge(p0, NULL); 03296 p2p_set_bridge(p1, NULL); 03297 03298 return res; 03299 }
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 1052 of file rtp.c.
References ast_inet_ntoa(), ast_log(), 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, LOG_DEBUG, ast_rtp::nat, option_debug, reconstruct(), rtp_debug_test_addr(), ast_rtp::s, and ast_rtp::them.
Referenced by ast_rtp_read().
01053 { 01054 int res = 0, payload = 0, bridged_payload = 0, mark; 01055 struct rtpPayloadType rtpPT; 01056 int reconstruct = ntohl(rtpheader[0]); 01057 01058 /* Get fields from packet */ 01059 payload = (reconstruct & 0x7f0000) >> 16; 01060 mark = (((reconstruct & 0x800000) >> 23) != 0); 01061 01062 /* Check what the payload value should be */ 01063 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01064 01065 /* 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 */ 01066 if (!bridged->current_RTP_PT[payload].code) 01067 return -1; 01068 01069 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01070 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01071 return -1; 01072 01073 /* Otherwise adjust bridged payload to match */ 01074 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01075 01076 /* If the mark bit has not been sent yet... do it now */ 01077 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01078 mark = 1; 01079 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01080 } 01081 01082 /* Reconstruct part of the packet */ 01083 reconstruct &= 0xFF80FFFF; 01084 reconstruct |= (bridged_payload << 16); 01085 reconstruct |= (mark << 23); 01086 rtpheader[0] = htonl(reconstruct); 01087 01088 /* Send the packet back out */ 01089 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01090 if (res < 0) { 01091 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01092 ast_log(LOG_DEBUG, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno)); 01093 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01094 if (option_debug || rtpdebug) 01095 ast_log(LOG_DEBUG, "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)); 01096 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01097 } 01098 return 0; 01099 } else if (rtp_debug_test_addr(&bridged->them)) 01100 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); 01101 01102 return 0; 01103 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1003 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().
01004 { 01005 struct timeval now; 01006 double transit; 01007 double current_time; 01008 double d; 01009 double dtv; 01010 double prog; 01011 01012 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01013 gettimeofday(&rtp->rxcore, NULL); 01014 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01015 /* map timestamp to a real time */ 01016 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01017 rtp->rxcore.tv_sec -= timestamp / 8000; 01018 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01019 /* Round to 0.1ms for nice, pretty timestamps */ 01020 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01021 if (rtp->rxcore.tv_usec < 0) { 01022 /* Adjust appropriately if necessary */ 01023 rtp->rxcore.tv_usec += 1000000; 01024 rtp->rxcore.tv_sec -= 1; 01025 } 01026 } 01027 01028 gettimeofday(&now,NULL); 01029 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01030 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01031 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01032 if (tv->tv_usec >= 1000000) { 01033 tv->tv_usec -= 1000000; 01034 tv->tv_sec += 1; 01035 } 01036 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01037 dtv = (double)rtp->drxcore + (double)(prog); 01038 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01039 transit = current_time - dtv; 01040 d = transit - rtp->rxtransit; 01041 rtp->rxtransit = transit; 01042 if (d<0) 01043 d=-d; 01044 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01045 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01046 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01047 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01048 rtp->rtcp->minrxjitter = rtp->rxjitter; 01049 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2188 of file rtp.c.
References ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02189 { 02190 struct timeval t; 02191 long ms; 02192 if (ast_tvzero(rtp->txcore)) { 02193 rtp->txcore = ast_tvnow(); 02194 /* Round to 20ms for nice, pretty timestamps */ 02195 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02196 } 02197 /* Use previous txcore if available */ 02198 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02199 ms = ast_tvdiff_ms(t, rtp->txcore); 02200 if (ms < 0) 02201 ms = 0; 02202 /* Use what we just got for next time */ 02203 rtp->txcore = t; 02204 return (unsigned int) ms; 02205 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static, read] |
Get channel driver interface structure.
Definition at line 1477 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, protos, 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().
01478 { 01479 struct ast_rtp_protocol *cur = NULL; 01480 01481 AST_LIST_LOCK(&protos); 01482 AST_LIST_TRAVERSE(&protos, cur, list) { 01483 if (cur->type == chan->tech->type) 01484 break; 01485 } 01486 AST_LIST_UNLOCK(&protos); 01487 01488 return cur; 01489 }
static int p2p_callback_disable | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
int * | fds, | |||
int ** | iod | |||
) | [static] |
Helper function to switch a channel and RTP stream out of callback mode.
Definition at line 3135 of file rtp.c.
References ast_channel_lock, ast_channel_unlock, ast_io_add(), AST_IO_IN, ast_io_remove(), ast_test_flag, ast_channel::fds, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, rtpread(), and ast_rtp::s.
Referenced by bridge_p2p_loop().
03136 { 03137 ast_channel_lock(chan); 03138 03139 /* Remove the callback from the IO context */ 03140 ast_io_remove(rtp->io, iod[0]); 03141 03142 /* Restore file descriptors */ 03143 chan->fds[0] = fds[0]; 03144 ast_channel_unlock(chan); 03145 03146 /* Restore callback mode if previously used */ 03147 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03148 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03149 03150 return 0; 03151 }
static int p2p_callback_enable | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
int * | fds, | |||
int ** | iod | |||
) | [static] |
Helper function that sets what an RTP structure is bridged to.
Definition at line 3154 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03155 { 03156 ast_mutex_lock(&rtp0->bridge_lock); 03157 rtp0->bridged = rtp1; 03158 ast_mutex_unlock(&rtp0->bridge_lock); 03159 03160 return; 03161 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static, read] |
Definition at line 670 of file rtp.c.
References AST_FRAME_DTMF_END, ast_log(), ast_rtp::dtmfcount, event, f, LOG_DEBUG, option_debug, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00671 { 00672 unsigned int event; 00673 char resp = 0; 00674 struct ast_frame *f = NULL; 00675 event = ntohl(*((unsigned int *)(data))); 00676 event &= 0x001F; 00677 if (option_debug > 2 || rtpdebug) 00678 ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len); 00679 if (event < 10) { 00680 resp = '0' + event; 00681 } else if (event < 11) { 00682 resp = '*'; 00683 } else if (event < 12) { 00684 resp = '#'; 00685 } else if (event < 16) { 00686 resp = 'A' + (event - 12); 00687 } else if (event < 17) { 00688 resp = 'X'; 00689 } 00690 if (rtp->resp && (rtp->resp != resp)) { 00691 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00692 } 00693 rtp->resp = resp; 00694 rtp->dtmfcount = dtmftimeout; 00695 return f; 00696 }
static struct ast_frame* process_rfc2833 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp | |||
) | [static, read] |
Process RTP DTMF and events according to RFC 2833.
RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
rtp | ||
data | ||
len | ||
seqno |
Definition at line 709 of file rtp.c.
References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_null_frame, ast_test_flag, ast_rtp::dtmfcount, ast_rtp::dtmfsamples, event, f, FLAG_DTMF_COMPENSATE, ast_rtp::lastevent, ast_frame::len, LOG_DEBUG, option_debug, ast_rtp::resp, ast_frame::samples, and send_dtmf().
Referenced by ast_rtp_read().
00710 { 00711 unsigned int event; 00712 unsigned int event_end; 00713 unsigned int samples; 00714 char resp = 0; 00715 struct ast_frame *f = NULL; 00716 00717 /* Figure out event, event end, and samples */ 00718 event = ntohl(*((unsigned int *)(data))); 00719 event >>= 24; 00720 event_end = ntohl(*((unsigned int *)(data))); 00721 event_end <<= 8; 00722 event_end >>= 24; 00723 samples = ntohl(*((unsigned int *)(data))); 00724 samples &= 0xFFFF; 00725 00726 /* Print out debug if turned on */ 00727 if (rtpdebug || option_debug > 2) 00728 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00729 00730 /* Figure out what digit was pressed */ 00731 if (event < 10) { 00732 resp = '0' + event; 00733 } else if (event < 11) { 00734 resp = '*'; 00735 } else if (event < 12) { 00736 resp = '#'; 00737 } else if (event < 16) { 00738 resp = 'A' + (event - 12); 00739 } else if (event < 17) { /* Event 16: Hook flash */ 00740 resp = 'X'; 00741 } else { 00742 /* Not a supported event */ 00743 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 00744 return &ast_null_frame; 00745 } 00746 00747 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00748 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 00749 rtp->resp = resp; 00750 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00751 f->len = 0; 00752 rtp->lastevent = timestamp; 00753 } 00754 } else { 00755 if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) { 00756 rtp->resp = resp; 00757 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00758 } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) { 00759 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00760 f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */ 00761 rtp->resp = 0; 00762 rtp->lastevent = seqno; 00763 } 00764 } 00765 00766 rtp->dtmfcount = dtmftimeout; 00767 rtp->dtmfsamples = samples; 00768 00769 return f; 00770 }
static struct ast_frame* process_rfc3389 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static, read] |
Process Comfort Noise RTP.
This is incomplete at the moment.
Definition at line 778 of file rtp.c.
References 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_DEBUG, LOG_NOTICE, ast_frame::offset, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read().
00779 { 00780 struct ast_frame *f = NULL; 00781 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00782 totally help us out becuase we don't have an engine to keep it going and we are not 00783 guaranteed to have it every 20ms or anything */ 00784 if (rtpdebug) 00785 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00786 00787 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00788 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00789 ast_inet_ntoa(rtp->them.sin_addr)); 00790 ast_set_flag(rtp, FLAG_3389_WARNING); 00791 } 00792 00793 /* Must have at least one byte */ 00794 if (!len) 00795 return NULL; 00796 if (len < 24) { 00797 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00798 rtp->f.datalen = len - 1; 00799 rtp->f.offset = AST_FRIENDLY_OFFSET; 00800 memcpy(rtp->f.data, data + 1, len - 1); 00801 } else { 00802 rtp->f.data = NULL; 00803 rtp->f.offset = 0; 00804 rtp->f.datalen = 0; 00805 } 00806 rtp->f.frametype = AST_FRAME_CNG; 00807 rtp->f.subclass = data[0] & 0x7f; 00808 rtp->f.datalen = len - 1; 00809 rtp->f.samples = 0; 00810 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00811 f = &rtp->f; 00812 return f; 00813 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 656 of file rtp.c.
References rtcpdebugaddr.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00657 { 00658 if (rtcpdebug == 0) 00659 return 0; 00660 if (rtcpdebugaddr.sin_addr.s_addr) { 00661 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00662 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00663 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00664 return 0; 00665 } 00666 return 1; 00667 }
static int rtcp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3574 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtcp_do_debug_ip(), and rtcpdebugaddr.
03574 { 03575 if (argc != 2) { 03576 if (argc != 4) 03577 return RESULT_SHOWUSAGE; 03578 return rtcp_do_debug_ip(fd, argc, argv); 03579 } 03580 rtcpdebug = 1; 03581 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03582 ast_cli(fd, "RTCP Debugging Enabled\n"); 03583 return RESULT_SUCCESS; 03584 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3562 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtcp_do_debug_ip_deprecated(), and rtcpdebugaddr.
03562 { 03563 if (argc != 3) { 03564 if (argc != 5) 03565 return RESULT_SHOWUSAGE; 03566 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03567 } 03568 rtcpdebug = 1; 03569 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03570 ast_cli(fd, "RTCP Debugging Enabled\n"); 03571 return RESULT_SUCCESS; 03572 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3519 of file rtp.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcpdebugaddr.
Referenced by rtcp_do_debug().
03520 { 03521 struct hostent *hp; 03522 struct ast_hostent ahp; 03523 int port = 0; 03524 char *p, *arg; 03525 if (argc != 4) 03526 return RESULT_SHOWUSAGE; 03527 03528 arg = argv[3]; 03529 p = strstr(arg, ":"); 03530 if (p) { 03531 *p = '\0'; 03532 p++; 03533 port = atoi(p); 03534 } 03535 hp = ast_gethostbyname(arg, &ahp); 03536 if (hp == NULL) 03537 return RESULT_SHOWUSAGE; 03538 rtcpdebugaddr.sin_family = AF_INET; 03539 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03540 rtcpdebugaddr.sin_port = htons(port); 03541 if (port == 0) 03542 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03543 else 03544 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03545 rtcpdebug = 1; 03546 return RESULT_SUCCESS; 03547 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3489 of file rtp.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcpdebugaddr.
Referenced by rtcp_do_debug_deprecated().
03490 { 03491 struct hostent *hp; 03492 struct ast_hostent ahp; 03493 int port = 0; 03494 char *p, *arg; 03495 if (argc != 5) 03496 return RESULT_SHOWUSAGE; 03497 03498 arg = argv[4]; 03499 p = strstr(arg, ":"); 03500 if (p) { 03501 *p = '\0'; 03502 p++; 03503 port = atoi(p); 03504 } 03505 hp = ast_gethostbyname(arg, &ahp); 03506 if (hp == NULL) 03507 return RESULT_SHOWUSAGE; 03508 rtcpdebugaddr.sin_family = AF_INET; 03509 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03510 rtcpdebugaddr.sin_port = htons(port); 03511 if (port == 0) 03512 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03513 else 03514 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03515 rtcpdebug = 1; 03516 return RESULT_SUCCESS; 03517 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3595 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03595 { 03596 if (argc != 2) { 03597 return RESULT_SHOWUSAGE; 03598 } 03599 rtcpstats = 1; 03600 ast_cli(fd, "RTCP Stats Enabled\n"); 03601 return RESULT_SUCCESS; 03602 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3586 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03586 { 03587 if (argc != 3) { 03588 return RESULT_SHOWUSAGE; 03589 } 03590 rtcpstats = 1; 03591 ast_cli(fd, "RTCP Stats Enabled\n"); 03592 return RESULT_SUCCESS; 03593 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3622 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03623 { 03624 if (argc != 3) 03625 return RESULT_SHOWUSAGE; 03626 rtcpdebug = 0; 03627 ast_cli(fd,"RTCP Debugging Disabled\n"); 03628 return RESULT_SUCCESS; 03629 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3613 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03614 { 03615 if (argc != 4) 03616 return RESULT_SHOWUSAGE; 03617 rtcpdebug = 0; 03618 ast_cli(fd,"RTCP Debugging Disabled\n"); 03619 return RESULT_SUCCESS; 03620 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3640 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03641 { 03642 if (argc != 3) 03643 return RESULT_SHOWUSAGE; 03644 rtcpstats = 0; 03645 ast_cli(fd,"RTCP Stats Disabled\n"); 03646 return RESULT_SUCCESS; 03647 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3631 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03632 { 03633 if (argc != 4) 03634 return RESULT_SHOWUSAGE; 03635 rtcpstats = 0; 03636 ast_cli(fd,"RTCP Stats Disabled\n"); 03637 return RESULT_SUCCESS; 03638 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 643 of file rtp.c.
References rtpdebugaddr.
Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_senddigit_continuation(), ast_rtp_senddigit_end(), and bridge_p2p_rtp_write().
00644 { 00645 if (rtpdebug == 0) 00646 return 0; 00647 if (rtpdebugaddr.sin_addr.s_addr) { 00648 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00649 && (rtpdebugaddr.sin_port != addr->sin_port)) 00650 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00651 return 0; 00652 } 00653 return 1; 00654 }
static int rtp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3549 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtp_do_debug_ip(), and rtpdebugaddr.
03550 { 03551 if (argc != 2) { 03552 if (argc != 4) 03553 return RESULT_SHOWUSAGE; 03554 return rtp_do_debug_ip(fd, argc, argv); 03555 } 03556 rtpdebug = 1; 03557 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03558 ast_cli(fd, "RTP Debugging Enabled\n"); 03559 return RESULT_SUCCESS; 03560 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3459 of file rtp.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtpdebugaddr.
Referenced by rtp_do_debug().
03460 { 03461 struct hostent *hp; 03462 struct ast_hostent ahp; 03463 int port = 0; 03464 char *p, *arg; 03465 03466 if (argc != 4) 03467 return RESULT_SHOWUSAGE; 03468 arg = argv[3]; 03469 p = strstr(arg, ":"); 03470 if (p) { 03471 *p = '\0'; 03472 p++; 03473 port = atoi(p); 03474 } 03475 hp = ast_gethostbyname(arg, &ahp); 03476 if (hp == NULL) 03477 return RESULT_SHOWUSAGE; 03478 rtpdebugaddr.sin_family = AF_INET; 03479 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03480 rtpdebugaddr.sin_port = htons(port); 03481 if (port == 0) 03482 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03483 else 03484 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03485 rtpdebug = 1; 03486 return RESULT_SUCCESS; 03487 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3604 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03605 { 03606 if (argc != 3) 03607 return RESULT_SHOWUSAGE; 03608 rtpdebug = 0; 03609 ast_cli(fd,"RTP Debugging Disabled\n"); 03610 return RESULT_SUCCESS; 03611 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1853 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01854 { 01855 int s; 01856 long flags; 01857 s = socket(AF_INET, SOCK_DGRAM, 0); 01858 if (s > -1) { 01859 flags = fcntl(s, F_GETFL); 01860 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01861 #ifdef SO_NO_CHECK 01862 if (nochecksums) 01863 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01864 #endif 01865 } 01866 return s; 01867 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 815 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, ast_rtp::data, and f.
Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().
00816 { 00817 struct ast_rtp *rtp = cbdata; 00818 struct ast_frame *f; 00819 f = ast_rtp_read(rtp); 00820 if (f) { 00821 if (rtp->callback) 00822 rtp->callback(rtp, f, rtp->data); 00823 } 00824 return 1; 00825 }
static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static, read] |
Definition at line 616 of file rtp.c.
References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_test_flag, ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::f, FLAG_DTMF_COMPENSATE, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, option_debug, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.
Referenced by process_cisco_dtmf(), and process_rfc2833().
00617 { 00618 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00619 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00620 if (option_debug) 00621 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00622 rtp->resp = 0; 00623 rtp->dtmfsamples = 0; 00624 return &ast_null_frame; 00625 } 00626 if (option_debug) 00627 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00628 if (rtp->resp == 'X') { 00629 rtp->f.frametype = AST_FRAME_CONTROL; 00630 rtp->f.subclass = AST_CONTROL_FLASH; 00631 } else { 00632 rtp->f.frametype = type; 00633 rtp->f.subclass = rtp->resp; 00634 } 00635 rtp->f.datalen = 0; 00636 rtp->f.samples = 0; 00637 rtp->f.mallocd = 0; 00638 rtp->f.src = "RTP"; 00639 return &rtp->f; 00640 00641 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
Definition at line 300 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().
00301 { 00302 switch(msg) { 00303 case STUN_MAPPED_ADDRESS: 00304 return "Mapped Address"; 00305 case STUN_RESPONSE_ADDRESS: 00306 return "Response Address"; 00307 case STUN_CHANGE_REQUEST: 00308 return "Change Request"; 00309 case STUN_SOURCE_ADDRESS: 00310 return "Source Address"; 00311 case STUN_CHANGED_ADDRESS: 00312 return "Changed Address"; 00313 case STUN_USERNAME: 00314 return "Username"; 00315 case STUN_PASSWORD: 00316 return "Password"; 00317 case STUN_MESSAGE_INTEGRITY: 00318 return "Message Integrity"; 00319 case STUN_ERROR_CODE: 00320 return "Error Code"; 00321 case STUN_UNKNOWN_ATTRIBUTES: 00322 return "Unknown Attributes"; 00323 case STUN_REFLECTED_FROM: 00324 return "Reflected From"; 00325 } 00326 return "Non-RFC3489 Attribute"; 00327 }
static int stun_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3649 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03650 { 03651 if (argc != 2) { 03652 return RESULT_SHOWUSAGE; 03653 } 03654 stundebug = 1; 03655 ast_cli(fd, "STUN Debugging Enabled\n"); 03656 return RESULT_SUCCESS; 03657 }
static int stun_handle_packet | ( | int | s, | |
struct sockaddr_in * | src, | |||
unsigned char * | data, | |||
size_t | len | |||
) | [static] |
Definition at line 424 of file rtp.c.
References append_attr_address(), append_attr_string(), ast_log(), ast_verbose(), stun_attr::attr, stun_header::id, stun_header::ies, stun_attr::len, LOG_DEBUG, stun_header::msglen, stun_header::msgtype, option_debug, STUN_ACCEPT, stun_attr2str(), STUN_BINDREQ, STUN_BINDRESP, STUN_IGNORE, STUN_MAPPED_ADDRESS, stun_msg2str(), stun_process_attr(), stun_send(), STUN_USERNAME, and stun_state::username.
Referenced by ast_rtp_read().
00425 { 00426 struct stun_header *resp, *hdr = (struct stun_header *)data; 00427 struct stun_attr *attr; 00428 struct stun_state st; 00429 int ret = STUN_IGNORE; 00430 unsigned char respdata[1024]; 00431 int resplen, respleft; 00432 00433 if (len < sizeof(struct stun_header)) { 00434 if (option_debug) 00435 ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header)); 00436 return -1; 00437 } 00438 if (stundebug) 00439 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen)); 00440 if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) { 00441 if (option_debug) 00442 ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header)); 00443 } else 00444 len = ntohs(hdr->msglen); 00445 data += sizeof(struct stun_header); 00446 memset(&st, 0, sizeof(st)); 00447 while(len) { 00448 if (len < sizeof(struct stun_attr)) { 00449 if (option_debug) 00450 ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr)); 00451 break; 00452 } 00453 attr = (struct stun_attr *)data; 00454 if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) { 00455 if (option_debug) 00456 ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len); 00457 break; 00458 } 00459 if (stun_process_attr(&st, attr)) { 00460 if (option_debug) 00461 ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00462 break; 00463 } 00464 /* Clear attribute in case previous entry was a string */ 00465 attr->attr = 0; 00466 data += ntohs(attr->len) + sizeof(struct stun_attr); 00467 len -= ntohs(attr->len) + sizeof(struct stun_attr); 00468 } 00469 /* Null terminate any string */ 00470 *data = '\0'; 00471 resp = (struct stun_header *)respdata; 00472 resplen = 0; 00473 respleft = sizeof(respdata) - sizeof(struct stun_header); 00474 resp->id = hdr->id; 00475 resp->msgtype = 0; 00476 resp->msglen = 0; 00477 attr = (struct stun_attr *)resp->ies; 00478 if (!len) { 00479 switch(ntohs(hdr->msgtype)) { 00480 case STUN_BINDREQ: 00481 if (stundebug) 00482 ast_verbose("STUN Bind Request, username: %s\n", 00483 st.username ? st.username : "<none>"); 00484 if (st.username) 00485 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00486 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00487 resp->msglen = htons(resplen); 00488 resp->msgtype = htons(STUN_BINDRESP); 00489 stun_send(s, src, resp); 00490 ret = STUN_ACCEPT; 00491 break; 00492 default: 00493 if (stundebug) 00494 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00495 } 00496 } 00497 return ret; 00498 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
Definition at line 281 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00282 { 00283 switch(msg) { 00284 case STUN_BINDREQ: 00285 return "Binding Request"; 00286 case STUN_BINDRESP: 00287 return "Binding Response"; 00288 case STUN_BINDERR: 00289 return "Binding Error Response"; 00290 case STUN_SECREQ: 00291 return "Shared Secret Request"; 00292 case STUN_SECRESP: 00293 return "Shared Secret Response"; 00294 case STUN_SECERR: 00295 return "Shared Secret Error Response"; 00296 } 00297 return "Non-RFC3489 Message"; 00298 }
static int stun_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3659 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03660 { 03661 if (argc != 3) 03662 return RESULT_SHOWUSAGE; 03663 stundebug = 0; 03664 ast_cli(fd, "STUN Debugging Disabled\n"); 03665 return RESULT_SUCCESS; 03666 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 334 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().
00335 { 00336 if (stundebug) 00337 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00338 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00339 switch(ntohs(attr->attr)) { 00340 case STUN_USERNAME: 00341 state->username = (const char *) (attr->value); 00342 break; 00343 case STUN_PASSWORD: 00344 state->password = (const char *) (attr->value); 00345 break; 00346 default: 00347 if (stundebug) 00348 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00349 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00350 } 00351 return 0; 00352 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
Definition at line 391 of file rtp.c.
References ast_random(), and stun_header::id.
Referenced by ast_rtp_stun_request().
00392 { 00393 int x; 00394 for (x=0;x<4;x++) 00395 req->id.id[x] = ast_random(); 00396 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
Definition at line 385 of file rtp.c.
References stun_header::msglen.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00386 { 00387 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00388 (struct sockaddr *)dst, sizeof(*dst)); 00389 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 503 of file rtp.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00504 { 00505 unsigned int sec, usec, frac; 00506 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00507 usec = tv.tv_usec; 00508 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00509 *msw = sec; 00510 *lsw = frac; 00511 }
struct ast_cli_entry cli_rtp[] [static] |
struct ast_cli_entry cli_rtp_no_debug_deprecated [static] |
Initial value:
{ { "rtp", "no", "debug", NULL }, rtp_no_debug, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_debug_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "debug", NULL }, rtcp_do_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "debug", "ip", NULL }, rtcp_do_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "no", "debug", NULL }, rtcp_no_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "no", "stats", NULL }, rtcp_no_stats_deprecated, NULL, NULL }
struct ast_cli_entry cli_rtp_rtcp_stats_deprecated [static] |
Initial value:
{ { "rtp", "rtcp", "stats", NULL }, rtcp_do_stats_deprecated, NULL, NULL }
struct ast_cli_entry cli_stun_no_debug_deprecated [static] |
Initial value:
{ { "stun", "no", "debug", NULL }, stun_no_debug, NULL, NULL }
char debug_usage[] [static] |
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
struct { ... } mimeTypes[] [static] |
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
char no_debug_usage[] [static] |
Referenced by get_unaligned_uint16(), get_unaligned_uint32(), put_unaligned_uint16(), and put_unaligned_uint32().
struct rtpPayloadType payloadType |
Definition at line 1349 of file rtp.c.
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
char rtcp_debug_usage[] [static] |
char rtcp_no_debug_usage[] [static] |
char rtcp_no_stats_usage[] [static] |
char rtcp_stats_usage[] [static] |
struct sockaddr_in rtcpdebugaddr [static] |
Debug RTCP packets to/from this host
Definition at line 88 of file rtp.c.
Referenced by rtcp_debug_test_addr(), rtcp_do_debug(), rtcp_do_debug_deprecated(), rtcp_do_debug_ip(), and rtcp_do_debug_ip_deprecated().
int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static] |
struct sockaddr_in rtpdebugaddr [static] |
Debug packets to/from this host
Definition at line 87 of file rtp.c.
Referenced by rtp_debug_test_addr(), rtp_do_debug(), and rtp_do_debug_ip().
int rtpend [static] |
int rtpstart [static] |
struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static] |
char stun_debug_usage[] [static] |
char stun_no_debug_usage[] [static] |
char* subtype |
char* type |
Definition at line 1350 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), acf_channel_read(), aji_handle_presence(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_connect(), build_setup(), check_header(), find_subscription_type(), g723_len(), load_module(), misdn_cfg_get(), misdn_cfg_get_config_string(), msg_timestamp(), parse_information(), parse_setup(), sla_load_config(), subscription_type2str(), and yyparse().