#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. | |
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. | |
void | ast_rtp_new_source (struct ast_rtp *rtp) |
struct ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr) |
Initializate a RTP session using an in_addr structure. | |
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
Register interface to channel driver. | |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
Unregister interface to channel driver. | |
void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
Setting RTP payload types from lines in a SDP description:. | |
void | ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src) |
Copy payload types between RTP structures. | |
void | ast_rtp_pt_default (struct ast_rtp *rtp) |
Set payload types to defaults. | |
static int | ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec) |
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 | |
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 1858 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().
01859 { 01860 struct ast_rtcp *rtcp; 01861 01862 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01863 return NULL; 01864 rtcp->s = rtp_socket(); 01865 rtcp->us.sin_family = AF_INET; 01866 rtcp->them.sin_family = AF_INET; 01867 rtcp->schedid = -1; 01868 01869 if (rtcp->s < 0) { 01870 free(rtcp); 01871 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01872 return NULL; 01873 } 01874 01875 return rtcp; 01876 }
Definition at line 826 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().
00827 { 00828 socklen_t len; 00829 int position, i, packetwords; 00830 int res; 00831 struct sockaddr_in sin; 00832 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00833 unsigned int *rtcpheader; 00834 int pt; 00835 struct timeval now; 00836 unsigned int length; 00837 int rc; 00838 double rttsec; 00839 uint64_t rtt = 0; 00840 unsigned int dlsr; 00841 unsigned int lsr; 00842 unsigned int msw; 00843 unsigned int lsw; 00844 unsigned int comp; 00845 struct ast_frame *f = &ast_null_frame; 00846 00847 if (!rtp || !rtp->rtcp) 00848 return &ast_null_frame; 00849 00850 len = sizeof(sin); 00851 00852 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00853 0, (struct sockaddr *)&sin, &len); 00854 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00855 00856 if (res < 0) { 00857 ast_assert(errno != EBADF); 00858 if (errno != EAGAIN) { 00859 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00860 return NULL; 00861 } 00862 return &ast_null_frame; 00863 } 00864 00865 packetwords = res / 4; 00866 00867 if (rtp->nat) { 00868 /* Send to whoever sent to us */ 00869 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00870 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00871 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00872 if (option_debug || rtpdebug) 00873 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)); 00874 } 00875 } 00876 00877 if (option_debug) 00878 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00879 00880 /* Process a compound packet */ 00881 position = 0; 00882 while (position < packetwords) { 00883 i = position; 00884 length = ntohl(rtcpheader[i]); 00885 pt = (length & 0xff0000) >> 16; 00886 rc = (length & 0x1f000000) >> 24; 00887 length &= 0xffff; 00888 00889 if ((i + length) > packetwords) { 00890 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00891 return &ast_null_frame; 00892 } 00893 00894 if (rtcp_debug_test_addr(&sin)) { 00895 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00896 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00897 ast_verbose("Reception reports: %d\n", rc); 00898 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00899 } 00900 00901 i += 2; /* Advance past header and ssrc */ 00902 00903 switch (pt) { 00904 case RTCP_PT_SR: 00905 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00906 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00907 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00908 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00909 00910 if (rtcp_debug_test_addr(&sin)) { 00911 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00912 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00913 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00914 } 00915 i += 5; 00916 if (rc < 1) 00917 break; 00918 /* Intentional fall through */ 00919 case RTCP_PT_RR: 00920 /* Don't handle multiple reception reports (rc > 1) yet */ 00921 /* Calculate RTT per RFC */ 00922 gettimeofday(&now, NULL); 00923 timeval2ntp(now, &msw, &lsw); 00924 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00925 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00926 lsr = ntohl(rtcpheader[i + 4]); 00927 dlsr = ntohl(rtcpheader[i + 5]); 00928 rtt = comp - lsr - dlsr; 00929 00930 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00931 sess->ee_delay = (eedelay * 1000) / 65536; */ 00932 if (rtt < 4294) { 00933 rtt = (rtt * 1000000) >> 16; 00934 } else { 00935 rtt = (rtt * 1000) >> 16; 00936 rtt *= 1000; 00937 } 00938 rtt = rtt / 1000.; 00939 rttsec = rtt / 1000.; 00940 00941 if (comp - dlsr >= lsr) { 00942 rtp->rtcp->accumulated_transit += rttsec; 00943 rtp->rtcp->rtt = rttsec; 00944 if (rtp->rtcp->maxrtt<rttsec) 00945 rtp->rtcp->maxrtt = rttsec; 00946 if (rtp->rtcp->minrtt>rttsec) 00947 rtp->rtcp->minrtt = rttsec; 00948 } else if (rtcp_debug_test_addr(&sin)) { 00949 ast_verbose("Internal RTCP NTP clock skew detected: " 00950 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 00951 "diff=%d\n", 00952 lsr, comp, dlsr, dlsr / 65536, 00953 (dlsr % 65536) * 1000 / 65536, 00954 dlsr - (comp - lsr)); 00955 } 00956 } 00957 00958 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00959 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00960 if (rtcp_debug_test_addr(&sin)) { 00961 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00962 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00963 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00964 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00965 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00966 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00967 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00968 if (rtt) 00969 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 00970 } 00971 break; 00972 case RTCP_PT_FUR: 00973 if (rtcp_debug_test_addr(&sin)) 00974 ast_verbose("Received an RTCP Fast Update Request\n"); 00975 rtp->f.frametype = AST_FRAME_CONTROL; 00976 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00977 rtp->f.datalen = 0; 00978 rtp->f.samples = 0; 00979 rtp->f.mallocd = 0; 00980 rtp->f.src = "RTP"; 00981 f = &rtp->f; 00982 break; 00983 case RTCP_PT_SDES: 00984 if (rtcp_debug_test_addr(&sin)) 00985 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00986 break; 00987 case RTCP_PT_BYE: 00988 if (rtcp_debug_test_addr(&sin)) 00989 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00990 break; 00991 default: 00992 if (option_debug) 00993 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)); 00994 break; 00995 } 00996 position += (length + 1); 00997 } 00998 00999 return f; 01000 }
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 2340 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02341 { 02342 struct ast_rtp *rtp = data; 02343 int res; 02344 02345 rtp->rtcp->sendfur = 1; 02346 res = ast_rtcp_write(data); 02347 02348 return res; 02349 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2557 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().
02558 { 02559 struct ast_rtp *rtp = (struct ast_rtp *)data; 02560 int res; 02561 02562 if (!rtp || !rtp->rtcp) 02563 return 0; 02564 02565 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02566 res = ast_rtcp_write_sr(data); 02567 else 02568 res = ast_rtcp_write_rr(data); 02569 02570 return res; 02571 }
static int ast_rtcp_write_rr | ( | const void * | data | ) | [static] |
Send RTCP recepient's report.
Definition at line 2462 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().
02463 { 02464 struct ast_rtp *rtp = (struct ast_rtp *)data; 02465 int res; 02466 int len = 32; 02467 unsigned int lost; 02468 unsigned int extended; 02469 unsigned int expected; 02470 unsigned int expected_interval; 02471 unsigned int received_interval; 02472 int lost_interval; 02473 struct timeval now; 02474 unsigned int *rtcpheader; 02475 char bdata[1024]; 02476 struct timeval dlsr; 02477 int fraction; 02478 02479 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02480 return 0; 02481 02482 if (!rtp->rtcp->them.sin_addr.s_addr) { 02483 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02484 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02485 return 0; 02486 } 02487 02488 extended = rtp->cycles + rtp->lastrxseqno; 02489 expected = extended - rtp->seedrxseqno + 1; 02490 lost = expected - rtp->rxcount; 02491 expected_interval = expected - rtp->rtcp->expected_prior; 02492 rtp->rtcp->expected_prior = expected; 02493 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02494 rtp->rtcp->received_prior = rtp->rxcount; 02495 lost_interval = expected_interval - received_interval; 02496 if (expected_interval == 0 || lost_interval <= 0) 02497 fraction = 0; 02498 else 02499 fraction = (lost_interval << 8) / expected_interval; 02500 gettimeofday(&now, NULL); 02501 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02502 rtcpheader = (unsigned int *)bdata; 02503 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02504 rtcpheader[1] = htonl(rtp->ssrc); 02505 rtcpheader[2] = htonl(rtp->themssrc); 02506 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02507 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02508 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02509 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02510 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02511 02512 if (rtp->rtcp->sendfur) { 02513 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02514 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02515 len += 8; 02516 rtp->rtcp->sendfur = 0; 02517 } 02518 02519 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02520 it can change mid call, and SDES can't) */ 02521 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02522 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02523 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02524 len += 12; 02525 02526 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02527 02528 if (res < 0) { 02529 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02530 /* Remove the scheduler */ 02531 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02532 return 0; 02533 } 02534 02535 rtp->rtcp->rr_count++; 02536 02537 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02538 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02539 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02540 " IA jitter: %.4f\n" 02541 " Their last SR: %u\n" 02542 " DLSR: %4.4f (sec)\n\n", 02543 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02544 ntohs(rtp->rtcp->them.sin_port), 02545 rtp->ssrc, rtp->themssrc, fraction, lost, 02546 rtp->rxjitter, 02547 rtp->rtcp->themrxlsr, 02548 (double)(ntohl(rtcpheader[7])/65536.0)); 02549 } 02550 02551 return res; 02552 }
static int ast_rtcp_write_sr | ( | const void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2352 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().
02353 { 02354 struct ast_rtp *rtp = (struct ast_rtp *)data; 02355 int res; 02356 int len = 0; 02357 struct timeval now; 02358 unsigned int now_lsw; 02359 unsigned int now_msw; 02360 unsigned int *rtcpheader; 02361 unsigned int lost; 02362 unsigned int extended; 02363 unsigned int expected; 02364 unsigned int expected_interval; 02365 unsigned int received_interval; 02366 int lost_interval; 02367 int fraction; 02368 struct timeval dlsr; 02369 char bdata[512]; 02370 02371 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02372 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02373 return 0; 02374 02375 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02376 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02377 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02378 return 0; 02379 } 02380 02381 gettimeofday(&now, NULL); 02382 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02383 rtcpheader = (unsigned int *)bdata; 02384 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02385 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02386 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02387 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02388 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02389 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02390 len += 28; 02391 02392 extended = rtp->cycles + rtp->lastrxseqno; 02393 expected = extended - rtp->seedrxseqno + 1; 02394 if (rtp->rxcount > expected) 02395 expected += rtp->rxcount - expected; 02396 lost = expected - rtp->rxcount; 02397 expected_interval = expected - rtp->rtcp->expected_prior; 02398 rtp->rtcp->expected_prior = expected; 02399 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02400 rtp->rtcp->received_prior = rtp->rxcount; 02401 lost_interval = expected_interval - received_interval; 02402 if (expected_interval == 0 || lost_interval <= 0) 02403 fraction = 0; 02404 else 02405 fraction = (lost_interval << 8) / expected_interval; 02406 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02407 rtcpheader[7] = htonl(rtp->themssrc); 02408 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02409 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02410 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02411 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02412 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02413 len += 24; 02414 02415 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02416 02417 if (rtp->rtcp->sendfur) { 02418 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02419 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02420 len += 8; 02421 rtp->rtcp->sendfur = 0; 02422 } 02423 02424 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02425 /* it can change mid call, and SDES can't) */ 02426 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02427 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02428 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02429 len += 12; 02430 02431 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02432 if (res < 0) { 02433 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)); 02434 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02435 return 0; 02436 } 02437 02438 /* FIXME Don't need to get a new one */ 02439 gettimeofday(&rtp->rtcp->txlsr, NULL); 02440 rtp->rtcp->sr_count++; 02441 02442 rtp->rtcp->lastsrtxcount = rtp->txcount; 02443 02444 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02445 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02446 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02447 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02448 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02449 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02450 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02451 ast_verbose(" Report block:\n"); 02452 ast_verbose(" Fraction lost: %u\n", fraction); 02453 ast_verbose(" Cumulative loss: %u\n", lost); 02454 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02455 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02456 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02457 } 02458 return res; 02459 }
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 3278 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.
03279 { 03280 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03281 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03282 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03283 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03284 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03285 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03286 int codec0 = 0, codec1 = 0; 03287 void *pvt0 = NULL, *pvt1 = NULL; 03288 03289 /* Lock channels */ 03290 ast_channel_lock(c0); 03291 while(ast_channel_trylock(c1)) { 03292 ast_channel_unlock(c0); 03293 usleep(1); 03294 ast_channel_lock(c0); 03295 } 03296 03297 /* Ensure neither channel got hungup during lock avoidance */ 03298 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03299 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03300 ast_channel_unlock(c0); 03301 ast_channel_unlock(c1); 03302 return AST_BRIDGE_FAILED; 03303 } 03304 03305 /* Find channel driver interfaces */ 03306 if (!(pr0 = get_proto(c0))) { 03307 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03308 ast_channel_unlock(c0); 03309 ast_channel_unlock(c1); 03310 return AST_BRIDGE_FAILED; 03311 } 03312 if (!(pr1 = get_proto(c1))) { 03313 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03314 ast_channel_unlock(c0); 03315 ast_channel_unlock(c1); 03316 return AST_BRIDGE_FAILED; 03317 } 03318 03319 /* Get channel specific interface structures */ 03320 pvt0 = c0->tech_pvt; 03321 pvt1 = c1->tech_pvt; 03322 03323 /* Get audio and video interface (if native bridge is possible) */ 03324 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03325 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03326 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03327 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03328 03329 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03330 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03331 audio_p0_res = AST_RTP_GET_FAILED; 03332 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03333 audio_p1_res = AST_RTP_GET_FAILED; 03334 03335 /* Check if a bridge is possible (partial/native) */ 03336 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03337 /* Somebody doesn't want to play... */ 03338 ast_channel_unlock(c0); 03339 ast_channel_unlock(c1); 03340 return AST_BRIDGE_FAILED_NOWARN; 03341 } 03342 03343 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03344 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03345 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03346 audio_p0_res = AST_RTP_TRY_PARTIAL; 03347 } 03348 03349 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03350 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03351 audio_p1_res = AST_RTP_TRY_PARTIAL; 03352 } 03353 03354 /* If both sides are not using the same method of DTMF transmission 03355 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03356 * -------------------------------------------------- 03357 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03358 * |-----------|------------|-----------------------| 03359 * | Inband | False | True | 03360 * | RFC2833 | True | True | 03361 * | SIP INFO | False | False | 03362 * -------------------------------------------------- 03363 * However, if DTMF from both channels is being monitored by the core, then 03364 * we can still do packet-to-packet bridging, because passing through the 03365 * core will handle DTMF mode translation. 03366 */ 03367 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03368 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03369 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03370 ast_channel_unlock(c0); 03371 ast_channel_unlock(c1); 03372 return AST_BRIDGE_FAILED_NOWARN; 03373 } 03374 audio_p0_res = AST_RTP_TRY_PARTIAL; 03375 audio_p1_res = AST_RTP_TRY_PARTIAL; 03376 } 03377 03378 /* If we need to feed frames into the core don't do a P2P bridge */ 03379 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 03380 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 03381 ast_channel_unlock(c0); 03382 ast_channel_unlock(c1); 03383 return AST_BRIDGE_FAILED_NOWARN; 03384 } 03385 03386 /* Get codecs from both sides */ 03387 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03388 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03389 if (codec0 && codec1 && !(codec0 & codec1)) { 03390 /* Hey, we can't do native bridging if both parties speak different codecs */ 03391 if (option_debug) 03392 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03393 ast_channel_unlock(c0); 03394 ast_channel_unlock(c1); 03395 return AST_BRIDGE_FAILED_NOWARN; 03396 } 03397 03398 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03399 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03400 struct ast_format_list fmt0, fmt1; 03401 03402 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03403 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03404 if (option_debug) 03405 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03406 ast_channel_unlock(c0); 03407 ast_channel_unlock(c1); 03408 return AST_BRIDGE_FAILED_NOWARN; 03409 } 03410 /* They must also be using the same packetization */ 03411 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03412 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03413 if (fmt0.cur_ms != fmt1.cur_ms) { 03414 if (option_debug) 03415 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03416 ast_channel_unlock(c0); 03417 ast_channel_unlock(c1); 03418 return AST_BRIDGE_FAILED_NOWARN; 03419 } 03420 03421 if (option_verbose > 2) 03422 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03423 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03424 } else { 03425 if (option_verbose > 2) 03426 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03427 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03428 } 03429 03430 return res; 03431 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2722 of file rtp.c.
References rtpPayloadType::code, and MAX_RTP_PT.
Referenced by process_sdp().
02723 { 02724 if (pt < 0 || pt > MAX_RTP_PT) 02725 return 0; /* bogus payload type */ 02726 02727 if (static_RTP_PT[pt].isAstFormat) 02728 return static_RTP_PT[pt].code; 02729 else 02730 return 0; 02731 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) | [read] |
Definition at line 2717 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
02718 { 02719 return &rtp->pref; 02720 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2704 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().
02705 { 02706 int x; 02707 for (x = 0; x < 32; x++) { /* Ugly way */ 02708 rtp->pref.order[x] = prefs->order[x]; 02709 rtp->pref.framing[x] = prefs->framing[x]; 02710 } 02711 if (rtp->smoother) 02712 ast_smoother_free(rtp->smoother); 02713 rtp->smoother = NULL; 02714 return 0; 02715 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2123 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().
02124 { 02125 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02126 /*Print some info on the call here */ 02127 ast_verbose(" RTP-stats\n"); 02128 ast_verbose("* Our Receiver:\n"); 02129 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02130 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02131 ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02132 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02133 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02134 ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count); 02135 ast_verbose("* Our Sender:\n"); 02136 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02137 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02138 ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost); 02139 ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0); 02140 ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count); 02141 ast_verbose(" RTT: %f\n", rtp->rtcp->rtt); 02142 } 02143 02144 if (rtp->smoother) 02145 ast_smoother_free(rtp->smoother); 02146 if (rtp->ioid) 02147 ast_io_remove(rtp->io, rtp->ioid); 02148 if (rtp->s > -1) 02149 close(rtp->s); 02150 if (rtp->rtcp) { 02151 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02152 close(rtp->rtcp->s); 02153 free(rtp->rtcp); 02154 rtp->rtcp=NULL; 02155 } 02156 02157 ast_mutex_destroy(&rtp->bridge_lock); 02158 02159 free(rtp); 02160 }
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 1475 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().
01476 { 01477 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01478 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01479 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01480 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01481 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01482 int srccodec, destcodec, nat_active = 0; 01483 01484 /* Lock channels */ 01485 ast_channel_lock(dest); 01486 if (src) { 01487 while(ast_channel_trylock(src)) { 01488 ast_channel_unlock(dest); 01489 usleep(1); 01490 ast_channel_lock(dest); 01491 } 01492 } 01493 01494 /* Find channel driver interfaces */ 01495 destpr = get_proto(dest); 01496 if (src) 01497 srcpr = get_proto(src); 01498 if (!destpr) { 01499 if (option_debug) 01500 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01501 ast_channel_unlock(dest); 01502 if (src) 01503 ast_channel_unlock(src); 01504 return 0; 01505 } 01506 if (!srcpr) { 01507 if (option_debug) 01508 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01509 ast_channel_unlock(dest); 01510 if (src) 01511 ast_channel_unlock(src); 01512 return 0; 01513 } 01514 01515 /* Get audio and video interface (if native bridge is possible) */ 01516 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01517 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01518 if (srcpr) { 01519 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01520 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01521 } 01522 01523 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01524 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01525 /* Somebody doesn't want to play... */ 01526 ast_channel_unlock(dest); 01527 if (src) 01528 ast_channel_unlock(src); 01529 return 0; 01530 } 01531 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01532 srccodec = srcpr->get_codec(src); 01533 else 01534 srccodec = 0; 01535 if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec) 01536 destcodec = destpr->get_codec(dest); 01537 else 01538 destcodec = 0; 01539 /* Ensure we have at least one matching codec */ 01540 if (!(srccodec & destcodec)) { 01541 ast_channel_unlock(dest); 01542 if (src) 01543 ast_channel_unlock(src); 01544 return 0; 01545 } 01546 /* Consider empty media as non-existant */ 01547 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01548 srcp = NULL; 01549 /* If the client has NAT stuff turned on then just safe NAT is active */ 01550 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01551 nat_active = 1; 01552 /* Bridge media early */ 01553 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01554 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01555 ast_channel_unlock(dest); 01556 if (src) 01557 ast_channel_unlock(src); 01558 if (option_debug) 01559 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01560 return 1; 01561 }
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 2034 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().
02035 { 02036 struct ast_rtp *bridged = NULL; 02037 02038 ast_mutex_lock(&rtp->bridge_lock); 02039 bridged = rtp->bridged; 02040 ast_mutex_unlock(&rtp->bridge_lock); 02041 02042 return bridged; 02043 }
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 1697 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().
01699 { 01700 int pt; 01701 01702 ast_mutex_lock(&rtp->bridge_lock); 01703 01704 *astFormats = *nonAstFormats = 0; 01705 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01706 if (rtp->current_RTP_PT[pt].isAstFormat) { 01707 *astFormats |= rtp->current_RTP_PT[pt].code; 01708 } else { 01709 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01710 } 01711 } 01712 01713 ast_mutex_unlock(&rtp->bridge_lock); 01714 01715 return; 01716 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2016 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().
02017 { 02018 if ((them->sin_family != AF_INET) || 02019 (them->sin_port != rtp->them.sin_port) || 02020 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02021 them->sin_family = AF_INET; 02022 them->sin_port = rtp->them.sin_port; 02023 them->sin_addr = rtp->them.sin_addr; 02024 return 1; 02025 } 02026 return 0; 02027 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2079 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().
02080 { 02081 /* 02082 *ssrc our ssrc 02083 *themssrc their ssrc 02084 *lp lost packets 02085 *rxjitter our calculated jitter(rx) 02086 *rxcount no. received packets 02087 *txjitter reported jitter of the other end 02088 *txcount transmitted packets 02089 *rlp remote lost packets 02090 *rtt round trip time 02091 */ 02092 02093 if (qual && rtp) { 02094 qual->local_ssrc = rtp->ssrc; 02095 qual->local_jitter = rtp->rxjitter; 02096 qual->local_count = rtp->rxcount; 02097 qual->remote_ssrc = rtp->themssrc; 02098 qual->remote_count = rtp->txcount; 02099 if (rtp->rtcp) { 02100 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02101 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02102 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02103 qual->rtt = rtp->rtcp->rtt; 02104 } 02105 } 02106 if (rtp->rtcp) { 02107 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02108 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02109 rtp->ssrc, 02110 rtp->themssrc, 02111 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02112 rtp->rxjitter, 02113 rtp->rxcount, 02114 (double)rtp->rtcp->reported_jitter / 65536.0, 02115 rtp->txcount, 02116 rtp->rtcp->reported_lost, 02117 rtp->rtcp->rtt); 02118 return rtp->rtcp->quality; 02119 } else 02120 return "<Unknown> - RTP/RTCP has already been destroyed"; 02121 }
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 2029 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 3816 of file rtp.c.
References ast_cli_register_multiple(), and ast_rtp_reload().
Referenced by main().
03817 { 03818 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03819 ast_rtp_reload(); 03820 }
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 1740 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().
01741 { 01742 int pt = 0; 01743 01744 ast_mutex_lock(&rtp->bridge_lock); 01745 01746 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01747 code == rtp->rtp_lookup_code_cache_code) { 01748 /* Use our cached mapping, to avoid the overhead of the loop below */ 01749 pt = rtp->rtp_lookup_code_cache_result; 01750 ast_mutex_unlock(&rtp->bridge_lock); 01751 return pt; 01752 } 01753 01754 /* Check the dynamic list first */ 01755 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01756 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01757 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01758 rtp->rtp_lookup_code_cache_code = code; 01759 rtp->rtp_lookup_code_cache_result = pt; 01760 ast_mutex_unlock(&rtp->bridge_lock); 01761 return pt; 01762 } 01763 } 01764 01765 /* Then the static list */ 01766 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01767 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01768 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01769 rtp->rtp_lookup_code_cache_code = code; 01770 rtp->rtp_lookup_code_cache_result = pt; 01771 ast_mutex_unlock(&rtp->bridge_lock); 01772 return pt; 01773 } 01774 } 01775 01776 ast_mutex_unlock(&rtp->bridge_lock); 01777 01778 return -1; 01779 }
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 1800 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len, and name.
Referenced by process_sdp().
01802 { 01803 int format; 01804 unsigned len; 01805 char *end = buf; 01806 char *start = buf; 01807 01808 if (!buf || !size) 01809 return NULL; 01810 01811 snprintf(end, size, "0x%x (", capability); 01812 01813 len = strlen(end); 01814 end += len; 01815 size -= len; 01816 start = end; 01817 01818 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01819 if (capability & format) { 01820 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01821 01822 snprintf(end, size, "%s|", name); 01823 len = strlen(end); 01824 end += len; 01825 size -= len; 01826 } 01827 } 01828 01829 if (start == end) 01830 snprintf(start, size, "nothing)"); 01831 else if (size > 1) 01832 *(end -1) = ')'; 01833 01834 return buf; 01835 }
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 1781 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().
01783 { 01784 unsigned int i; 01785 01786 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01787 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01788 if (isAstFormat && 01789 (code == AST_FORMAT_G726_AAL2) && 01790 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01791 return "G726-32"; 01792 else 01793 return mimeTypes[i].subtype; 01794 } 01795 } 01796 01797 return ""; 01798 }
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 1718 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().
01719 { 01720 struct rtpPayloadType result; 01721 01722 result.isAstFormat = result.code = 0; 01723 01724 if (pt < 0 || pt > MAX_RTP_PT) 01725 return result; /* bogus payload type */ 01726 01727 /* Start with negotiated codecs */ 01728 ast_mutex_lock(&rtp->bridge_lock); 01729 result = rtp->current_RTP_PT[pt]; 01730 ast_mutex_unlock(&rtp->bridge_lock); 01731 01732 /* If it doesn't exist, check our static RTP type list, just in case */ 01733 if (!result.code) 01734 result = static_RTP_PT[pt]; 01735 01736 return result; 01737 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1563 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().
01564 { 01565 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01566 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01567 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01568 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01569 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01570 int srccodec, destcodec; 01571 01572 /* Lock channels */ 01573 ast_channel_lock(dest); 01574 while(ast_channel_trylock(src)) { 01575 ast_channel_unlock(dest); 01576 usleep(1); 01577 ast_channel_lock(dest); 01578 } 01579 01580 /* Find channel driver interfaces */ 01581 if (!(destpr = get_proto(dest))) { 01582 if (option_debug) 01583 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01584 ast_channel_unlock(dest); 01585 ast_channel_unlock(src); 01586 return 0; 01587 } 01588 if (!(srcpr = get_proto(src))) { 01589 if (option_debug) 01590 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01591 ast_channel_unlock(dest); 01592 ast_channel_unlock(src); 01593 return 0; 01594 } 01595 01596 /* Get audio and video interface (if native bridge is possible) */ 01597 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01598 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01599 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01600 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01601 01602 /* Ensure we have at least one matching codec */ 01603 if (srcpr->get_codec) 01604 srccodec = srcpr->get_codec(src); 01605 else 01606 srccodec = 0; 01607 if (destpr->get_codec) 01608 destcodec = destpr->get_codec(dest); 01609 else 01610 destcodec = 0; 01611 01612 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01613 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) { 01614 /* Somebody doesn't want to play... */ 01615 ast_channel_unlock(dest); 01616 ast_channel_unlock(src); 01617 return 0; 01618 } 01619 ast_rtp_pt_copy(destp, srcp); 01620 if (vdestp && vsrcp) 01621 ast_rtp_pt_copy(vdestp, vsrcp); 01622 if (media) { 01623 /* Bridge early */ 01624 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01625 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01626 } 01627 ast_channel_unlock(dest); 01628 ast_channel_unlock(src); 01629 if (option_debug) 01630 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01631 return 1; 01632 }
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 1982 of file rtp.c.
References ast_rtp_new_with_bindaddr().
01983 { 01984 struct in_addr ia; 01985 01986 memset(&ia, 0, sizeof(ia)); 01987 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 01988 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1882 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().
01883 { 01884 ast_mutex_init(&rtp->bridge_lock); 01885 01886 rtp->them.sin_family = AF_INET; 01887 rtp->us.sin_family = AF_INET; 01888 rtp->ssrc = ast_random(); 01889 rtp->seqno = ast_random() & 0xffff; 01890 ast_set_flag(rtp, FLAG_HAS_DTMF); 01891 01892 return; 01893 }
void ast_rtp_new_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 1999 of file rtp.c.
References ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), sip_write(), and skinny_indicate().
02000 { 02001 rtp->set_marker_bit = 1; 02002 return; 02003 }
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 1895 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().
01896 { 01897 struct ast_rtp *rtp; 01898 int x; 01899 int first; 01900 int startplace; 01901 01902 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01903 return NULL; 01904 01905 ast_rtp_new_init(rtp); 01906 01907 rtp->s = rtp_socket(); 01908 if (rtp->s < 0) { 01909 free(rtp); 01910 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01911 return NULL; 01912 } 01913 if (sched && rtcpenable) { 01914 rtp->sched = sched; 01915 rtp->rtcp = ast_rtcp_new(); 01916 } 01917 01918 /* Select a random port number in the range of possible RTP */ 01919 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01920 x = x & ~1; 01921 /* Save it for future references. */ 01922 startplace = x; 01923 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01924 for (;;) { 01925 /* Must be an even port number by RTP spec */ 01926 rtp->us.sin_port = htons(x); 01927 rtp->us.sin_addr = addr; 01928 /* If there's rtcp, initialize it as well. */ 01929 if (rtp->rtcp) { 01930 rtp->rtcp->us.sin_port = htons(x + 1); 01931 rtp->rtcp->us.sin_addr = addr; 01932 } 01933 /* Try to bind it/them. */ 01934 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01935 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01936 break; 01937 if (!first) { 01938 /* Primary bind succeeded! Gotta recreate it */ 01939 close(rtp->s); 01940 rtp->s = rtp_socket(); 01941 } 01942 if (errno != EADDRINUSE) { 01943 /* We got an error that wasn't expected, abort! */ 01944 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01945 close(rtp->s); 01946 if (rtp->rtcp) { 01947 close(rtp->rtcp->s); 01948 free(rtp->rtcp); 01949 } 01950 free(rtp); 01951 return NULL; 01952 } 01953 /* The port was used, increment it (by two). */ 01954 x += 2; 01955 /* Did we go over the limit ? */ 01956 if (x > rtpend) 01957 /* then, start from the begingig. */ 01958 x = (rtpstart + 1) & ~1; 01959 /* Check if we reached the place were we started. */ 01960 if (x == startplace) { 01961 /* If so, there's no ports available. */ 01962 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01963 close(rtp->s); 01964 if (rtp->rtcp) { 01965 close(rtp->rtcp->s); 01966 free(rtp->rtcp); 01967 } 01968 free(rtp); 01969 return NULL; 01970 } 01971 } 01972 rtp->sched = sched; 01973 rtp->io = io; 01974 if (callbackmode) { 01975 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01976 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01977 } 01978 ast_rtp_pt_default(rtp); 01979 return rtp; 01980 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2833 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().
02834 { 02835 struct ast_rtp_protocol *cur; 02836 02837 AST_LIST_LOCK(&protos); 02838 AST_LIST_TRAVERSE(&protos, cur, list) { 02839 if (!strcmp(cur->type, proto->type)) { 02840 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02841 AST_LIST_UNLOCK(&protos); 02842 return -1; 02843 } 02844 } 02845 AST_LIST_INSERT_HEAD(&protos, proto, list); 02846 AST_LIST_UNLOCK(&protos); 02847 02848 return 0; 02849 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2825 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.
Referenced by load_module(), and unload_module().
02826 { 02827 AST_LIST_LOCK(&protos); 02828 AST_LIST_REMOVE(&protos, proto, list); 02829 AST_LIST_UNLOCK(&protos); 02830 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1399 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().
01400 { 01401 int i; 01402 01403 if (!rtp) 01404 return; 01405 01406 ast_mutex_lock(&rtp->bridge_lock); 01407 01408 for (i = 0; i < MAX_RTP_PT; ++i) { 01409 rtp->current_RTP_PT[i].isAstFormat = 0; 01410 rtp->current_RTP_PT[i].code = 0; 01411 } 01412 01413 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01414 rtp->rtp_lookup_code_cache_code = 0; 01415 rtp->rtp_lookup_code_cache_result = 0; 01416 01417 ast_mutex_unlock(&rtp->bridge_lock); 01418 }
Copy payload types between RTP structures.
Definition at line 1439 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().
01440 { 01441 unsigned int i; 01442 01443 ast_mutex_lock(&dest->bridge_lock); 01444 ast_mutex_lock(&src->bridge_lock); 01445 01446 for (i=0; i < MAX_RTP_PT; ++i) { 01447 dest->current_RTP_PT[i].isAstFormat = 01448 src->current_RTP_PT[i].isAstFormat; 01449 dest->current_RTP_PT[i].code = 01450 src->current_RTP_PT[i].code; 01451 } 01452 dest->rtp_lookup_code_cache_isAstFormat = 0; 01453 dest->rtp_lookup_code_cache_code = 0; 01454 dest->rtp_lookup_code_cache_result = 0; 01455 01456 ast_mutex_unlock(&src->bridge_lock); 01457 ast_mutex_unlock(&dest->bridge_lock); 01458 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1420 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().
01421 { 01422 int i; 01423 01424 ast_mutex_lock(&rtp->bridge_lock); 01425 01426 /* Initialize to default payload types */ 01427 for (i = 0; i < MAX_RTP_PT; ++i) { 01428 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01429 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01430 } 01431 01432 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01433 rtp->rtp_lookup_code_cache_code = 0; 01434 rtp->rtp_lookup_code_cache_result = 0; 01435 01436 ast_mutex_unlock(&rtp->bridge_lock); 01437 }
Definition at line 2608 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().
02609 { 02610 unsigned char *rtpheader; 02611 int hdrlen = 12; 02612 int res; 02613 unsigned int ms; 02614 int pred; 02615 int mark = 0; 02616 02617 ms = calc_txstamp(rtp, &f->delivery); 02618 /* Default prediction */ 02619 if (f->frametype == AST_FRAME_VOICE) { 02620 pred = rtp->lastts + f->samples; 02621 02622 /* Re-calculate last TS */ 02623 rtp->lastts = rtp->lastts + ms * 8; 02624 if (ast_tvzero(f->delivery)) { 02625 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02626 and if so, go with our prediction */ 02627 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02628 rtp->lastts = pred; 02629 else { 02630 if (option_debug > 2) 02631 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02632 mark = 1; 02633 } 02634 } 02635 } else if (f->frametype == AST_FRAME_VIDEO) { 02636 mark = f->subclass & 0x1; 02637 pred = rtp->lastovidtimestamp + f->samples; 02638 /* Re-calculate last TS */ 02639 rtp->lastts = rtp->lastts + ms * 90; 02640 /* If it's close to our prediction, go for it */ 02641 if (ast_tvzero(f->delivery)) { 02642 if (abs(rtp->lastts - pred) < 7200) { 02643 rtp->lastts = pred; 02644 rtp->lastovidtimestamp += f->samples; 02645 } else { 02646 if (option_debug > 2) 02647 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); 02648 rtp->lastovidtimestamp = rtp->lastts; 02649 } 02650 } 02651 } 02652 02653 /* If we have been explicitly told to set the marker bit do so */ 02654 if (rtp->set_marker_bit) { 02655 mark = 1; 02656 rtp->set_marker_bit = 0; 02657 } 02658 02659 /* If the timestamp for non-digit packets has moved beyond the timestamp 02660 for digits, update the digit timestamp. 02661 */ 02662 if (rtp->lastts > rtp->lastdigitts) 02663 rtp->lastdigitts = rtp->lastts; 02664 02665 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) 02666 rtp->lastts = f->ts * 8; 02667 02668 /* Get a pointer to the header */ 02669 rtpheader = (unsigned char *)(f->data - hdrlen); 02670 02671 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02672 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02673 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02674 02675 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02676 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02677 if (res <0) { 02678 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02679 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)); 02680 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02681 /* Only give this error message once if we are not RTP debugging */ 02682 if (option_debug || rtpdebug) 02683 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)); 02684 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02685 } 02686 } else { 02687 rtp->txcount++; 02688 rtp->txoctetcount +=(res - hdrlen); 02689 02690 if (rtp->rtcp && rtp->rtcp->schedid < 1) 02691 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02692 } 02693 02694 if (rtp_debug_test_addr(&rtp->them)) 02695 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02696 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02697 } 02698 02699 rtp->seqno++; 02700 02701 return 0; 02702 }
Definition at line 1104 of file rtp.c.
References ast_assert, ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_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, 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().
01105 { 01106 int res; 01107 struct sockaddr_in sin; 01108 socklen_t len; 01109 unsigned int seqno; 01110 int version; 01111 int payloadtype; 01112 int hdrlen = 12; 01113 int padding; 01114 int mark; 01115 int ext; 01116 int cc; 01117 unsigned int ssrc; 01118 unsigned int timestamp; 01119 unsigned int *rtpheader; 01120 struct rtpPayloadType rtpPT; 01121 struct ast_rtp *bridged = NULL; 01122 01123 /* If time is up, kill it */ 01124 if (rtp->sending_digit) 01125 ast_rtp_senddigit_continuation(rtp); 01126 01127 len = sizeof(sin); 01128 01129 /* Cache where the header will go */ 01130 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01131 0, (struct sockaddr *)&sin, &len); 01132 01133 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01134 if (res < 0) { 01135 ast_assert(errno != EBADF); 01136 if (errno != EAGAIN) { 01137 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01138 return NULL; 01139 } 01140 return &ast_null_frame; 01141 } 01142 01143 if (res < hdrlen) { 01144 ast_log(LOG_WARNING, "RTP Read too short\n"); 01145 return &ast_null_frame; 01146 } 01147 01148 /* Get fields */ 01149 seqno = ntohl(rtpheader[0]); 01150 01151 /* Check RTP version */ 01152 version = (seqno & 0xC0000000) >> 30; 01153 if (!version) { 01154 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01155 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01156 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01157 } 01158 return &ast_null_frame; 01159 } 01160 01161 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01162 /* If we don't have the other side's address, then ignore this */ 01163 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01164 return &ast_null_frame; 01165 #endif 01166 01167 /* Send to whoever send to us if NAT is turned on */ 01168 if (rtp->nat) { 01169 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01170 (rtp->them.sin_port != sin.sin_port)) { 01171 rtp->them = sin; 01172 if (rtp->rtcp) { 01173 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01174 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01175 } 01176 rtp->rxseqno = 0; 01177 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01178 if (option_debug || rtpdebug) 01179 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)); 01180 } 01181 } 01182 01183 /* If we are bridged to another RTP stream, send direct */ 01184 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01185 return &ast_null_frame; 01186 01187 if (version != 2) 01188 return &ast_null_frame; 01189 01190 payloadtype = (seqno & 0x7f0000) >> 16; 01191 padding = seqno & (1 << 29); 01192 mark = seqno & (1 << 23); 01193 ext = seqno & (1 << 28); 01194 cc = (seqno & 0xF000000) >> 24; 01195 seqno &= 0xffff; 01196 timestamp = ntohl(rtpheader[1]); 01197 ssrc = ntohl(rtpheader[2]); 01198 01199 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01200 if (option_debug || rtpdebug) 01201 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01202 mark = 1; 01203 } 01204 01205 rtp->rxssrc = ssrc; 01206 01207 if (padding) { 01208 /* Remove padding bytes */ 01209 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01210 } 01211 01212 if (cc) { 01213 /* CSRC fields present */ 01214 hdrlen += cc*4; 01215 } 01216 01217 if (ext) { 01218 /* RTP Extension present */ 01219 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01220 hdrlen += 4; 01221 } 01222 01223 if (res < hdrlen) { 01224 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01225 return &ast_null_frame; 01226 } 01227 01228 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01229 01230 if (rtp->rxcount==1) { 01231 /* This is the first RTP packet successfully received from source */ 01232 rtp->seedrxseqno = seqno; 01233 } 01234 01235 /* Do not schedule RR if RTCP isn't run */ 01236 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01237 /* Schedule transmission of Receiver Report */ 01238 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01239 } 01240 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01241 rtp->cycles += RTP_SEQ_MOD; 01242 01243 rtp->lastrxseqno = seqno; 01244 01245 if (rtp->themssrc==0) 01246 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01247 01248 if (rtp_debug_test_addr(&sin)) 01249 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01250 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01251 01252 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01253 if (!rtpPT.isAstFormat) { 01254 struct ast_frame *f = NULL; 01255 01256 /* This is special in-band data that's not one of our codecs */ 01257 if (rtpPT.code == AST_RTP_DTMF) { 01258 /* It's special -- rfc2833 process it */ 01259 if (rtp_debug_test_addr(&sin)) { 01260 unsigned char *data; 01261 unsigned int event; 01262 unsigned int event_end; 01263 unsigned int duration; 01264 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01265 event = ntohl(*((unsigned int *)(data))); 01266 event >>= 24; 01267 event_end = ntohl(*((unsigned int *)(data))); 01268 event_end <<= 8; 01269 event_end >>= 24; 01270 duration = ntohl(*((unsigned int *)(data))); 01271 duration &= 0xFFFF; 01272 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); 01273 } 01274 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01275 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01276 /* It's really special -- process it the Cisco way */ 01277 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01278 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01279 rtp->lastevent = seqno; 01280 } 01281 } else if (rtpPT.code == AST_RTP_CN) { 01282 /* Comfort Noise */ 01283 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01284 } else { 01285 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01286 } 01287 return f ? f : &ast_null_frame; 01288 } 01289 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01290 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01291 01292 if (!rtp->lastrxts) 01293 rtp->lastrxts = timestamp; 01294 01295 rtp->rxseqno = seqno; 01296 01297 /* Record received timestamp as last received now */ 01298 rtp->lastrxts = timestamp; 01299 01300 rtp->f.mallocd = 0; 01301 rtp->f.datalen = res - hdrlen; 01302 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01303 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01304 rtp->f.seqno = seqno; 01305 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01306 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01307 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01308 ast_frame_byteswap_be(&rtp->f); 01309 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01310 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01311 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01312 rtp->f.ts = timestamp / 8; 01313 rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000); 01314 } else { 01315 /* Video -- samples is # of samples vs. 90000 */ 01316 if (!rtp->lastividtimestamp) 01317 rtp->lastividtimestamp = timestamp; 01318 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01319 rtp->lastividtimestamp = timestamp; 01320 rtp->f.delivery.tv_sec = 0; 01321 rtp->f.delivery.tv_usec = 0; 01322 if (mark) 01323 rtp->f.subclass |= 0x1; 01324 01325 } 01326 rtp->f.src = "RTP"; 01327 return &rtp->f; 01328 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3751 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().
03752 { 03753 struct ast_config *cfg; 03754 const char *s; 03755 03756 rtpstart = 5000; 03757 rtpend = 31000; 03758 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03759 cfg = ast_config_load("rtp.conf"); 03760 if (cfg) { 03761 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03762 rtpstart = atoi(s); 03763 if (rtpstart < 1024) 03764 rtpstart = 1024; 03765 if (rtpstart > 65535) 03766 rtpstart = 65535; 03767 } 03768 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03769 rtpend = atoi(s); 03770 if (rtpend < 1024) 03771 rtpend = 1024; 03772 if (rtpend > 65535) 03773 rtpend = 65535; 03774 } 03775 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03776 rtcpinterval = atoi(s); 03777 if (rtcpinterval == 0) 03778 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03779 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03780 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03781 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03782 rtcpinterval = RTCP_MAX_INTERVALMS; 03783 } 03784 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03785 #ifdef SO_NO_CHECK 03786 if (ast_false(s)) 03787 nochecksums = 1; 03788 else 03789 nochecksums = 0; 03790 #else 03791 if (ast_false(s)) 03792 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03793 #endif 03794 } 03795 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03796 dtmftimeout = atoi(s); 03797 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03798 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03799 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03800 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03801 }; 03802 } 03803 ast_config_destroy(cfg); 03804 } 03805 if (rtpstart >= rtpend) { 03806 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03807 rtpstart = 5000; 03808 rtpend = 31000; 03809 } 03810 if (option_verbose > 1) 03811 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03812 return 0; 03813 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2059 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.
02060 { 02061 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02062 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02063 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02064 rtp->lastts = 0; 02065 rtp->lastdigitts = 0; 02066 rtp->lastrxts = 0; 02067 rtp->lastividtimestamp = 0; 02068 rtp->lastovidtimestamp = 0; 02069 rtp->lasteventseqn = 0; 02070 rtp->lastevent = 0; 02071 rtp->lasttxformat = 0; 02072 rtp->lastrxformat = 0; 02073 rtp->dtmfcount = 0; 02074 rtp->dtmfsamples = 0; 02075 rtp->seqno = 0; 02076 rtp->rxseqno = 0; 02077 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2574 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().
02575 { 02576 unsigned int *rtpheader; 02577 int hdrlen = 12; 02578 int res; 02579 int payload; 02580 char data[256]; 02581 level = 127 - (level & 0x7f); 02582 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02583 02584 /* If we have no peer, return immediately */ 02585 if (!rtp->them.sin_addr.s_addr) 02586 return 0; 02587 02588 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02589 02590 /* Get a pointer to the header */ 02591 rtpheader = (unsigned int *)data; 02592 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02593 rtpheader[1] = htonl(rtp->lastts); 02594 rtpheader[2] = htonl(rtp->ssrc); 02595 data[12] = level; 02596 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02597 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02598 if (res <0) 02599 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)); 02600 if (rtp_debug_test_addr(&rtp->them)) 02601 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02602 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02603 02604 } 02605 return 0; 02606 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2182 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().
02183 { 02184 unsigned int *rtpheader; 02185 int hdrlen = 12, res = 0, i = 0, payload = 0; 02186 char data[256]; 02187 02188 if ((digit <= '9') && (digit >= '0')) 02189 digit -= '0'; 02190 else if (digit == '*') 02191 digit = 10; 02192 else if (digit == '#') 02193 digit = 11; 02194 else if ((digit >= 'A') && (digit <= 'D')) 02195 digit = digit - 'A' + 12; 02196 else if ((digit >= 'a') && (digit <= 'd')) 02197 digit = digit - 'a' + 12; 02198 else { 02199 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02200 return 0; 02201 } 02202 02203 /* If we have no peer, return immediately */ 02204 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02205 return 0; 02206 02207 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02208 02209 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02210 rtp->send_duration = 160; 02211 02212 /* Get a pointer to the header */ 02213 rtpheader = (unsigned int *)data; 02214 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02215 rtpheader[1] = htonl(rtp->lastdigitts); 02216 rtpheader[2] = htonl(rtp->ssrc); 02217 02218 for (i = 0; i < 2; i++) { 02219 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02220 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02221 if (res < 0) 02222 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02223 ast_inet_ntoa(rtp->them.sin_addr), 02224 ntohs(rtp->them.sin_port), strerror(errno)); 02225 if (rtp_debug_test_addr(&rtp->them)) 02226 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02227 ast_inet_ntoa(rtp->them.sin_addr), 02228 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02229 /* Increment sequence number */ 02230 rtp->seqno++; 02231 /* Increment duration */ 02232 rtp->send_duration += 160; 02233 /* Clear marker bit and set seqno */ 02234 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02235 } 02236 02237 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02238 rtp->sending_digit = 1; 02239 rtp->send_digit = digit; 02240 rtp->send_payload = payload; 02241 02242 return 0; 02243 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2246 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().
02247 { 02248 unsigned int *rtpheader; 02249 int hdrlen = 12, res = 0; 02250 char data[256]; 02251 02252 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02253 return 0; 02254 02255 /* Setup packet to send */ 02256 rtpheader = (unsigned int *)data; 02257 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02258 rtpheader[1] = htonl(rtp->lastdigitts); 02259 rtpheader[2] = htonl(rtp->ssrc); 02260 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02261 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02262 02263 /* Transmit */ 02264 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02265 if (res < 0) 02266 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02267 ast_inet_ntoa(rtp->them.sin_addr), 02268 ntohs(rtp->them.sin_port), strerror(errno)); 02269 if (rtp_debug_test_addr(&rtp->them)) 02270 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02271 ast_inet_ntoa(rtp->them.sin_addr), 02272 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02273 02274 /* Increment sequence number */ 02275 rtp->seqno++; 02276 /* Increment duration */ 02277 rtp->send_duration += 160; 02278 02279 return 0; 02280 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2283 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().
02284 { 02285 unsigned int *rtpheader; 02286 int hdrlen = 12, res = 0, i = 0; 02287 char data[256]; 02288 02289 /* If no address, then bail out */ 02290 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02291 return 0; 02292 02293 if ((digit <= '9') && (digit >= '0')) 02294 digit -= '0'; 02295 else if (digit == '*') 02296 digit = 10; 02297 else if (digit == '#') 02298 digit = 11; 02299 else if ((digit >= 'A') && (digit <= 'D')) 02300 digit = digit - 'A' + 12; 02301 else if ((digit >= 'a') && (digit <= 'd')) 02302 digit = digit - 'a' + 12; 02303 else { 02304 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02305 return 0; 02306 } 02307 02308 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02309 02310 rtpheader = (unsigned int *)data; 02311 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02312 rtpheader[1] = htonl(rtp->lastdigitts); 02313 rtpheader[2] = htonl(rtp->ssrc); 02314 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02315 /* Set end bit */ 02316 rtpheader[3] |= htonl((1 << 23)); 02317 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02318 /* Send 3 termination packets */ 02319 for (i = 0; i < 3; i++) { 02320 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02321 if (res < 0) 02322 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02323 ast_inet_ntoa(rtp->them.sin_addr), 02324 ntohs(rtp->them.sin_port), strerror(errno)); 02325 if (rtp_debug_test_addr(&rtp->them)) 02326 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02327 ast_inet_ntoa(rtp->them.sin_addr), 02328 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02329 } 02330 rtp->sending_digit = 0; 02331 rtp->send_digit = 0; 02332 /* Increment lastdigitts */ 02333 rtp->lastdigitts += 960; 02334 rtp->seqno++; 02335 02336 return res; 02337 }
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 1638 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().
01639 { 01640 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01641 return; /* bogus payload type */ 01642 01643 ast_mutex_lock(&rtp->bridge_lock); 01644 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01645 ast_mutex_unlock(&rtp->bridge_lock); 01646 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2005 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().
02006 { 02007 rtp->them.sin_port = them->sin_port; 02008 rtp->them.sin_addr = them->sin_addr; 02009 if (rtp->rtcp) { 02010 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02011 rtp->rtcp->them.sin_addr = them->sin_addr; 02012 } 02013 rtp->rxseqno = 0; 02014 }
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 1665 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().
01668 { 01669 unsigned int i; 01670 int found = 0; 01671 01672 if (pt < 0 || pt > MAX_RTP_PT) 01673 return -1; /* bogus payload type */ 01674 01675 ast_mutex_lock(&rtp->bridge_lock); 01676 01677 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01678 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01679 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01680 found = 1; 01681 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01682 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01683 mimeTypes[i].payloadType.isAstFormat && 01684 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01685 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01686 break; 01687 } 01688 } 01689 01690 ast_mutex_unlock(&rtp->bridge_lock); 01691 01692 return (found ? 0 : -1); 01693 }
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 1990 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
01991 { 01992 int res; 01993 01994 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 01995 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 01996 return res; 01997 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2045 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().
02046 { 02047 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02048 02049 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02050 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02051 if (rtp->rtcp) { 02052 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02053 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02054 } 02055 02056 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02057 }
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 1650 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().
01651 { 01652 if (pt < 0 || pt > MAX_RTP_PT) 01653 return; /* bogus payload type */ 01654 01655 ast_mutex_lock(&rtp->bridge_lock); 01656 rtp->current_RTP_PT[pt].isAstFormat = 0; 01657 rtp->current_RTP_PT[pt].code = 0; 01658 ast_mutex_unlock(&rtp->bridge_lock); 01659 }
Definition at line 2733 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().
02734 { 02735 struct ast_frame *f; 02736 int codec; 02737 int hdrlen = 12; 02738 int subclass; 02739 02740 02741 /* If we have no peer, return immediately */ 02742 if (!rtp->them.sin_addr.s_addr) 02743 return 0; 02744 02745 /* If there is no data length, return immediately */ 02746 if (!_f->datalen) 02747 return 0; 02748 02749 /* Make sure we have enough space for RTP header */ 02750 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02751 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02752 return -1; 02753 } 02754 02755 subclass = _f->subclass; 02756 if (_f->frametype == AST_FRAME_VIDEO) 02757 subclass &= ~0x1; 02758 02759 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02760 if (codec < 0) { 02761 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02762 return -1; 02763 } 02764 02765 if (rtp->lasttxformat != subclass) { 02766 /* New format, reset the smoother */ 02767 if (option_debug) 02768 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02769 rtp->lasttxformat = subclass; 02770 if (rtp->smoother) 02771 ast_smoother_free(rtp->smoother); 02772 rtp->smoother = NULL; 02773 } 02774 02775 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 02776 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02777 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02778 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02779 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)); 02780 return -1; 02781 } 02782 if (fmt.flags) 02783 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02784 if (option_debug) 02785 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)); 02786 } 02787 } 02788 if (rtp->smoother) { 02789 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02790 ast_smoother_feed_be(rtp->smoother, _f); 02791 } else { 02792 ast_smoother_feed(rtp->smoother, _f); 02793 } 02794 02795 while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { 02796 if (f->subclass == AST_FORMAT_G722) { 02797 /* G.722 is silllllllllllllly */ 02798 f->samples /= 2; 02799 } 02800 02801 ast_rtp_raw_write(rtp, f, codec); 02802 } 02803 } else { 02804 /* Don't buffer outgoing frames; send them one-per-packet: */ 02805 if (_f->offset < hdrlen) { 02806 f = ast_frdup(_f); 02807 } else { 02808 f = _f; 02809 } 02810 if (f->data) { 02811 if (f->subclass == AST_FORMAT_G722) { 02812 /* G.722 is silllllllllllllly */ 02813 f->samples /= 2; 02814 } 02815 ast_rtp_raw_write(rtp, f, codec); 02816 } 02817 if (f != _f) 02818 ast_frfree(f); 02819 } 02820 02821 return 0; 02822 }
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 2852 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().
02853 { 02854 struct ast_frame *fr = NULL; 02855 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02856 int oldcodec0 = codec0, oldcodec1 = codec1; 02857 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02858 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02859 02860 /* Set it up so audio goes directly between the two endpoints */ 02861 02862 /* Test the first channel */ 02863 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02864 ast_rtp_get_peer(p1, &ac1); 02865 if (vp1) 02866 ast_rtp_get_peer(vp1, &vac1); 02867 } else 02868 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 02869 02870 /* Test the second channel */ 02871 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 02872 ast_rtp_get_peer(p0, &ac0); 02873 if (vp0) 02874 ast_rtp_get_peer(vp0, &vac0); 02875 } else 02876 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 02877 02878 /* Now we can unlock and move into our loop */ 02879 ast_channel_unlock(c0); 02880 ast_channel_unlock(c1); 02881 02882 /* Throw our channels into the structure and enter the loop */ 02883 cs[0] = c0; 02884 cs[1] = c1; 02885 cs[2] = NULL; 02886 for (;;) { 02887 /* Check if anything changed */ 02888 if ((c0->tech_pvt != pvt0) || 02889 (c1->tech_pvt != pvt1) || 02890 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 02891 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 02892 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 02893 if (c0->tech_pvt == pvt0) 02894 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02895 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02896 if (c1->tech_pvt == pvt1) 02897 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02898 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02899 return AST_BRIDGE_RETRY; 02900 } 02901 02902 /* Check if they have changed their address */ 02903 ast_rtp_get_peer(p1, &t1); 02904 if (vp1) 02905 ast_rtp_get_peer(vp1, &vt1); 02906 if (pr1->get_codec) 02907 codec1 = pr1->get_codec(c1); 02908 ast_rtp_get_peer(p0, &t0); 02909 if (vp0) 02910 ast_rtp_get_peer(vp0, &vt0); 02911 if (pr0->get_codec) 02912 codec0 = pr0->get_codec(c0); 02913 if ((inaddrcmp(&t1, &ac1)) || 02914 (vp1 && inaddrcmp(&vt1, &vac1)) || 02915 (codec1 != oldcodec1)) { 02916 if (option_debug > 1) { 02917 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02918 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 02919 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 02920 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 02921 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02922 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 02923 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02924 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 02925 } 02926 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))) 02927 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 02928 memcpy(&ac1, &t1, sizeof(ac1)); 02929 memcpy(&vac1, &vt1, sizeof(vac1)); 02930 oldcodec1 = codec1; 02931 } 02932 if ((inaddrcmp(&t0, &ac0)) || 02933 (vp0 && inaddrcmp(&vt0, &vac0))) { 02934 if (option_debug > 1) { 02935 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02936 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 02937 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02938 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 02939 } 02940 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))) 02941 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 02942 memcpy(&ac0, &t0, sizeof(ac0)); 02943 memcpy(&vac0, &vt0, sizeof(vac0)); 02944 oldcodec0 = codec0; 02945 } 02946 02947 /* Wait for frame to come in on the channels */ 02948 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 02949 if (!timeoutms) { 02950 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02951 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02952 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02953 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02954 return AST_BRIDGE_RETRY; 02955 } 02956 if (option_debug) 02957 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 02958 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 02959 break; 02960 continue; 02961 } 02962 fr = ast_read(who); 02963 other = (who == c0) ? c1 : c0; 02964 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 02965 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 02966 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 02967 /* Break out of bridge */ 02968 *fo = fr; 02969 *rc = who; 02970 if (option_debug) 02971 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 02972 if (c0->tech_pvt == pvt0) 02973 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02974 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02975 if (c1->tech_pvt == pvt1) 02976 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02977 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02978 return AST_BRIDGE_COMPLETE; 02979 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02980 if ((fr->subclass == AST_CONTROL_HOLD) || 02981 (fr->subclass == AST_CONTROL_UNHOLD) || 02982 (fr->subclass == AST_CONTROL_VIDUPDATE) || 02983 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 02984 if (fr->subclass == AST_CONTROL_HOLD) { 02985 /* If we someone went on hold we want the other side to reinvite back to us */ 02986 if (who == c0) 02987 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 02988 else 02989 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 02990 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 02991 /* If they went off hold they should go back to being direct */ 02992 if (who == c0) 02993 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 02994 else 02995 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 02996 } 02997 /* Update local address information */ 02998 ast_rtp_get_peer(p0, &t0); 02999 memcpy(&ac0, &t0, sizeof(ac0)); 03000 ast_rtp_get_peer(p1, &t1); 03001 memcpy(&ac1, &t1, sizeof(ac1)); 03002 /* Update codec information */ 03003 if (pr0->get_codec && c0->tech_pvt) 03004 oldcodec0 = codec0 = pr0->get_codec(c0); 03005 if (pr1->get_codec && c1->tech_pvt) 03006 oldcodec1 = codec1 = pr1->get_codec(c1); 03007 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03008 ast_frfree(fr); 03009 } else { 03010 *fo = fr; 03011 *rc = who; 03012 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03013 return AST_BRIDGE_COMPLETE; 03014 } 03015 } else { 03016 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03017 (fr->frametype == AST_FRAME_DTMF_END) || 03018 (fr->frametype == AST_FRAME_VOICE) || 03019 (fr->frametype == AST_FRAME_VIDEO) || 03020 (fr->frametype == AST_FRAME_IMAGE) || 03021 (fr->frametype == AST_FRAME_HTML) || 03022 (fr->frametype == AST_FRAME_MODEM) || 03023 (fr->frametype == AST_FRAME_TEXT)) { 03024 ast_write(other, fr); 03025 } 03026 ast_frfree(fr); 03027 } 03028 /* Swap priority */ 03029 cs[2] = cs[0]; 03030 cs[0] = cs[1]; 03031 cs[1] = cs[2]; 03032 } 03033 03034 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 03035 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 03036 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 03037 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 03038 03039 return AST_BRIDGE_FAILED; 03040 }
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 3138 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().
03139 { 03140 struct ast_frame *fr = NULL; 03141 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03142 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03143 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03144 int p0_callback = 0, p1_callback = 0; 03145 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03146 03147 /* Okay, setup each RTP structure to do P2P forwarding */ 03148 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03149 p2p_set_bridge(p0, p1); 03150 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03151 p2p_set_bridge(p1, p0); 03152 03153 /* Activate callback modes if possible */ 03154 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03155 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03156 03157 /* Now let go of the channel locks and be on our way */ 03158 ast_channel_unlock(c0); 03159 ast_channel_unlock(c1); 03160 03161 /* Go into a loop forwarding frames until we don't need to anymore */ 03162 cs[0] = c0; 03163 cs[1] = c1; 03164 cs[2] = NULL; 03165 for (;;) { 03166 /* If the underlying formats have changed force this bridge to break */ 03167 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { 03168 ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n"); 03169 res = AST_BRIDGE_FAILED_NOWARN; 03170 break; 03171 } 03172 /* Check if anything changed */ 03173 if ((c0->tech_pvt != pvt0) || 03174 (c1->tech_pvt != pvt1) || 03175 (c0->masq || c0->masqr || c1->masq || c1->masqr) || 03176 (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) { 03177 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03178 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03179 ast_frfree(fr); 03180 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03181 ast_frfree(fr); 03182 res = AST_BRIDGE_RETRY; 03183 break; 03184 } 03185 /* Wait on a channel to feed us a frame */ 03186 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03187 if (!timeoutms) { 03188 res = AST_BRIDGE_RETRY; 03189 break; 03190 } 03191 if (option_debug) 03192 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03193 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03194 break; 03195 continue; 03196 } 03197 /* Read in frame from channel */ 03198 fr = ast_read(who); 03199 other = (who == c0) ? c1 : c0; 03200 /* Dependong on the frame we may need to break out of our bridge */ 03201 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && 03202 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03203 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03204 /* Record received frame and who */ 03205 *fo = fr; 03206 *rc = who; 03207 if (option_debug) 03208 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03209 res = AST_BRIDGE_COMPLETE; 03210 break; 03211 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03212 if ((fr->subclass == AST_CONTROL_HOLD) || 03213 (fr->subclass == AST_CONTROL_UNHOLD) || 03214 (fr->subclass == AST_CONTROL_VIDUPDATE) || 03215 (fr->subclass == AST_CONTROL_SRCUPDATE)) { 03216 /* If we are going on hold, then break callback mode and P2P bridging */ 03217 if (fr->subclass == AST_CONTROL_HOLD) { 03218 if (p0_callback) 03219 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03220 if (p1_callback) 03221 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03222 p2p_set_bridge(p0, NULL); 03223 p2p_set_bridge(p1, NULL); 03224 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03225 /* If we are off hold, then go back to callback mode and P2P bridging */ 03226 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03227 p2p_set_bridge(p0, p1); 03228 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03229 p2p_set_bridge(p1, p0); 03230 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03231 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03232 } 03233 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03234 ast_frfree(fr); 03235 } else { 03236 *fo = fr; 03237 *rc = who; 03238 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03239 res = AST_BRIDGE_COMPLETE; 03240 break; 03241 } 03242 } else { 03243 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03244 (fr->frametype == AST_FRAME_DTMF_END) || 03245 (fr->frametype == AST_FRAME_VOICE) || 03246 (fr->frametype == AST_FRAME_VIDEO) || 03247 (fr->frametype == AST_FRAME_IMAGE) || 03248 (fr->frametype == AST_FRAME_HTML) || 03249 (fr->frametype == AST_FRAME_MODEM) || 03250 (fr->frametype == AST_FRAME_TEXT)) { 03251 ast_write(other, fr); 03252 } 03253 03254 ast_frfree(fr); 03255 } 03256 /* Swap priority */ 03257 cs[2] = cs[0]; 03258 cs[0] = cs[1]; 03259 cs[1] = cs[2]; 03260 } 03261 03262 /* If we are totally avoiding the core, then restore our link to it */ 03263 if (p0_callback) 03264 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03265 if (p1_callback) 03266 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03267 03268 /* Break out of the direct bridge */ 03269 p2p_set_bridge(p0, NULL); 03270 p2p_set_bridge(p1, NULL); 03271 03272 return res; 03273 }
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 1051 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().
01052 { 01053 int res = 0, payload = 0, bridged_payload = 0, mark; 01054 struct rtpPayloadType rtpPT; 01055 int reconstruct = ntohl(rtpheader[0]); 01056 01057 /* Get fields from packet */ 01058 payload = (reconstruct & 0x7f0000) >> 16; 01059 mark = (((reconstruct & 0x800000) >> 23) != 0); 01060 01061 /* Check what the payload value should be */ 01062 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01063 01064 /* 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 */ 01065 if (!bridged->current_RTP_PT[payload].code) 01066 return -1; 01067 01068 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01069 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01070 return -1; 01071 01072 /* Otherwise adjust bridged payload to match */ 01073 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01074 01075 /* If the mark bit has not been sent yet... do it now */ 01076 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01077 mark = 1; 01078 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01079 } 01080 01081 /* Reconstruct part of the packet */ 01082 reconstruct &= 0xFF80FFFF; 01083 reconstruct |= (bridged_payload << 16); 01084 reconstruct |= (mark << 23); 01085 rtpheader[0] = htonl(reconstruct); 01086 01087 /* Send the packet back out */ 01088 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01089 if (res < 0) { 01090 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01091 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)); 01092 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01093 if (option_debug || rtpdebug) 01094 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)); 01095 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01096 } 01097 return 0; 01098 } else if (rtp_debug_test_addr(&bridged->them)) 01099 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); 01100 01101 return 0; 01102 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1002 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().
01003 { 01004 struct timeval now; 01005 double transit; 01006 double current_time; 01007 double d; 01008 double dtv; 01009 double prog; 01010 01011 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01012 gettimeofday(&rtp->rxcore, NULL); 01013 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01014 /* map timestamp to a real time */ 01015 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01016 rtp->rxcore.tv_sec -= timestamp / 8000; 01017 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01018 /* Round to 0.1ms for nice, pretty timestamps */ 01019 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01020 if (rtp->rxcore.tv_usec < 0) { 01021 /* Adjust appropriately if necessary */ 01022 rtp->rxcore.tv_usec += 1000000; 01023 rtp->rxcore.tv_sec -= 1; 01024 } 01025 } 01026 01027 gettimeofday(&now,NULL); 01028 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01029 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01030 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01031 if (tv->tv_usec >= 1000000) { 01032 tv->tv_usec -= 1000000; 01033 tv->tv_sec += 1; 01034 } 01035 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01036 dtv = (double)rtp->drxcore + (double)(prog); 01037 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01038 transit = current_time - dtv; 01039 d = transit - rtp->rxtransit; 01040 rtp->rxtransit = transit; 01041 if (d<0) 01042 d=-d; 01043 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01044 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01045 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01046 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01047 rtp->rtcp->minrxjitter = rtp->rxjitter; 01048 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2162 of file rtp.c.
References ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02163 { 02164 struct timeval t; 02165 long ms; 02166 if (ast_tvzero(rtp->txcore)) { 02167 rtp->txcore = ast_tvnow(); 02168 /* Round to 20ms for nice, pretty timestamps */ 02169 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02170 } 02171 /* Use previous txcore if available */ 02172 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02173 ms = ast_tvdiff_ms(t, rtp->txcore); 02174 if (ms < 0) 02175 ms = 0; 02176 /* Use what we just got for next time */ 02177 rtp->txcore = t; 02178 return (unsigned int) ms; 02179 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static, read] |
Get channel driver interface structure.
Definition at line 1461 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().
01462 { 01463 struct ast_rtp_protocol *cur = NULL; 01464 01465 AST_LIST_LOCK(&protos); 01466 AST_LIST_TRAVERSE(&protos, cur, list) { 01467 if (cur->type == chan->tech->type) 01468 break; 01469 } 01470 AST_LIST_UNLOCK(&protos); 01471 01472 return cur; 01473 }
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 3109 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().
03110 { 03111 ast_channel_lock(chan); 03112 03113 /* Remove the callback from the IO context */ 03114 ast_io_remove(rtp->io, iod[0]); 03115 03116 /* Restore file descriptors */ 03117 chan->fds[0] = fds[0]; 03118 ast_channel_unlock(chan); 03119 03120 /* Restore callback mode if previously used */ 03121 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03122 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03123 03124 return 0; 03125 }
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 3128 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03129 { 03130 ast_mutex_lock(&rtp0->bridge_lock); 03131 rtp0->bridged = rtp1; 03132 ast_mutex_unlock(&rtp0->bridge_lock); 03133 03134 return; 03135 }
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.samples = 0; 00809 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00810 f = &rtp->f; 00811 return f; 00812 }
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 3548 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtcp_do_debug_ip(), and rtcpdebugaddr.
03548 { 03549 if (argc != 2) { 03550 if (argc != 4) 03551 return RESULT_SHOWUSAGE; 03552 return rtcp_do_debug_ip(fd, argc, argv); 03553 } 03554 rtcpdebug = 1; 03555 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03556 ast_cli(fd, "RTCP Debugging Enabled\n"); 03557 return RESULT_SUCCESS; 03558 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3536 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtcp_do_debug_ip_deprecated(), and rtcpdebugaddr.
03536 { 03537 if (argc != 3) { 03538 if (argc != 5) 03539 return RESULT_SHOWUSAGE; 03540 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03541 } 03542 rtcpdebug = 1; 03543 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03544 ast_cli(fd, "RTCP Debugging Enabled\n"); 03545 return RESULT_SUCCESS; 03546 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3493 of file rtp.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcpdebugaddr.
Referenced by rtcp_do_debug().
03494 { 03495 struct hostent *hp; 03496 struct ast_hostent ahp; 03497 int port = 0; 03498 char *p, *arg; 03499 if (argc != 4) 03500 return RESULT_SHOWUSAGE; 03501 03502 arg = argv[3]; 03503 p = strstr(arg, ":"); 03504 if (p) { 03505 *p = '\0'; 03506 p++; 03507 port = atoi(p); 03508 } 03509 hp = ast_gethostbyname(arg, &ahp); 03510 if (hp == NULL) 03511 return RESULT_SHOWUSAGE; 03512 rtcpdebugaddr.sin_family = AF_INET; 03513 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03514 rtcpdebugaddr.sin_port = htons(port); 03515 if (port == 0) 03516 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03517 else 03518 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03519 rtcpdebug = 1; 03520 return RESULT_SUCCESS; 03521 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3463 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().
03464 { 03465 struct hostent *hp; 03466 struct ast_hostent ahp; 03467 int port = 0; 03468 char *p, *arg; 03469 if (argc != 5) 03470 return RESULT_SHOWUSAGE; 03471 03472 arg = argv[4]; 03473 p = strstr(arg, ":"); 03474 if (p) { 03475 *p = '\0'; 03476 p++; 03477 port = atoi(p); 03478 } 03479 hp = ast_gethostbyname(arg, &ahp); 03480 if (hp == NULL) 03481 return RESULT_SHOWUSAGE; 03482 rtcpdebugaddr.sin_family = AF_INET; 03483 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03484 rtcpdebugaddr.sin_port = htons(port); 03485 if (port == 0) 03486 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03487 else 03488 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03489 rtcpdebug = 1; 03490 return RESULT_SUCCESS; 03491 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3569 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03569 { 03570 if (argc != 2) { 03571 return RESULT_SHOWUSAGE; 03572 } 03573 rtcpstats = 1; 03574 ast_cli(fd, "RTCP Stats Enabled\n"); 03575 return RESULT_SUCCESS; 03576 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3560 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03560 { 03561 if (argc != 3) { 03562 return RESULT_SHOWUSAGE; 03563 } 03564 rtcpstats = 1; 03565 ast_cli(fd, "RTCP Stats Enabled\n"); 03566 return RESULT_SUCCESS; 03567 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3596 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03597 { 03598 if (argc != 3) 03599 return RESULT_SHOWUSAGE; 03600 rtcpdebug = 0; 03601 ast_cli(fd,"RTCP Debugging Disabled\n"); 03602 return RESULT_SUCCESS; 03603 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3587 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03588 { 03589 if (argc != 4) 03590 return RESULT_SHOWUSAGE; 03591 rtcpdebug = 0; 03592 ast_cli(fd,"RTCP Debugging Disabled\n"); 03593 return RESULT_SUCCESS; 03594 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3614 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03615 { 03616 if (argc != 3) 03617 return RESULT_SHOWUSAGE; 03618 rtcpstats = 0; 03619 ast_cli(fd,"RTCP Stats Disabled\n"); 03620 return RESULT_SUCCESS; 03621 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3605 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03606 { 03607 if (argc != 4) 03608 return RESULT_SHOWUSAGE; 03609 rtcpstats = 0; 03610 ast_cli(fd,"RTCP Stats Disabled\n"); 03611 return RESULT_SUCCESS; 03612 }
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 3523 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtp_do_debug_ip(), and rtpdebugaddr.
03524 { 03525 if (argc != 2) { 03526 if (argc != 4) 03527 return RESULT_SHOWUSAGE; 03528 return rtp_do_debug_ip(fd, argc, argv); 03529 } 03530 rtpdebug = 1; 03531 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03532 ast_cli(fd, "RTP Debugging Enabled\n"); 03533 return RESULT_SUCCESS; 03534 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3433 of file rtp.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtpdebugaddr.
Referenced by rtp_do_debug().
03434 { 03435 struct hostent *hp; 03436 struct ast_hostent ahp; 03437 int port = 0; 03438 char *p, *arg; 03439 03440 if (argc != 4) 03441 return RESULT_SHOWUSAGE; 03442 arg = argv[3]; 03443 p = strstr(arg, ":"); 03444 if (p) { 03445 *p = '\0'; 03446 p++; 03447 port = atoi(p); 03448 } 03449 hp = ast_gethostbyname(arg, &ahp); 03450 if (hp == NULL) 03451 return RESULT_SHOWUSAGE; 03452 rtpdebugaddr.sin_family = AF_INET; 03453 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03454 rtpdebugaddr.sin_port = htons(port); 03455 if (port == 0) 03456 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03457 else 03458 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03459 rtpdebug = 1; 03460 return RESULT_SUCCESS; 03461 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3578 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03579 { 03580 if (argc != 3) 03581 return RESULT_SHOWUSAGE; 03582 rtpdebug = 0; 03583 ast_cli(fd,"RTP Debugging Disabled\n"); 03584 return RESULT_SUCCESS; 03585 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1837 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01838 { 01839 int s; 01840 long flags; 01841 s = socket(AF_INET, SOCK_DGRAM, 0); 01842 if (s > -1) { 01843 flags = fcntl(s, F_GETFL); 01844 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01845 #ifdef SO_NO_CHECK 01846 if (nochecksums) 01847 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01848 #endif 01849 } 01850 return s; 01851 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 814 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().
00815 { 00816 struct ast_rtp *rtp = cbdata; 00817 struct ast_frame *f; 00818 f = ast_rtp_read(rtp); 00819 if (f) { 00820 if (rtp->callback) 00821 rtp->callback(rtp, f, rtp->data); 00822 } 00823 return 1; 00824 }
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 3623 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03624 { 03625 if (argc != 2) { 03626 return RESULT_SHOWUSAGE; 03627 } 03628 stundebug = 1; 03629 ast_cli(fd, "STUN Debugging Enabled\n"); 03630 return RESULT_SUCCESS; 03631 }
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 3633 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03634 { 03635 if (argc != 3) 03636 return RESULT_SHOWUSAGE; 03637 stundebug = 0; 03638 ast_cli(fd, "STUN Debugging Disabled\n"); 03639 return RESULT_SUCCESS; 03640 }
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 1333 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 1334 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().