#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 20 |
#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 (void *data) |
Write and RTCP packet to the far end. | |
static int | ast_rtcp_write_rr (void *data) |
Send RTCP recepient's report. | |
static int | ast_rtcp_write_sr (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. | |
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 | |
void | 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) |
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_addr | packed |
struct stun_attr | packed |
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 193 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr(), and p2p_callback_disable().
#define FLAG_DTMF_COMPENSATE (1 << 7) |
Definition at line 194 of file rtp.c.
Referenced by ast_rtp_bridge(), ast_rtp_setdtmfcompensate(), process_rfc2833(), and send_dtmf().
#define FLAG_HAS_DTMF (1 << 3) |
Definition at line 190 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 187 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 188 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 189 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 191 of file rtp.c.
Referenced by ast_rtp_stop(), bridge_p2p_loop(), and bridge_p2p_rtp_write().
#define MAX_TIMESTAMP_SKEW 20 |
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 261 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 273 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 366 of file rtp.c.
References stun_addr::addr, stun_addr::family, stun_addr::port, and stun_addr::unused.
Referenced by stun_handle_packet().
00367 { 00368 int size = sizeof(**attr) + 8; 00369 struct stun_addr *addr; 00370 if (*left > size) { 00371 (*attr)->attr = htons(attrval); 00372 (*attr)->len = htons(8); 00373 addr = (struct stun_addr *)((*attr)->value); 00374 addr->unused = 0; 00375 addr->family = 0x01; 00376 addr->port = sin->sin_port; 00377 addr->addr = sin->sin_addr.s_addr; 00378 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00379 *len += size; 00380 *left -= size; 00381 } 00382 }
static void append_attr_string | ( | struct stun_attr ** | attr, | |
int | attrval, | |||
const char * | s, | |||
int * | len, | |||
int * | left | |||
) | [static] |
Definition at line 353 of file rtp.c.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00354 { 00355 int size = sizeof(**attr) + strlen(s); 00356 if (*left > size) { 00357 (*attr)->attr = htons(attrval); 00358 (*attr)->len = htons(strlen(s)); 00359 memcpy((*attr)->value, s, strlen(s)); 00360 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00361 *len += size; 00362 *left -= size; 00363 } 00364 }
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 524 of file rtp.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00525 { 00526 unsigned int interval; 00527 /*! \todo XXX Do a more reasonable calculation on this one 00528 * Look in RFC 3550 Section A.7 for an example*/ 00529 interval = rtcpinterval; 00530 return interval; 00531 }
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 517 of file rtp.c.
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 1833 of file rtp.c.
References ast_calloc, ast_log(), free, LOG_WARNING, rtp_socket(), ast_rtcp::s, ast_rtcp::them, and ast_rtcp::us.
Referenced by ast_rtp_new_with_bindaddr().
01834 { 01835 struct ast_rtcp *rtcp; 01836 01837 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01838 return NULL; 01839 rtcp->s = rtp_socket(); 01840 rtcp->us.sin_family = AF_INET; 01841 rtcp->them.sin_family = AF_INET; 01842 01843 if (rtcp->s < 0) { 01844 free(rtcp); 01845 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01846 return NULL; 01847 } 01848 01849 return rtcp; 01850 }
Definition at line 822 of file rtp.c.
Referenced by oh323_read(), sip_rtp_read(), and skinny_rtp_read().
00823 { 00824 socklen_t len; 00825 int position, i, packetwords; 00826 int res; 00827 struct sockaddr_in sin; 00828 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00829 unsigned int *rtcpheader; 00830 int pt; 00831 struct timeval now; 00832 unsigned int length; 00833 int rc; 00834 double rttsec; 00835 uint64_t rtt = 0; 00836 unsigned int dlsr; 00837 unsigned int lsr; 00838 unsigned int msw; 00839 unsigned int lsw; 00840 unsigned int comp; 00841 struct ast_frame *f = &ast_null_frame; 00842 00843 if (!rtp || !rtp->rtcp) 00844 return &ast_null_frame; 00845 00846 len = sizeof(sin); 00847 00848 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00849 0, (struct sockaddr *)&sin, &len); 00850 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00851 00852 if (res < 0) { 00853 if (errno == EBADF) 00854 CRASH; 00855 if (errno != EAGAIN) { 00856 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00857 return NULL; 00858 } 00859 return &ast_null_frame; 00860 } 00861 00862 packetwords = res / 4; 00863 00864 if (rtp->nat) { 00865 /* Send to whoever sent to us */ 00866 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00867 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00868 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00869 if (option_debug || rtpdebug) 00870 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)); 00871 } 00872 } 00873 00874 if (option_debug) 00875 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00876 00877 /* Process a compound packet */ 00878 position = 0; 00879 while (position < packetwords) { 00880 i = position; 00881 length = ntohl(rtcpheader[i]); 00882 pt = (length & 0xff0000) >> 16; 00883 rc = (length & 0x1f000000) >> 24; 00884 length &= 0xffff; 00885 00886 if ((i + length) > packetwords) { 00887 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00888 return &ast_null_frame; 00889 } 00890 00891 if (rtcp_debug_test_addr(&sin)) { 00892 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00893 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00894 ast_verbose("Reception reports: %d\n", rc); 00895 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00896 } 00897 00898 i += 2; /* Advance past header and ssrc */ 00899 00900 switch (pt) { 00901 case RTCP_PT_SR: 00902 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00903 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00904 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00905 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00906 00907 if (rtcp_debug_test_addr(&sin)) { 00908 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00909 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00910 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00911 } 00912 i += 5; 00913 if (rc < 1) 00914 break; 00915 /* Intentional fall through */ 00916 case RTCP_PT_RR: 00917 /* Don't handle multiple reception reports (rc > 1) yet */ 00918 /* Calculate RTT per RFC */ 00919 gettimeofday(&now, NULL); 00920 timeval2ntp(now, &msw, &lsw); 00921 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00922 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00923 lsr = ntohl(rtcpheader[i + 4]); 00924 dlsr = ntohl(rtcpheader[i + 5]); 00925 rtt = comp - lsr - dlsr; 00926 00927 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00928 sess->ee_delay = (eedelay * 1000) / 65536; */ 00929 if (rtt < 4294) { 00930 rtt = (rtt * 1000000) >> 16; 00931 } else { 00932 rtt = (rtt * 1000) >> 16; 00933 rtt *= 1000; 00934 } 00935 rtt = rtt / 1000.; 00936 rttsec = rtt / 1000.; 00937 00938 if (comp - dlsr >= lsr) { 00939 rtp->rtcp->accumulated_transit += rttsec; 00940 rtp->rtcp->rtt = rttsec; 00941 if (rtp->rtcp->maxrtt<rttsec) 00942 rtp->rtcp->maxrtt = rttsec; 00943 if (rtp->rtcp->minrtt>rttsec) 00944 rtp->rtcp->minrtt = rttsec; 00945 } else if (rtcp_debug_test_addr(&sin)) { 00946 ast_verbose("Internal RTCP NTP clock skew detected: " 00947 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 00948 "diff=%d\n", 00949 lsr, comp, dlsr, dlsr / 65536, 00950 (dlsr % 65536) * 1000 / 65536, 00951 dlsr - (comp - lsr)); 00952 } 00953 } 00954 00955 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00956 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00957 if (rtcp_debug_test_addr(&sin)) { 00958 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00959 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00960 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00961 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00962 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00963 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00964 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00965 if (rtt) 00966 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 00967 } 00968 break; 00969 case RTCP_PT_FUR: 00970 if (rtcp_debug_test_addr(&sin)) 00971 ast_verbose("Received an RTCP Fast Update Request\n"); 00972 rtp->f.frametype = AST_FRAME_CONTROL; 00973 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00974 rtp->f.datalen = 0; 00975 rtp->f.samples = 0; 00976 rtp->f.mallocd = 0; 00977 rtp->f.src = "RTP"; 00978 f = &rtp->f; 00979 break; 00980 case RTCP_PT_SDES: 00981 if (rtcp_debug_test_addr(&sin)) 00982 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00983 break; 00984 case RTCP_PT_BYE: 00985 if (rtcp_debug_test_addr(&sin)) 00986 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00987 break; 00988 default: 00989 if (option_debug) 00990 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)); 00991 break; 00992 } 00993 position += (length + 1); 00994 } 00995 00996 return f; 00997 }
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 2298 of file rtp.c.
02299 { 02300 struct ast_rtp *rtp = data; 02301 int res; 02302 02303 rtp->rtcp->sendfur = 1; 02304 res = ast_rtcp_write(data); 02305 02306 return res; 02307 }
static int ast_rtcp_write | ( | void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 2523 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().
02524 { 02525 struct ast_rtp *rtp = data; 02526 int res; 02527 02528 if (!rtp || !rtp->rtcp) 02529 return 0; 02530 02531 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02532 res = ast_rtcp_write_sr(data); 02533 else 02534 res = ast_rtcp_write_rr(data); 02535 02536 return res; 02537 }
static int ast_rtcp_write_rr | ( | void * | data | ) | [static] |
Send RTCP recepient's report.
Definition at line 2424 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, 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().
02425 { 02426 struct ast_rtp *rtp = data; 02427 int res; 02428 int len = 32; 02429 unsigned int lost; 02430 unsigned int extended; 02431 unsigned int expected; 02432 unsigned int expected_interval; 02433 unsigned int received_interval; 02434 int lost_interval; 02435 struct timeval now; 02436 unsigned int *rtcpheader; 02437 char bdata[1024]; 02438 struct timeval dlsr; 02439 int fraction; 02440 02441 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02442 return 0; 02443 02444 if (!rtp->rtcp->them.sin_addr.s_addr) { 02445 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 02446 if (rtp->rtcp->schedid > 0) 02447 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02448 rtp->rtcp->schedid = -1; 02449 return 0; 02450 } 02451 02452 extended = rtp->cycles + rtp->lastrxseqno; 02453 expected = extended - rtp->seedrxseqno + 1; 02454 lost = expected - rtp->rxcount; 02455 expected_interval = expected - rtp->rtcp->expected_prior; 02456 rtp->rtcp->expected_prior = expected; 02457 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02458 rtp->rtcp->received_prior = rtp->rxcount; 02459 lost_interval = expected_interval - received_interval; 02460 if (expected_interval == 0 || lost_interval <= 0) 02461 fraction = 0; 02462 else 02463 fraction = (lost_interval << 8) / expected_interval; 02464 gettimeofday(&now, NULL); 02465 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02466 rtcpheader = (unsigned int *)bdata; 02467 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02468 rtcpheader[1] = htonl(rtp->ssrc); 02469 rtcpheader[2] = htonl(rtp->themssrc); 02470 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02471 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02472 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02473 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02474 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02475 02476 if (rtp->rtcp->sendfur) { 02477 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02478 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02479 len += 8; 02480 rtp->rtcp->sendfur = 0; 02481 } 02482 02483 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02484 it can change mid call, and SDES can't) */ 02485 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02486 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02487 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02488 len += 12; 02489 02490 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02491 02492 if (res < 0) { 02493 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02494 /* Remove the scheduler */ 02495 if (rtp->rtcp->schedid > 0) 02496 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02497 rtp->rtcp->schedid = -1; 02498 return 0; 02499 } 02500 02501 rtp->rtcp->rr_count++; 02502 02503 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02504 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02505 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02506 " IA jitter: %.4f\n" 02507 " Their last SR: %u\n" 02508 " DLSR: %4.4f (sec)\n\n", 02509 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02510 ntohs(rtp->rtcp->them.sin_port), 02511 rtp->ssrc, rtp->themssrc, fraction, lost, 02512 rtp->rxjitter, 02513 rtp->rtcp->themrxlsr, 02514 (double)(ntohl(rtcpheader[7])/65536.0)); 02515 } 02516 02517 return res; 02518 }
static int ast_rtcp_write_sr | ( | void * | data | ) | [static] |
Send RTCP sender's report.
Definition at line 2310 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, 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().
02311 { 02312 struct ast_rtp *rtp = data; 02313 int res; 02314 int len = 0; 02315 struct timeval now; 02316 unsigned int now_lsw; 02317 unsigned int now_msw; 02318 unsigned int *rtcpheader; 02319 unsigned int lost; 02320 unsigned int extended; 02321 unsigned int expected; 02322 unsigned int expected_interval; 02323 unsigned int received_interval; 02324 int lost_interval; 02325 int fraction; 02326 struct timeval dlsr; 02327 char bdata[512]; 02328 02329 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02330 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02331 return 0; 02332 02333 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02334 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02335 if (rtp->rtcp->schedid > 0) 02336 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02337 rtp->rtcp->schedid = -1; 02338 return 0; 02339 } 02340 02341 gettimeofday(&now, NULL); 02342 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02343 rtcpheader = (unsigned int *)bdata; 02344 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02345 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02346 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02347 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02348 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02349 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02350 len += 28; 02351 02352 extended = rtp->cycles + rtp->lastrxseqno; 02353 expected = extended - rtp->seedrxseqno + 1; 02354 if (rtp->rxcount > expected) 02355 expected += rtp->rxcount - expected; 02356 lost = expected - rtp->rxcount; 02357 expected_interval = expected - rtp->rtcp->expected_prior; 02358 rtp->rtcp->expected_prior = expected; 02359 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02360 rtp->rtcp->received_prior = rtp->rxcount; 02361 lost_interval = expected_interval - received_interval; 02362 if (expected_interval == 0 || lost_interval <= 0) 02363 fraction = 0; 02364 else 02365 fraction = (lost_interval << 8) / expected_interval; 02366 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02367 rtcpheader[7] = htonl(rtp->themssrc); 02368 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02369 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02370 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 02371 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02372 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02373 len += 24; 02374 02375 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02376 02377 if (rtp->rtcp->sendfur) { 02378 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02379 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02380 len += 8; 02381 rtp->rtcp->sendfur = 0; 02382 } 02383 02384 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02385 /* it can change mid call, and SDES can't) */ 02386 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02387 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02388 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02389 len += 12; 02390 02391 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02392 if (res < 0) { 02393 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)); 02394 if (rtp->rtcp->schedid > 0) 02395 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02396 rtp->rtcp->schedid = -1; 02397 return 0; 02398 } 02399 02400 /* FIXME Don't need to get a new one */ 02401 gettimeofday(&rtp->rtcp->txlsr, NULL); 02402 rtp->rtcp->sr_count++; 02403 02404 rtp->rtcp->lastsrtxcount = rtp->txcount; 02405 02406 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02407 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02408 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02409 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02410 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02411 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02412 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02413 ast_verbose(" Report block:\n"); 02414 ast_verbose(" Fraction lost: %u\n", fraction); 02415 ast_verbose(" Cumulative loss: %u\n", lost); 02416 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02417 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02418 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02419 } 02420 return res; 02421 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 397 of file rtp.c.
Referenced by process_sdp().
00398 { 00399 return sizeof(struct ast_rtp); 00400 }
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 3206 of file rtp.c.
03207 { 03208 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03209 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03210 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03211 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03212 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03213 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03214 int codec0 = 0, codec1 = 0; 03215 void *pvt0 = NULL, *pvt1 = NULL; 03216 03217 /* Lock channels */ 03218 ast_channel_lock(c0); 03219 while(ast_channel_trylock(c1)) { 03220 ast_channel_unlock(c0); 03221 usleep(1); 03222 ast_channel_lock(c0); 03223 } 03224 03225 /* Find channel driver interfaces */ 03226 if (!(pr0 = get_proto(c0))) { 03227 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03228 ast_channel_unlock(c0); 03229 ast_channel_unlock(c1); 03230 return AST_BRIDGE_FAILED; 03231 } 03232 if (!(pr1 = get_proto(c1))) { 03233 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03234 ast_channel_unlock(c0); 03235 ast_channel_unlock(c1); 03236 return AST_BRIDGE_FAILED; 03237 } 03238 03239 /* Get channel specific interface structures */ 03240 pvt0 = c0->tech_pvt; 03241 pvt1 = c1->tech_pvt; 03242 03243 /* Get audio and video interface (if native bridge is possible) */ 03244 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03245 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03246 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03247 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03248 03249 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03250 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03251 audio_p0_res = AST_RTP_GET_FAILED; 03252 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03253 audio_p1_res = AST_RTP_GET_FAILED; 03254 03255 /* Check if a bridge is possible (partial/native) */ 03256 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03257 /* Somebody doesn't want to play... */ 03258 ast_channel_unlock(c0); 03259 ast_channel_unlock(c1); 03260 return AST_BRIDGE_FAILED_NOWARN; 03261 } 03262 03263 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03264 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03265 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03266 audio_p0_res = AST_RTP_TRY_PARTIAL; 03267 } 03268 03269 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03270 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03271 audio_p1_res = AST_RTP_TRY_PARTIAL; 03272 } 03273 03274 /* If both sides are not using the same method of DTMF transmission 03275 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03276 * -------------------------------------------------- 03277 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03278 * |-----------|------------|-----------------------| 03279 * | Inband | False | True | 03280 * | RFC2833 | True | True | 03281 * | SIP INFO | False | False | 03282 * -------------------------------------------------- 03283 * However, if DTMF from both channels is being monitored by the core, then 03284 * we can still do packet-to-packet bridging, because passing through the 03285 * core will handle DTMF mode translation. 03286 */ 03287 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03288 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03289 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03290 ast_channel_unlock(c0); 03291 ast_channel_unlock(c1); 03292 return AST_BRIDGE_FAILED_NOWARN; 03293 } 03294 audio_p0_res = AST_RTP_TRY_PARTIAL; 03295 audio_p1_res = AST_RTP_TRY_PARTIAL; 03296 } 03297 03298 /* If the core will need to compensate and the P2P bridge will need to feed up DTMF frames then we can not reliably do so yet, so do not P2P bridge */ 03299 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF) && ast_test_flag(p0, FLAG_DTMF_COMPENSATE)) || 03300 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF) && ast_test_flag(p1, FLAG_DTMF_COMPENSATE))) { 03301 ast_channel_unlock(c0); 03302 ast_channel_unlock(c1); 03303 return AST_BRIDGE_FAILED_NOWARN; 03304 } 03305 03306 /* Get codecs from both sides */ 03307 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03308 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03309 if (codec0 && codec1 && !(codec0 & codec1)) { 03310 /* Hey, we can't do native bridging if both parties speak different codecs */ 03311 if (option_debug) 03312 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03313 ast_channel_unlock(c0); 03314 ast_channel_unlock(c1); 03315 return AST_BRIDGE_FAILED_NOWARN; 03316 } 03317 03318 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03319 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03320 struct ast_format_list fmt0, fmt1; 03321 03322 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03323 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03324 if (option_debug) 03325 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03326 ast_channel_unlock(c0); 03327 ast_channel_unlock(c1); 03328 return AST_BRIDGE_FAILED_NOWARN; 03329 } 03330 /* They must also be using the same packetization */ 03331 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03332 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03333 if (fmt0.cur_ms != fmt1.cur_ms) { 03334 if (option_debug) 03335 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03336 ast_channel_unlock(c0); 03337 ast_channel_unlock(c1); 03338 return AST_BRIDGE_FAILED_NOWARN; 03339 } 03340 03341 if (option_verbose > 2) 03342 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03343 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03344 } else { 03345 if (option_verbose > 2) 03346 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03347 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03348 } 03349 03350 return res; 03351 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2681 of file rtp.c.
Referenced by process_sdp().
02682 { 02683 if (pt < 0 || pt > MAX_RTP_PT) 02684 return 0; /* bogus payload type */ 02685 02686 if (static_RTP_PT[pt].isAstFormat) 02687 return static_RTP_PT[pt].code; 02688 else 02689 return 0; 02690 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) | [read] |
Definition at line 2676 of file rtp.c.
Referenced by add_codec_to_sdp(), and process_sdp().
02677 { 02678 return &rtp->pref; 02679 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2663 of file rtp.c.
Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp(), register_verify(), set_peer_capabilities(), start_rtp(), and transmit_response_with_sdp().
02664 { 02665 int x; 02666 for (x = 0; x < 32; x++) { /* Ugly way */ 02667 rtp->pref.order[x] = prefs->order[x]; 02668 rtp->pref.framing[x] = prefs->framing[x]; 02669 } 02670 if (rtp->smoother) 02671 ast_smoother_free(rtp->smoother); 02672 rtp->smoother = NULL; 02673 return 0; 02674 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2080 of file rtp.c.
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().
02081 { 02082 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02083 /*Print some info on the call here */ 02084 ast_verbose(" RTP-stats\n"); 02085 ast_verbose("* Our Receiver:\n"); 02086 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02087 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02088 ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02089 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02090 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02091 ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count); 02092 ast_verbose("* Our Sender:\n"); 02093 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02094 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02095 ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost); 02096 ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter); 02097 ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count); 02098 ast_verbose(" RTT: %f\n", rtp->rtcp->rtt); 02099 } 02100 02101 if (rtp->smoother) 02102 ast_smoother_free(rtp->smoother); 02103 if (rtp->ioid) 02104 ast_io_remove(rtp->io, rtp->ioid); 02105 if (rtp->s > -1) 02106 close(rtp->s); 02107 if (rtp->rtcp) { 02108 if (rtp->rtcp->schedid > 0) 02109 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02110 close(rtp->rtcp->s); 02111 free(rtp->rtcp); 02112 rtp->rtcp=NULL; 02113 } 02114 02115 ast_mutex_destroy(&rtp->bridge_lock); 02116 02117 free(rtp); 02118 }
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 1466 of file rtp.c.
Referenced by wait_for_answer().
01467 { 01468 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01469 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01470 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01471 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01472 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01473 int srccodec, destcodec, nat_active = 0; 01474 01475 /* Lock channels */ 01476 ast_channel_lock(dest); 01477 if (src) { 01478 while(ast_channel_trylock(src)) { 01479 ast_channel_unlock(dest); 01480 usleep(1); 01481 ast_channel_lock(dest); 01482 } 01483 } 01484 01485 /* Find channel driver interfaces */ 01486 destpr = get_proto(dest); 01487 if (src) 01488 srcpr = get_proto(src); 01489 if (!destpr) { 01490 if (option_debug) 01491 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01492 ast_channel_unlock(dest); 01493 if (src) 01494 ast_channel_unlock(src); 01495 return 0; 01496 } 01497 if (!srcpr) { 01498 if (option_debug) 01499 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01500 ast_channel_unlock(dest); 01501 if (src) 01502 ast_channel_unlock(src); 01503 return 0; 01504 } 01505 01506 /* Get audio and video interface (if native bridge is possible) */ 01507 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01508 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01509 if (srcpr) { 01510 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01511 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01512 } 01513 01514 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01515 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01516 /* Somebody doesn't want to play... */ 01517 ast_channel_unlock(dest); 01518 if (src) 01519 ast_channel_unlock(src); 01520 return 0; 01521 } 01522 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01523 srccodec = srcpr->get_codec(src); 01524 else 01525 srccodec = 0; 01526 if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec) 01527 destcodec = destpr->get_codec(dest); 01528 else 01529 destcodec = 0; 01530 /* Ensure we have at least one matching codec */ 01531 if (!(srccodec & destcodec)) { 01532 ast_channel_unlock(dest); 01533 if (src) 01534 ast_channel_unlock(src); 01535 return 0; 01536 } 01537 /* Consider empty media as non-existant */ 01538 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01539 srcp = NULL; 01540 /* If the client has NAT stuff turned on then just safe NAT is active */ 01541 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01542 nat_active = 1; 01543 /* Bridge media early */ 01544 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01545 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01546 ast_channel_unlock(dest); 01547 if (src) 01548 ast_channel_unlock(src); 01549 if (option_debug) 01550 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01551 return 1; 01552 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 512 of file rtp.c.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().
00513 { 00514 return rtp->s; 00515 }
Definition at line 2002 of file rtp.c.
Referenced by ast_rtp_read(), and do_monitor().
02003 { 02004 struct ast_rtp *bridged = NULL; 02005 02006 ast_mutex_lock(&rtp->bridge_lock); 02007 bridged = rtp->bridged; 02008 ast_mutex_unlock(&rtp->bridge_lock); 02009 02010 return bridged; 02011 }
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 1672 of file rtp.c.
Referenced by process_sdp().
01674 { 01675 int pt; 01676 01677 ast_mutex_lock(&rtp->bridge_lock); 01678 01679 *astFormats = *nonAstFormats = 0; 01680 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01681 if (rtp->current_RTP_PT[pt].isAstFormat) { 01682 *astFormats |= rtp->current_RTP_PT[pt].code; 01683 } else { 01684 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01685 } 01686 } 01687 01688 ast_mutex_unlock(&rtp->bridge_lock); 01689 01690 return; 01691 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 1984 of file rtp.c.
Referenced by add_sdp(), bridge_native_loop(), do_monitor(), gtalk_update_stun(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
01985 { 01986 if ((them->sin_family != AF_INET) || 01987 (them->sin_port != rtp->them.sin_port) || 01988 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 01989 them->sin_family = AF_INET; 01990 them->sin_port = rtp->them.sin_port; 01991 them->sin_addr = rtp->them.sin_addr; 01992 return 1; 01993 } 01994 return 0; 01995 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2050 of file rtp.c.
Referenced by acf_channel_read(), handle_request_bye(), and sip_hangup().
02051 { 02052 /* 02053 *ssrc our ssrc 02054 *themssrc their ssrc 02055 *lp lost packets 02056 *rxjitter our calculated jitter(rx) 02057 *rxcount no. received packets 02058 *txjitter reported jitter of the other end 02059 *txcount transmitted packets 02060 *rlp remote lost packets 02061 *rtt round trip time 02062 */ 02063 02064 if (qual) { 02065 qual->local_ssrc = rtp->ssrc; 02066 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02067 qual->local_jitter = rtp->rxjitter; 02068 qual->local_count = rtp->rxcount; 02069 qual->remote_ssrc = rtp->themssrc; 02070 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02071 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02072 qual->remote_count = rtp->txcount; 02073 qual->rtt = rtp->rtcp->rtt; 02074 } 02075 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt); 02076 02077 return rtp->rtcp->quality; 02078 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 567 of file rtp.c.
Referenced by do_monitor().
00568 { 00569 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00570 return 0; 00571 return rtp->rtpholdtimeout; 00572 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 575 of file rtp.c.
Referenced by do_monitor().
00576 { 00577 return rtp->rtpkeepalive; 00578 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 559 of file rtp.c.
Referenced by do_monitor().
00560 { 00561 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00562 return 0; 00563 return rtp->rtptimeout; 00564 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 1997 of file rtp.c.
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 595 of file rtp.c.
Referenced by sip_get_rtp_peer().
00596 { 00597 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00598 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 3736 of file rtp.c.
Referenced by main().
03737 { 03738 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03739 ast_rtp_reload(); 03740 }
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 1715 of file rtp.c.
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().
01716 { 01717 int pt = 0; 01718 01719 ast_mutex_lock(&rtp->bridge_lock); 01720 01721 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01722 code == rtp->rtp_lookup_code_cache_code) { 01723 /* Use our cached mapping, to avoid the overhead of the loop below */ 01724 pt = rtp->rtp_lookup_code_cache_result; 01725 ast_mutex_unlock(&rtp->bridge_lock); 01726 return pt; 01727 } 01728 01729 /* Check the dynamic list first */ 01730 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01731 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01732 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01733 rtp->rtp_lookup_code_cache_code = code; 01734 rtp->rtp_lookup_code_cache_result = pt; 01735 ast_mutex_unlock(&rtp->bridge_lock); 01736 return pt; 01737 } 01738 } 01739 01740 /* Then the static list */ 01741 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01742 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01743 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01744 rtp->rtp_lookup_code_cache_code = code; 01745 rtp->rtp_lookup_code_cache_result = pt; 01746 ast_mutex_unlock(&rtp->bridge_lock); 01747 return pt; 01748 } 01749 } 01750 01751 ast_mutex_unlock(&rtp->bridge_lock); 01752 01753 return -1; 01754 }
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 1775 of file rtp.c.
Referenced by process_sdp().
01777 { 01778 int format; 01779 unsigned len; 01780 char *end = buf; 01781 char *start = buf; 01782 01783 if (!buf || !size) 01784 return NULL; 01785 01786 snprintf(end, size, "0x%x (", capability); 01787 01788 len = strlen(end); 01789 end += len; 01790 size -= len; 01791 start = end; 01792 01793 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01794 if (capability & format) { 01795 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01796 01797 snprintf(end, size, "%s|", name); 01798 len = strlen(end); 01799 end += len; 01800 size -= len; 01801 } 01802 } 01803 01804 if (start == end) 01805 snprintf(start, size, "nothing)"); 01806 else if (size > 1) 01807 *(end -1) = ')'; 01808 01809 return buf; 01810 }
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 1756 of file rtp.c.
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().
01758 { 01759 unsigned int i; 01760 01761 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01762 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01763 if (isAstFormat && 01764 (code == AST_FORMAT_G726_AAL2) && 01765 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01766 return "G726-32"; 01767 else 01768 return mimeTypes[i].subtype; 01769 } 01770 } 01771 01772 return ""; 01773 }
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 1693 of file rtp.c.
Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().
01694 { 01695 struct rtpPayloadType result; 01696 01697 result.isAstFormat = result.code = 0; 01698 01699 if (pt < 0 || pt > MAX_RTP_PT) 01700 return result; /* bogus payload type */ 01701 01702 /* Start with negotiated codecs */ 01703 ast_mutex_lock(&rtp->bridge_lock); 01704 result = rtp->current_RTP_PT[pt]; 01705 ast_mutex_unlock(&rtp->bridge_lock); 01706 01707 /* If it doesn't exist, check our static RTP type list, just in case */ 01708 if (!result.code) 01709 result = static_RTP_PT[pt]; 01710 01711 return result; 01712 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1554 of file rtp.c.
Referenced by wait_for_answer().
01555 { 01556 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01557 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01558 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01559 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01560 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01561 int srccodec, destcodec; 01562 01563 /* Lock channels */ 01564 ast_channel_lock(dest); 01565 while(ast_channel_trylock(src)) { 01566 ast_channel_unlock(dest); 01567 usleep(1); 01568 ast_channel_lock(dest); 01569 } 01570 01571 /* Find channel driver interfaces */ 01572 if (!(destpr = get_proto(dest))) { 01573 if (option_debug) 01574 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01575 ast_channel_unlock(dest); 01576 ast_channel_unlock(src); 01577 return 0; 01578 } 01579 if (!(srcpr = get_proto(src))) { 01580 if (option_debug) 01581 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01582 ast_channel_unlock(dest); 01583 ast_channel_unlock(src); 01584 return 0; 01585 } 01586 01587 /* Get audio and video interface (if native bridge is possible) */ 01588 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01589 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01590 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01591 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01592 01593 /* Ensure we have at least one matching codec */ 01594 if (srcpr->get_codec) 01595 srccodec = srcpr->get_codec(src); 01596 else 01597 srccodec = 0; 01598 if (destpr->get_codec) 01599 destcodec = destpr->get_codec(dest); 01600 else 01601 destcodec = 0; 01602 01603 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01604 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) { 01605 /* Somebody doesn't want to play... */ 01606 ast_channel_unlock(dest); 01607 ast_channel_unlock(src); 01608 return 0; 01609 } 01610 ast_rtp_pt_copy(destp, srcp); 01611 if (vdestp && vsrcp) 01612 ast_rtp_pt_copy(vdestp, vsrcp); 01613 if (media) { 01614 /* Bridge early */ 01615 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01616 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01617 } 01618 ast_channel_unlock(dest); 01619 ast_channel_unlock(src); 01620 if (option_debug) 01621 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01622 return 1; 01623 }
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 1956 of file rtp.c.
01957 { 01958 struct in_addr ia; 01959 01960 memset(&ia, 0, sizeof(ia)); 01961 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 01962 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1856 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().
01857 { 01858 ast_mutex_init(&rtp->bridge_lock); 01859 01860 rtp->them.sin_family = AF_INET; 01861 rtp->us.sin_family = AF_INET; 01862 rtp->ssrc = ast_random(); 01863 rtp->seqno = ast_random() & 0xffff; 01864 ast_set_flag(rtp, FLAG_HAS_DTMF); 01865 01866 return; 01867 }
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 1869 of file rtp.c.
Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), sip_alloc(), and start_rtp().
01870 { 01871 struct ast_rtp *rtp; 01872 int x; 01873 int first; 01874 int startplace; 01875 01876 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01877 return NULL; 01878 01879 ast_rtp_new_init(rtp); 01880 01881 rtp->s = rtp_socket(); 01882 if (rtp->s < 0) { 01883 free(rtp); 01884 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01885 return NULL; 01886 } 01887 if (sched && rtcpenable) { 01888 rtp->sched = sched; 01889 rtp->rtcp = ast_rtcp_new(); 01890 } 01891 01892 /* Select a random port number in the range of possible RTP */ 01893 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01894 x = x & ~1; 01895 /* Save it for future references. */ 01896 startplace = x; 01897 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01898 for (;;) { 01899 /* Must be an even port number by RTP spec */ 01900 rtp->us.sin_port = htons(x); 01901 rtp->us.sin_addr = addr; 01902 /* If there's rtcp, initialize it as well. */ 01903 if (rtp->rtcp) { 01904 rtp->rtcp->us.sin_port = htons(x + 1); 01905 rtp->rtcp->us.sin_addr = addr; 01906 } 01907 /* Try to bind it/them. */ 01908 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01909 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01910 break; 01911 if (!first) { 01912 /* Primary bind succeeded! Gotta recreate it */ 01913 close(rtp->s); 01914 rtp->s = rtp_socket(); 01915 } 01916 if (errno != EADDRINUSE) { 01917 /* We got an error that wasn't expected, abort! */ 01918 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01919 close(rtp->s); 01920 if (rtp->rtcp) { 01921 close(rtp->rtcp->s); 01922 free(rtp->rtcp); 01923 } 01924 free(rtp); 01925 return NULL; 01926 } 01927 /* The port was used, increment it (by two). */ 01928 x += 2; 01929 /* Did we go over the limit ? */ 01930 if (x > rtpend) 01931 /* then, start from the begingig. */ 01932 x = (rtpstart + 1) & ~1; 01933 /* Check if we reached the place were we started. */ 01934 if (x == startplace) { 01935 /* If so, there's no ports available. */ 01936 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01937 close(rtp->s); 01938 if (rtp->rtcp) { 01939 close(rtp->rtcp->s); 01940 free(rtp->rtcp); 01941 } 01942 free(rtp); 01943 return NULL; 01944 } 01945 } 01946 rtp->sched = sched; 01947 rtp->io = io; 01948 if (callbackmode) { 01949 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01950 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01951 } 01952 ast_rtp_pt_default(rtp); 01953 return rtp; 01954 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2781 of file rtp.c.
Referenced by load_module().
02782 { 02783 struct ast_rtp_protocol *cur; 02784 02785 AST_LIST_LOCK(&protos); 02786 AST_LIST_TRAVERSE(&protos, cur, list) { 02787 if (!strcmp(cur->type, proto->type)) { 02788 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02789 AST_LIST_UNLOCK(&protos); 02790 return -1; 02791 } 02792 } 02793 AST_LIST_INSERT_HEAD(&protos, proto, list); 02794 AST_LIST_UNLOCK(&protos); 02795 02796 return 0; 02797 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2773 of file rtp.c.
Referenced by load_module(), and unload_module().
02774 { 02775 AST_LIST_LOCK(&protos); 02776 AST_LIST_REMOVE(&protos, proto, list); 02777 AST_LIST_UNLOCK(&protos); 02778 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1390 of file rtp.c.
Referenced by process_sdp().
01391 { 01392 int i; 01393 01394 if (!rtp) 01395 return; 01396 01397 ast_mutex_lock(&rtp->bridge_lock); 01398 01399 for (i = 0; i < MAX_RTP_PT; ++i) { 01400 rtp->current_RTP_PT[i].isAstFormat = 0; 01401 rtp->current_RTP_PT[i].code = 0; 01402 } 01403 01404 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01405 rtp->rtp_lookup_code_cache_code = 0; 01406 rtp->rtp_lookup_code_cache_result = 0; 01407 01408 ast_mutex_unlock(&rtp->bridge_lock); 01409 }
Copy payload types between RTP structures.
Definition at line 1430 of file rtp.c.
Referenced by ast_rtp_make_compatible(), and process_sdp().
01431 { 01432 unsigned int i; 01433 01434 ast_mutex_lock(&dest->bridge_lock); 01435 ast_mutex_lock(&src->bridge_lock); 01436 01437 for (i=0; i < MAX_RTP_PT; ++i) { 01438 dest->current_RTP_PT[i].isAstFormat = 01439 src->current_RTP_PT[i].isAstFormat; 01440 dest->current_RTP_PT[i].code = 01441 src->current_RTP_PT[i].code; 01442 } 01443 dest->rtp_lookup_code_cache_isAstFormat = 0; 01444 dest->rtp_lookup_code_cache_code = 0; 01445 dest->rtp_lookup_code_cache_result = 0; 01446 01447 ast_mutex_unlock(&src->bridge_lock); 01448 ast_mutex_unlock(&dest->bridge_lock); 01449 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1411 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr().
01412 { 01413 int i; 01414 01415 ast_mutex_lock(&rtp->bridge_lock); 01416 01417 /* Initialize to default payload types */ 01418 for (i = 0; i < MAX_RTP_PT; ++i) { 01419 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01420 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01421 } 01422 01423 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01424 rtp->rtp_lookup_code_cache_code = 0; 01425 rtp->rtp_lookup_code_cache_result = 0; 01426 01427 ast_mutex_unlock(&rtp->bridge_lock); 01428 }
Definition at line 2574 of file rtp.c.
References AST_FORMAT_MAX_AUDIO, 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, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_frame::has_timing_info, 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::ssrc, ast_frame::subclass, ast_rtp::them, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
02575 { 02576 unsigned char *rtpheader; 02577 int hdrlen = 12; 02578 int res; 02579 unsigned int ms; 02580 int pred; 02581 int mark = 0; 02582 02583 ms = calc_txstamp(rtp, &f->delivery); 02584 /* Default prediction */ 02585 if (f->subclass < AST_FORMAT_MAX_AUDIO) { 02586 pred = rtp->lastts + f->samples; 02587 02588 /* Re-calculate last TS */ 02589 rtp->lastts = rtp->lastts + ms * 8; 02590 if (ast_tvzero(f->delivery)) { 02591 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02592 and if so, go with our prediction */ 02593 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02594 rtp->lastts = pred; 02595 else { 02596 if (option_debug > 2) 02597 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02598 mark = 1; 02599 } 02600 } 02601 } else { 02602 mark = f->subclass & 0x1; 02603 pred = rtp->lastovidtimestamp + f->samples; 02604 /* Re-calculate last TS */ 02605 rtp->lastts = rtp->lastts + ms * 90; 02606 /* If it's close to our prediction, go for it */ 02607 if (ast_tvzero(f->delivery)) { 02608 if (abs(rtp->lastts - pred) < 7200) { 02609 rtp->lastts = pred; 02610 rtp->lastovidtimestamp += f->samples; 02611 } else { 02612 if (option_debug > 2) 02613 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); 02614 rtp->lastovidtimestamp = rtp->lastts; 02615 } 02616 } 02617 } 02618 /* If the timestamp for non-digit packets has moved beyond the timestamp 02619 for digits, update the digit timestamp. 02620 */ 02621 if (rtp->lastts > rtp->lastdigitts) 02622 rtp->lastdigitts = rtp->lastts; 02623 02624 if (f->has_timing_info) 02625 rtp->lastts = f->ts * 8; 02626 02627 /* Get a pointer to the header */ 02628 rtpheader = (unsigned char *)(f->data - hdrlen); 02629 02630 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02631 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02632 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02633 02634 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02635 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02636 if (res <0) { 02637 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02638 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)); 02639 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02640 /* Only give this error message once if we are not RTP debugging */ 02641 if (option_debug || rtpdebug) 02642 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)); 02643 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02644 } 02645 } else { 02646 rtp->txcount++; 02647 rtp->txoctetcount +=(res - hdrlen); 02648 02649 if (rtp->rtcp && rtp->rtcp->schedid < 1) 02650 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02651 } 02652 02653 if (rtp_debug_test_addr(&rtp->them)) 02654 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02655 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02656 } 02657 02658 rtp->seqno++; 02659 02660 return 0; 02661 }
Definition at line 1097 of file rtp.c.
Referenced by gtalk_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().
01098 { 01099 int res; 01100 struct sockaddr_in sin; 01101 socklen_t len; 01102 unsigned int seqno; 01103 int version; 01104 int payloadtype; 01105 int hdrlen = 12; 01106 int padding; 01107 int mark; 01108 int ext; 01109 int cc; 01110 unsigned int ssrc; 01111 unsigned int timestamp; 01112 unsigned int *rtpheader; 01113 struct rtpPayloadType rtpPT; 01114 struct ast_rtp *bridged = NULL; 01115 01116 /* If time is up, kill it */ 01117 if (rtp->sending_digit) 01118 ast_rtp_senddigit_continuation(rtp); 01119 01120 len = sizeof(sin); 01121 01122 /* Cache where the header will go */ 01123 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01124 0, (struct sockaddr *)&sin, &len); 01125 01126 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01127 if (res < 0) { 01128 if (errno == EBADF) 01129 CRASH; 01130 if (errno != EAGAIN) { 01131 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01132 return NULL; 01133 } 01134 return &ast_null_frame; 01135 } 01136 01137 if (res < hdrlen) { 01138 ast_log(LOG_WARNING, "RTP Read too short\n"); 01139 return &ast_null_frame; 01140 } 01141 01142 /* Get fields */ 01143 seqno = ntohl(rtpheader[0]); 01144 01145 /* Check RTP version */ 01146 version = (seqno & 0xC0000000) >> 30; 01147 if (!version) { 01148 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01149 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01150 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01151 } 01152 return &ast_null_frame; 01153 } 01154 01155 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01156 /* If we don't have the other side's address, then ignore this */ 01157 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01158 return &ast_null_frame; 01159 #endif 01160 01161 /* Send to whoever send to us if NAT is turned on */ 01162 if (rtp->nat) { 01163 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01164 (rtp->them.sin_port != sin.sin_port)) { 01165 rtp->them = sin; 01166 if (rtp->rtcp) { 01167 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01168 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01169 } 01170 rtp->rxseqno = 0; 01171 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01172 if (option_debug || rtpdebug) 01173 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)); 01174 } 01175 } 01176 01177 /* If we are bridged to another RTP stream, send direct */ 01178 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01179 return &ast_null_frame; 01180 01181 if (version != 2) 01182 return &ast_null_frame; 01183 01184 payloadtype = (seqno & 0x7f0000) >> 16; 01185 padding = seqno & (1 << 29); 01186 mark = seqno & (1 << 23); 01187 ext = seqno & (1 << 28); 01188 cc = (seqno & 0xF000000) >> 24; 01189 seqno &= 0xffff; 01190 timestamp = ntohl(rtpheader[1]); 01191 ssrc = ntohl(rtpheader[2]); 01192 01193 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01194 if (option_debug || rtpdebug) 01195 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01196 mark = 1; 01197 } 01198 01199 rtp->rxssrc = ssrc; 01200 01201 if (padding) { 01202 /* Remove padding bytes */ 01203 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01204 } 01205 01206 if (cc) { 01207 /* CSRC fields present */ 01208 hdrlen += cc*4; 01209 } 01210 01211 if (ext) { 01212 /* RTP Extension present */ 01213 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01214 hdrlen += 4; 01215 } 01216 01217 if (res < hdrlen) { 01218 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01219 return &ast_null_frame; 01220 } 01221 01222 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01223 01224 if (rtp->rxcount==1) { 01225 /* This is the first RTP packet successfully received from source */ 01226 rtp->seedrxseqno = seqno; 01227 } 01228 01229 /* Do not schedule RR if RTCP isn't run */ 01230 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01231 /* Schedule transmission of Receiver Report */ 01232 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01233 } 01234 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01235 rtp->cycles += RTP_SEQ_MOD; 01236 01237 rtp->lastrxseqno = seqno; 01238 01239 if (rtp->themssrc==0) 01240 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01241 01242 if (rtp_debug_test_addr(&sin)) 01243 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01244 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01245 01246 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01247 if (!rtpPT.isAstFormat) { 01248 struct ast_frame *f = NULL; 01249 01250 /* This is special in-band data that's not one of our codecs */ 01251 if (rtpPT.code == AST_RTP_DTMF) { 01252 /* It's special -- rfc2833 process it */ 01253 if (rtp_debug_test_addr(&sin)) { 01254 unsigned char *data; 01255 unsigned int event; 01256 unsigned int event_end; 01257 unsigned int duration; 01258 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01259 event = ntohl(*((unsigned int *)(data))); 01260 event >>= 24; 01261 event_end = ntohl(*((unsigned int *)(data))); 01262 event_end <<= 8; 01263 event_end >>= 24; 01264 duration = ntohl(*((unsigned int *)(data))); 01265 duration &= 0xFFFF; 01266 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); 01267 } 01268 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01269 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01270 /* It's really special -- process it the Cisco way */ 01271 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01272 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01273 rtp->lastevent = seqno; 01274 } 01275 } else if (rtpPT.code == AST_RTP_CN) { 01276 /* Comfort Noise */ 01277 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01278 } else { 01279 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01280 } 01281 return f ? f : &ast_null_frame; 01282 } 01283 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01284 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01285 01286 if (!rtp->lastrxts) 01287 rtp->lastrxts = timestamp; 01288 01289 rtp->rxseqno = seqno; 01290 01291 /* Record received timestamp as last received now */ 01292 rtp->lastrxts = timestamp; 01293 01294 rtp->f.mallocd = 0; 01295 rtp->f.datalen = res - hdrlen; 01296 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01297 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01298 rtp->f.seqno = seqno; 01299 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01300 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01301 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01302 ast_frame_byteswap_be(&rtp->f); 01303 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01304 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01305 rtp->f.has_timing_info = 1; 01306 rtp->f.ts = timestamp / 8; 01307 rtp->f.len = rtp->f.samples / 8; 01308 } else { 01309 /* Video -- samples is # of samples vs. 90000 */ 01310 if (!rtp->lastividtimestamp) 01311 rtp->lastividtimestamp = timestamp; 01312 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01313 rtp->lastividtimestamp = timestamp; 01314 rtp->f.delivery.tv_sec = 0; 01315 rtp->f.delivery.tv_usec = 0; 01316 if (mark) 01317 rtp->f.subclass |= 0x1; 01318 01319 } 01320 rtp->f.src = "RTP"; 01321 return &rtp->f; 01322 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3671 of file rtp.c.
Referenced by ast_rtp_init().
03672 { 03673 struct ast_config *cfg; 03674 const char *s; 03675 03676 rtpstart = 5000; 03677 rtpend = 31000; 03678 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03679 cfg = ast_config_load("rtp.conf"); 03680 if (cfg) { 03681 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03682 rtpstart = atoi(s); 03683 if (rtpstart < 1024) 03684 rtpstart = 1024; 03685 if (rtpstart > 65535) 03686 rtpstart = 65535; 03687 } 03688 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03689 rtpend = atoi(s); 03690 if (rtpend < 1024) 03691 rtpend = 1024; 03692 if (rtpend > 65535) 03693 rtpend = 65535; 03694 } 03695 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03696 rtcpinterval = atoi(s); 03697 if (rtcpinterval == 0) 03698 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03699 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03700 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03701 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03702 rtcpinterval = RTCP_MAX_INTERVALMS; 03703 } 03704 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03705 #ifdef SO_NO_CHECK 03706 if (ast_false(s)) 03707 nochecksums = 1; 03708 else 03709 nochecksums = 0; 03710 #else 03711 if (ast_false(s)) 03712 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03713 #endif 03714 } 03715 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03716 dtmftimeout = atoi(s); 03717 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03718 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03719 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03720 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03721 }; 03722 } 03723 ast_config_destroy(cfg); 03724 } 03725 if (rtpstart >= rtpend) { 03726 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03727 rtpstart = 5000; 03728 rtpend = 31000; 03729 } 03730 if (option_verbose > 1) 03731 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03732 return 0; 03733 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2030 of file rtp.c.
02031 { 02032 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02033 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02034 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02035 rtp->lastts = 0; 02036 rtp->lastdigitts = 0; 02037 rtp->lastrxts = 0; 02038 rtp->lastividtimestamp = 0; 02039 rtp->lastovidtimestamp = 0; 02040 rtp->lasteventseqn = 0; 02041 rtp->lastevent = 0; 02042 rtp->lasttxformat = 0; 02043 rtp->lastrxformat = 0; 02044 rtp->dtmfcount = 0; 02045 rtp->dtmfsamples = 0; 02046 rtp->seqno = 0; 02047 rtp->rxseqno = 0; 02048 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2540 of file rtp.c.
Referenced by do_monitor().
02541 { 02542 unsigned int *rtpheader; 02543 int hdrlen = 12; 02544 int res; 02545 int payload; 02546 char data[256]; 02547 level = 127 - (level & 0x7f); 02548 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02549 02550 /* If we have no peer, return immediately */ 02551 if (!rtp->them.sin_addr.s_addr) 02552 return 0; 02553 02554 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02555 02556 /* Get a pointer to the header */ 02557 rtpheader = (unsigned int *)data; 02558 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02559 rtpheader[1] = htonl(rtp->lastts); 02560 rtpheader[2] = htonl(rtp->ssrc); 02561 data[12] = level; 02562 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02563 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02564 if (res <0) 02565 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)); 02566 if (rtp_debug_test_addr(&rtp->them)) 02567 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02568 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02569 02570 } 02571 return 0; 02572 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2140 of file rtp.c.
Referenced by oh323_digit_begin(), and sip_senddigit_begin().
02141 { 02142 unsigned int *rtpheader; 02143 int hdrlen = 12, res = 0, i = 0, payload = 0; 02144 char data[256]; 02145 02146 if ((digit <= '9') && (digit >= '0')) 02147 digit -= '0'; 02148 else if (digit == '*') 02149 digit = 10; 02150 else if (digit == '#') 02151 digit = 11; 02152 else if ((digit >= 'A') && (digit <= 'D')) 02153 digit = digit - 'A' + 12; 02154 else if ((digit >= 'a') && (digit <= 'd')) 02155 digit = digit - 'a' + 12; 02156 else { 02157 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02158 return 0; 02159 } 02160 02161 /* If we have no peer, return immediately */ 02162 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02163 return 0; 02164 02165 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02166 02167 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02168 rtp->send_duration = 160; 02169 02170 /* Get a pointer to the header */ 02171 rtpheader = (unsigned int *)data; 02172 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02173 rtpheader[1] = htonl(rtp->lastdigitts); 02174 rtpheader[2] = htonl(rtp->ssrc); 02175 02176 for (i = 0; i < 2; i++) { 02177 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02178 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02179 if (res < 0) 02180 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02181 ast_inet_ntoa(rtp->them.sin_addr), 02182 ntohs(rtp->them.sin_port), strerror(errno)); 02183 if (rtp_debug_test_addr(&rtp->them)) 02184 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02185 ast_inet_ntoa(rtp->them.sin_addr), 02186 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02187 /* Increment sequence number */ 02188 rtp->seqno++; 02189 /* Increment duration */ 02190 rtp->send_duration += 160; 02191 /* Clear marker bit and set seqno */ 02192 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02193 } 02194 02195 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02196 rtp->sending_digit = 1; 02197 rtp->send_digit = digit; 02198 rtp->send_payload = payload; 02199 02200 return 0; 02201 }
static int ast_rtp_senddigit_continuation | ( | struct ast_rtp * | rtp | ) | [static] |
Send continuation frame for DTMF.
Definition at line 2204 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_verbose(), 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().
02205 { 02206 unsigned int *rtpheader; 02207 int hdrlen = 12, res = 0; 02208 char data[256]; 02209 02210 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02211 return 0; 02212 02213 /* Setup packet to send */ 02214 rtpheader = (unsigned int *)data; 02215 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02216 rtpheader[1] = htonl(rtp->lastdigitts); 02217 rtpheader[2] = htonl(rtp->ssrc); 02218 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02219 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02220 02221 /* Transmit */ 02222 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02223 if (res < 0) 02224 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02225 ast_inet_ntoa(rtp->them.sin_addr), 02226 ntohs(rtp->them.sin_port), strerror(errno)); 02227 if (rtp_debug_test_addr(&rtp->them)) 02228 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02229 ast_inet_ntoa(rtp->them.sin_addr), 02230 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02231 02232 /* Increment sequence number */ 02233 rtp->seqno++; 02234 /* Increment duration */ 02235 rtp->send_duration += 160; 02236 02237 return 0; 02238 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send end packets for DTMF.
Definition at line 2241 of file rtp.c.
References ast_inet_ntoa(), ast_log(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, 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 oh323_digit_end(), and sip_senddigit_end().
02242 { 02243 unsigned int *rtpheader; 02244 int hdrlen = 12, res = 0, i = 0; 02245 char data[256]; 02246 02247 /* If no address, then bail out */ 02248 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02249 return 0; 02250 02251 if ((digit <= '9') && (digit >= '0')) 02252 digit -= '0'; 02253 else if (digit == '*') 02254 digit = 10; 02255 else if (digit == '#') 02256 digit = 11; 02257 else if ((digit >= 'A') && (digit <= 'D')) 02258 digit = digit - 'A' + 12; 02259 else if ((digit >= 'a') && (digit <= 'd')) 02260 digit = digit - 'a' + 12; 02261 else { 02262 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02263 return 0; 02264 } 02265 02266 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02267 02268 rtpheader = (unsigned int *)data; 02269 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02270 rtpheader[1] = htonl(rtp->lastdigitts); 02271 rtpheader[2] = htonl(rtp->ssrc); 02272 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02273 /* Set end bit */ 02274 rtpheader[3] |= htonl((1 << 23)); 02275 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02276 /* Send 3 termination packets */ 02277 for (i = 0; i < 3; i++) { 02278 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02279 if (res < 0) 02280 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02281 ast_inet_ntoa(rtp->them.sin_addr), 02282 ntohs(rtp->them.sin_port), strerror(errno)); 02283 if (rtp_debug_test_addr(&rtp->them)) 02284 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02285 ast_inet_ntoa(rtp->them.sin_addr), 02286 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02287 } 02288 rtp->sending_digit = 0; 02289 rtp->send_digit = 0; 02290 /* Increment lastdigitts */ 02291 rtp->lastdigitts += 960; 02292 rtp->seqno++; 02293 02294 return res; 02295 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 585 of file rtp.c.
Referenced by start_rtp().
00586 { 00587 rtp->callback = callback; 00588 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 580 of file rtp.c.
Referenced by start_rtp().
00581 { 00582 rtp->data = data; 00583 }
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).
Definition at line 1629 of file rtp.c.
Referenced by gtalk_newcall(), and process_sdp().
01630 { 01631 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01632 return; /* bogus payload type */ 01633 01634 ast_mutex_lock(&rtp->bridge_lock); 01635 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01636 ast_mutex_unlock(&rtp->bridge_lock); 01637 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 1973 of file rtp.c.
Referenced by handle_open_receive_channel_ack_message(), process_sdp(), and setup_rtp_connection().
01974 { 01975 rtp->them.sin_port = them->sin_port; 01976 rtp->them.sin_addr = them->sin_addr; 01977 if (rtp->rtcp) { 01978 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 01979 rtp->rtcp->them.sin_addr = them->sin_addr; 01980 } 01981 rtp->rxseqno = 0; 01982 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 547 of file rtp.c.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00548 { 00549 rtp->rtpholdtimeout = timeout; 00550 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 553 of file rtp.c.
Referenced by create_addr_from_peer(), and sip_alloc().
00554 { 00555 rtp->rtpkeepalive = period; 00556 }
void 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.
Definition at line 1642 of file rtp.c.
Referenced by __oh323_rtp_create(), gtalk_newcall(), process_sdp(), and set_dtmf_payload().
01645 { 01646 unsigned int i; 01647 01648 if (pt < 0 || pt > MAX_RTP_PT) 01649 return; /* bogus payload type */ 01650 01651 ast_mutex_lock(&rtp->bridge_lock); 01652 01653 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01654 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01655 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01656 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01657 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01658 mimeTypes[i].payloadType.isAstFormat && 01659 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01660 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01661 break; 01662 } 01663 } 01664 01665 ast_mutex_unlock(&rtp->bridge_lock); 01666 01667 return; 01668 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 541 of file rtp.c.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00542 { 00543 rtp->rtptimeout = timeout; 00544 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 534 of file rtp.c.
Referenced by handle_response_invite().
00535 { 00536 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00537 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00538 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 600 of file rtp.c.
Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), sip_alloc(), and sip_dtmfmode().
00601 { 00602 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00603 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 605 of file rtp.c.
Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), and sip_alloc().
00606 { 00607 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00608 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 590 of file rtp.c.
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 610 of file rtp.c.
Referenced by gtalk_new().
00611 { 00612 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00613 }
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 1964 of file rtp.c.
Referenced by __oh323_rtp_create(), and sip_alloc().
01965 { 01966 int res; 01967 01968 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 01969 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 01970 return res; 01971 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2013 of file rtp.c.
Referenced by process_sdp(), setup_rtp_connection(), and stop_media_flows().
02014 { 02015 if (rtp->rtcp && rtp->rtcp->schedid > 0) { 02016 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02017 rtp->rtcp->schedid = -1; 02018 } 02019 02020 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02021 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02022 if (rtp->rtcp) { 02023 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02024 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02025 } 02026 02027 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02028 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Definition at line 402 of file rtp.c.
Referenced by gtalk_update_stun().
00403 { 00404 struct stun_header *req; 00405 unsigned char reqdata[1024]; 00406 int reqlen, reqleft; 00407 struct stun_attr *attr; 00408 00409 req = (struct stun_header *)reqdata; 00410 stun_req_id(req); 00411 reqlen = 0; 00412 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00413 req->msgtype = 0; 00414 req->msglen = 0; 00415 attr = (struct stun_attr *)req->ies; 00416 if (username) 00417 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00418 req->msglen = htons(reqlen); 00419 req->msgtype = htons(STUN_BINDREQ); 00420 stun_send(rtp->s, suggestion, req); 00421 }
Definition at line 2692 of file rtp.c.
Referenced by gtalk_write(), mgcp_write(), oh323_write(), sip_write(), and skinny_write().
02693 { 02694 struct ast_frame *f; 02695 int codec; 02696 int hdrlen = 12; 02697 int subclass; 02698 02699 02700 /* If we have no peer, return immediately */ 02701 if (!rtp->them.sin_addr.s_addr) 02702 return 0; 02703 02704 /* If there is no data length, return immediately */ 02705 if (!_f->datalen) 02706 return 0; 02707 02708 /* Make sure we have enough space for RTP header */ 02709 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02710 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02711 return -1; 02712 } 02713 02714 subclass = _f->subclass; 02715 if (_f->frametype == AST_FRAME_VIDEO) 02716 subclass &= ~0x1; 02717 02718 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02719 if (codec < 0) { 02720 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02721 return -1; 02722 } 02723 02724 if (rtp->lasttxformat != subclass) { 02725 /* New format, reset the smoother */ 02726 if (option_debug) 02727 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02728 rtp->lasttxformat = subclass; 02729 if (rtp->smoother) 02730 ast_smoother_free(rtp->smoother); 02731 rtp->smoother = NULL; 02732 } 02733 02734 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX) { 02735 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02736 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02737 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02738 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)); 02739 return -1; 02740 } 02741 if (fmt.flags) 02742 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02743 if (option_debug) 02744 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)); 02745 } 02746 } 02747 if (rtp->smoother) { 02748 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02749 ast_smoother_feed_be(rtp->smoother, _f); 02750 } else { 02751 ast_smoother_feed(rtp->smoother, _f); 02752 } 02753 02754 while((f = ast_smoother_read(rtp->smoother)) && (f->data)) 02755 ast_rtp_raw_write(rtp, f, codec); 02756 } else { 02757 /* Don't buffer outgoing frames; send them one-per-packet: */ 02758 if (_f->offset < hdrlen) { 02759 f = ast_frdup(_f); 02760 } else { 02761 f = _f; 02762 } 02763 if (f->data) 02764 ast_rtp_raw_write(rtp, f, codec); 02765 if (f != _f) 02766 ast_frfree(f); 02767 } 02768 02769 return 0; 02770 }
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 2800 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_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, 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_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, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
02801 { 02802 struct ast_frame *fr = NULL; 02803 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 02804 int oldcodec0 = codec0, oldcodec1 = codec1; 02805 struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,}; 02806 struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,}; 02807 02808 /* Set it up so audio goes directly between the two endpoints */ 02809 02810 /* Test the first channel */ 02811 if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) { 02812 ast_rtp_get_peer(p1, &ac1); 02813 if (vp1) 02814 ast_rtp_get_peer(vp1, &vac1); 02815 } else 02816 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 02817 02818 /* Test the second channel */ 02819 if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) { 02820 ast_rtp_get_peer(p0, &ac0); 02821 if (vp0) 02822 ast_rtp_get_peer(vp0, &vac0); 02823 } else 02824 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name); 02825 02826 /* Now we can unlock and move into our loop */ 02827 ast_channel_unlock(c0); 02828 ast_channel_unlock(c1); 02829 02830 /* Throw our channels into the structure and enter the loop */ 02831 cs[0] = c0; 02832 cs[1] = c1; 02833 cs[2] = NULL; 02834 for (;;) { 02835 /* Check if anything changed */ 02836 if ((c0->tech_pvt != pvt0) || 02837 (c1->tech_pvt != pvt1) || 02838 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 02839 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 02840 if (c0->tech_pvt == pvt0) 02841 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02842 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02843 if (c1->tech_pvt == pvt1) 02844 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02845 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02846 return AST_BRIDGE_RETRY; 02847 } 02848 02849 /* Check if they have changed their address */ 02850 ast_rtp_get_peer(p1, &t1); 02851 if (vp1) 02852 ast_rtp_get_peer(vp1, &vt1); 02853 if (pr1->get_codec) 02854 codec1 = pr1->get_codec(c1); 02855 ast_rtp_get_peer(p0, &t0); 02856 if (vp0) 02857 ast_rtp_get_peer(vp0, &vt0); 02858 if (pr0->get_codec) 02859 codec0 = pr0->get_codec(c0); 02860 if ((inaddrcmp(&t1, &ac1)) || 02861 (vp1 && inaddrcmp(&vt1, &vac1)) || 02862 (codec1 != oldcodec1)) { 02863 if (option_debug > 1) { 02864 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02865 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1); 02866 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 02867 c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1); 02868 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02869 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 02870 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02871 c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 02872 } 02873 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))) 02874 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 02875 memcpy(&ac1, &t1, sizeof(ac1)); 02876 memcpy(&vac1, &vt1, sizeof(vac1)); 02877 oldcodec1 = codec1; 02878 } 02879 if ((inaddrcmp(&t0, &ac0)) || 02880 (vp0 && inaddrcmp(&vt0, &vac0))) { 02881 if (option_debug > 1) { 02882 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 02883 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0); 02884 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 02885 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 02886 } 02887 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))) 02888 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 02889 memcpy(&ac0, &t0, sizeof(ac0)); 02890 memcpy(&vac0, &vt0, sizeof(vac0)); 02891 oldcodec0 = codec0; 02892 } 02893 02894 /* Wait for frame to come in on the channels */ 02895 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 02896 if (!timeoutms) { 02897 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02898 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02899 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02900 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02901 return AST_BRIDGE_RETRY; 02902 } 02903 if (option_debug) 02904 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 02905 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 02906 break; 02907 continue; 02908 } 02909 fr = ast_read(who); 02910 other = (who == c0) ? c1 : c0; 02911 if (!fr || ((fr->frametype == AST_FRAME_DTMF) && 02912 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 02913 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 02914 /* Break out of bridge */ 02915 *fo = fr; 02916 *rc = who; 02917 if (option_debug) 02918 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 02919 if (c0->tech_pvt == pvt0) 02920 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02921 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02922 if (c1->tech_pvt == pvt1) 02923 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02924 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02925 return AST_BRIDGE_COMPLETE; 02926 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02927 if ((fr->subclass == AST_CONTROL_HOLD) || 02928 (fr->subclass == AST_CONTROL_UNHOLD) || 02929 (fr->subclass == AST_CONTROL_VIDUPDATE)) { 02930 if (fr->subclass == AST_CONTROL_HOLD) { 02931 /* If we someone went on hold we want the other side to reinvite back to us */ 02932 if (who == c0) 02933 pr1->set_rtp_peer(c1, NULL, NULL, 0, 0); 02934 else 02935 pr0->set_rtp_peer(c0, NULL, NULL, 0, 0); 02936 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 02937 /* If they went off hold they should go back to being direct */ 02938 if (who == c0) 02939 pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)); 02940 else 02941 pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)); 02942 } 02943 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 02944 ast_frfree(fr); 02945 } else { 02946 *fo = fr; 02947 *rc = who; 02948 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 02949 return AST_BRIDGE_COMPLETE; 02950 } 02951 } else { 02952 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 02953 (fr->frametype == AST_FRAME_DTMF) || 02954 (fr->frametype == AST_FRAME_VOICE) || 02955 (fr->frametype == AST_FRAME_VIDEO) || 02956 (fr->frametype == AST_FRAME_IMAGE) || 02957 (fr->frametype == AST_FRAME_HTML) || 02958 (fr->frametype == AST_FRAME_MODEM) || 02959 (fr->frametype == AST_FRAME_TEXT)) { 02960 ast_write(other, fr); 02961 } 02962 ast_frfree(fr); 02963 } 02964 /* Swap priority */ 02965 cs[2] = cs[0]; 02966 cs[0] = cs[1]; 02967 cs[1] = cs[2]; 02968 } 02969 02970 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 02971 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 02972 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 02973 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 02974 02975 return AST_BRIDGE_FAILED; 02976 }
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 3074 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_clear_flag, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, 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_frame::data, ast_frame::datalen, FLAG_P2P_SENT_MARK, ast_frame::frametype, LOG_DEBUG, LOG_NOTICE, ast_channel::masq, ast_channel::masqr, option_debug, p2p_callback_disable(), p2p_callback_enable(), p2p_set_bridge(), ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by ast_rtp_bridge().
03075 { 03076 struct ast_frame *fr = NULL; 03077 struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, }; 03078 int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1}; 03079 int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL}; 03080 int p0_callback = 0, p1_callback = 0; 03081 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03082 03083 /* Okay, setup each RTP structure to do P2P forwarding */ 03084 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03085 p2p_set_bridge(p0, p1); 03086 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03087 p2p_set_bridge(p1, p0); 03088 03089 /* Activate callback modes if possible */ 03090 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03091 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03092 03093 /* Now let go of the channel locks and be on our way */ 03094 ast_channel_unlock(c0); 03095 ast_channel_unlock(c1); 03096 03097 /* Go into a loop forwarding frames until we don't need to anymore */ 03098 cs[0] = c0; 03099 cs[1] = c1; 03100 cs[2] = NULL; 03101 for (;;) { 03102 /* Check if anything changed */ 03103 if ((c0->tech_pvt != pvt0) || 03104 (c1->tech_pvt != pvt1) || 03105 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 03106 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 03107 if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) 03108 ast_frfree(fr); 03109 if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) 03110 ast_frfree(fr); 03111 res = AST_BRIDGE_RETRY; 03112 break; 03113 } 03114 /* Wait on a channel to feed us a frame */ 03115 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { 03116 if (!timeoutms) { 03117 res = AST_BRIDGE_RETRY; 03118 break; 03119 } 03120 if (option_debug) 03121 ast_log(LOG_NOTICE, "Ooh, empty read...\n"); 03122 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 03123 break; 03124 continue; 03125 } 03126 /* Read in frame from channel */ 03127 fr = ast_read(who); 03128 other = (who == c0) ? c1 : c0; 03129 /* Dependong on the frame we may need to break out of our bridge */ 03130 if (!fr || ((fr->frametype == AST_FRAME_DTMF) && 03131 ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) | 03132 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) { 03133 /* Record received frame and who */ 03134 *fo = fr; 03135 *rc = who; 03136 if (option_debug) 03137 ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup"); 03138 res = AST_BRIDGE_COMPLETE; 03139 break; 03140 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03141 if ((fr->subclass == AST_CONTROL_HOLD) || 03142 (fr->subclass == AST_CONTROL_UNHOLD) || 03143 (fr->subclass == AST_CONTROL_VIDUPDATE)) { 03144 /* If we are going on hold, then break callback mode and P2P bridging */ 03145 if (fr->subclass == AST_CONTROL_HOLD) { 03146 if (p0_callback) 03147 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03148 if (p1_callback) 03149 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03150 p2p_set_bridge(p0, NULL); 03151 p2p_set_bridge(p1, NULL); 03152 } else if (fr->subclass == AST_CONTROL_UNHOLD) { 03153 /* If we are off hold, then go back to callback mode and P2P bridging */ 03154 ast_clear_flag(p0, FLAG_P2P_SENT_MARK); 03155 p2p_set_bridge(p0, p1); 03156 ast_clear_flag(p1, FLAG_P2P_SENT_MARK); 03157 p2p_set_bridge(p1, p0); 03158 p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]); 03159 p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]); 03160 } 03161 ast_indicate_data(other, fr->subclass, fr->data, fr->datalen); 03162 ast_frfree(fr); 03163 } else { 03164 *fo = fr; 03165 *rc = who; 03166 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name); 03167 res = AST_BRIDGE_COMPLETE; 03168 break; 03169 } 03170 } else { 03171 if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || 03172 (fr->frametype == AST_FRAME_DTMF) || 03173 (fr->frametype == AST_FRAME_VOICE) || 03174 (fr->frametype == AST_FRAME_VIDEO) || 03175 (fr->frametype == AST_FRAME_IMAGE) || 03176 (fr->frametype == AST_FRAME_HTML) || 03177 (fr->frametype == AST_FRAME_MODEM) || 03178 (fr->frametype == AST_FRAME_TEXT)) { 03179 ast_write(other, fr); 03180 } 03181 03182 ast_frfree(fr); 03183 } 03184 /* Swap priority */ 03185 cs[2] = cs[0]; 03186 cs[0] = cs[1]; 03187 cs[1] = cs[2]; 03188 } 03189 03190 /* If we are totally avoiding the core, then restore our link to it */ 03191 if (p0_callback) 03192 p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]); 03193 if (p1_callback) 03194 p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]); 03195 03196 /* Break out of the direct bridge */ 03197 p2p_set_bridge(p0, NULL); 03198 p2p_set_bridge(p1, NULL); 03199 03200 return res; 03201 }
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 1048 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, 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().
01049 { 01050 int res = 0, payload = 0, bridged_payload = 0, mark; 01051 struct rtpPayloadType rtpPT; 01052 int reconstruct = ntohl(rtpheader[0]); 01053 01054 /* Get fields from packet */ 01055 payload = (reconstruct & 0x7f0000) >> 16; 01056 mark = (((reconstruct & 0x800000) >> 23) != 0); 01057 01058 /* Check what the payload value should be */ 01059 rtpPT = ast_rtp_lookup_pt(rtp, payload); 01060 01061 /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */ 01062 if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF) 01063 return -1; 01064 01065 /* Otherwise adjust bridged payload to match */ 01066 bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code); 01067 01068 /* If the mark bit has not been sent yet... do it now */ 01069 if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) { 01070 mark = 1; 01071 ast_set_flag(rtp, FLAG_P2P_SENT_MARK); 01072 } 01073 01074 /* Reconstruct part of the packet */ 01075 reconstruct &= 0xFF80FFFF; 01076 reconstruct |= (bridged_payload << 16); 01077 reconstruct |= (mark << 23); 01078 rtpheader[0] = htonl(reconstruct); 01079 01080 /* Send the packet back out */ 01081 res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them)); 01082 if (res < 0) { 01083 if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01084 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)); 01085 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01086 if (option_debug || rtpdebug) 01087 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)); 01088 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01089 } 01090 return 0; 01091 } else if (rtp_debug_test_addr(&bridged->them)) 01092 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); 01093 01094 return 0; 01095 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 999 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().
01000 { 01001 struct timeval now; 01002 double transit; 01003 double current_time; 01004 double d; 01005 double dtv; 01006 double prog; 01007 01008 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01009 gettimeofday(&rtp->rxcore, NULL); 01010 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01011 /* map timestamp to a real time */ 01012 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01013 rtp->rxcore.tv_sec -= timestamp / 8000; 01014 rtp->rxcore.tv_usec -= (timestamp % 8000) * 125; 01015 /* Round to 0.1ms for nice, pretty timestamps */ 01016 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01017 if (rtp->rxcore.tv_usec < 0) { 01018 /* Adjust appropriately if necessary */ 01019 rtp->rxcore.tv_usec += 1000000; 01020 rtp->rxcore.tv_sec -= 1; 01021 } 01022 } 01023 01024 gettimeofday(&now,NULL); 01025 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01026 tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000; 01027 tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125; 01028 if (tv->tv_usec >= 1000000) { 01029 tv->tv_usec -= 1000000; 01030 tv->tv_sec += 1; 01031 } 01032 prog = (double)((timestamp-rtp->seedrxts)/8000.); 01033 dtv = (double)rtp->drxcore + (double)(prog); 01034 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01035 transit = current_time - dtv; 01036 d = transit - rtp->rxtransit; 01037 rtp->rxtransit = transit; 01038 if (d<0) 01039 d=-d; 01040 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01041 if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter) 01042 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01043 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01044 rtp->rtcp->minrxjitter = rtp->rxjitter; 01045 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 2120 of file rtp.c.
References ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
02121 { 02122 struct timeval t; 02123 long ms; 02124 if (ast_tvzero(rtp->txcore)) { 02125 rtp->txcore = ast_tvnow(); 02126 /* Round to 20ms for nice, pretty timestamps */ 02127 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 02128 } 02129 /* Use previous txcore if available */ 02130 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 02131 ms = ast_tvdiff_ms(t, rtp->txcore); 02132 if (ms < 0) 02133 ms = 0; 02134 /* Use what we just got for next time */ 02135 rtp->txcore = t; 02136 return (unsigned int) ms; 02137 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static, read] |
Get channel driver interface structure.
Definition at line 1452 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().
01453 { 01454 struct ast_rtp_protocol *cur = NULL; 01455 01456 AST_LIST_LOCK(&protos); 01457 AST_LIST_TRAVERSE(&protos, cur, list) { 01458 if (cur->type == chan->tech->type) 01459 break; 01460 } 01461 AST_LIST_UNLOCK(&protos); 01462 01463 return cur; 01464 }
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 3045 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().
03046 { 03047 ast_channel_lock(chan); 03048 03049 /* Remove the callback from the IO context */ 03050 ast_io_remove(rtp->io, iod[0]); 03051 03052 /* Restore file descriptors */ 03053 chan->fds[0] = fds[0]; 03054 ast_channel_unlock(chan); 03055 03056 /* Restore callback mode if previously used */ 03057 if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) 03058 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 03059 03060 return 0; 03061 }
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 3064 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by bridge_p2p_loop().
03065 { 03066 ast_mutex_lock(&rtp0->bridge_lock); 03067 rtp0->bridged = rtp1; 03068 ast_mutex_unlock(&rtp0->bridge_lock); 03069 03070 return; 03071 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static, read] |
Definition at line 669 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().
00670 { 00671 unsigned int event; 00672 char resp = 0; 00673 struct ast_frame *f = NULL; 00674 event = ntohl(*((unsigned int *)(data))); 00675 event &= 0x001F; 00676 if (option_debug > 2 || rtpdebug) 00677 ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len); 00678 if (event < 10) { 00679 resp = '0' + event; 00680 } else if (event < 11) { 00681 resp = '*'; 00682 } else if (event < 12) { 00683 resp = '#'; 00684 } else if (event < 16) { 00685 resp = 'A' + (event - 12); 00686 } else if (event < 17) { 00687 resp = 'X'; 00688 } 00689 if (rtp->resp && (rtp->resp != resp)) { 00690 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00691 } 00692 rtp->resp = resp; 00693 rtp->dtmfcount = dtmftimeout; 00694 return f; 00695 }
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 708 of file rtp.c.
References AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), 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().
00709 { 00710 unsigned int event; 00711 unsigned int event_end; 00712 unsigned int samples; 00713 char resp = 0; 00714 struct ast_frame *f = NULL; 00715 00716 /* Figure out event, event end, and samples */ 00717 event = ntohl(*((unsigned int *)(data))); 00718 event >>= 24; 00719 event_end = ntohl(*((unsigned int *)(data))); 00720 event_end <<= 8; 00721 event_end >>= 24; 00722 samples = ntohl(*((unsigned int *)(data))); 00723 samples &= 0xFFFF; 00724 00725 /* Print out debug if turned on */ 00726 if (rtpdebug || option_debug > 2) 00727 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00728 00729 /* Figure out what digit was pressed */ 00730 if (event < 10) { 00731 resp = '0' + event; 00732 } else if (event < 11) { 00733 resp = '*'; 00734 } else if (event < 12) { 00735 resp = '#'; 00736 } else if (event < 16) { 00737 resp = 'A' + (event - 12); 00738 } else if (event < 17) { /* Event 16: Hook flash */ 00739 resp = 'X'; 00740 } 00741 00742 if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) { 00743 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 00744 rtp->resp = resp; 00745 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00746 f->len = 0; 00747 rtp->lastevent = timestamp; 00748 } 00749 } else { 00750 if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) { 00751 rtp->resp = resp; 00752 f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN); 00753 } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) { 00754 f = send_dtmf(rtp, AST_FRAME_DTMF_END); 00755 f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */ 00756 rtp->resp = 0; 00757 rtp->lastevent = seqno; 00758 } 00759 } 00760 00761 rtp->dtmfcount = dtmftimeout; 00762 rtp->dtmfsamples = samples; 00763 00764 return f; 00765 }
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 773 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().
00774 { 00775 struct ast_frame *f = NULL; 00776 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00777 totally help us out becuase we don't have an engine to keep it going and we are not 00778 guaranteed to have it every 20ms or anything */ 00779 if (rtpdebug) 00780 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00781 00782 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00783 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00784 ast_inet_ntoa(rtp->them.sin_addr)); 00785 ast_set_flag(rtp, FLAG_3389_WARNING); 00786 } 00787 00788 /* Must have at least one byte */ 00789 if (!len) 00790 return NULL; 00791 if (len < 24) { 00792 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00793 rtp->f.datalen = len - 1; 00794 rtp->f.offset = AST_FRIENDLY_OFFSET; 00795 memcpy(rtp->f.data, data + 1, len - 1); 00796 } else { 00797 rtp->f.data = NULL; 00798 rtp->f.offset = 0; 00799 rtp->f.datalen = 0; 00800 } 00801 rtp->f.frametype = AST_FRAME_CNG; 00802 rtp->f.subclass = data[0] & 0x7f; 00803 rtp->f.datalen = len - 1; 00804 rtp->f.samples = 0; 00805 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00806 f = &rtp->f; 00807 return f; 00808 }
static int rtcp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 655 of file rtp.c.
References rtcpdebugaddr.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), and ast_rtp_destroy().
00656 { 00657 if (rtcpdebug == 0) 00658 return 0; 00659 if (rtcpdebugaddr.sin_addr.s_addr) { 00660 if (((ntohs(rtcpdebugaddr.sin_port) != 0) 00661 && (rtcpdebugaddr.sin_port != addr->sin_port)) 00662 || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00663 return 0; 00664 } 00665 return 1; 00666 }
static int rtcp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3468 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtcp_do_debug_ip(), and rtcpdebugaddr.
03468 { 03469 if (argc != 2) { 03470 if (argc != 4) 03471 return RESULT_SHOWUSAGE; 03472 return rtcp_do_debug_ip(fd, argc, argv); 03473 } 03474 rtcpdebug = 1; 03475 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03476 ast_cli(fd, "RTCP Debugging Enabled\n"); 03477 return RESULT_SUCCESS; 03478 }
static int rtcp_do_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3456 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtcp_do_debug_ip_deprecated(), and rtcpdebugaddr.
03456 { 03457 if (argc != 3) { 03458 if (argc != 5) 03459 return RESULT_SHOWUSAGE; 03460 return rtcp_do_debug_ip_deprecated(fd, argc, argv); 03461 } 03462 rtcpdebug = 1; 03463 memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr)); 03464 ast_cli(fd, "RTCP Debugging Enabled\n"); 03465 return RESULT_SUCCESS; 03466 }
static int rtcp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3413 of file rtp.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtcpdebugaddr.
Referenced by rtcp_do_debug().
03414 { 03415 struct hostent *hp; 03416 struct ast_hostent ahp; 03417 int port = 0; 03418 char *p, *arg; 03419 if (argc != 4) 03420 return RESULT_SHOWUSAGE; 03421 03422 arg = argv[3]; 03423 p = strstr(arg, ":"); 03424 if (p) { 03425 *p = '\0'; 03426 p++; 03427 port = atoi(p); 03428 } 03429 hp = ast_gethostbyname(arg, &ahp); 03430 if (hp == NULL) 03431 return RESULT_SHOWUSAGE; 03432 rtcpdebugaddr.sin_family = AF_INET; 03433 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03434 rtcpdebugaddr.sin_port = htons(port); 03435 if (port == 0) 03436 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03437 else 03438 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03439 rtcpdebug = 1; 03440 return RESULT_SUCCESS; 03441 }
static int rtcp_do_debug_ip_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3383 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().
03384 { 03385 struct hostent *hp; 03386 struct ast_hostent ahp; 03387 int port = 0; 03388 char *p, *arg; 03389 if (argc != 5) 03390 return RESULT_SHOWUSAGE; 03391 03392 arg = argv[4]; 03393 p = strstr(arg, ":"); 03394 if (p) { 03395 *p = '\0'; 03396 p++; 03397 port = atoi(p); 03398 } 03399 hp = ast_gethostbyname(arg, &ahp); 03400 if (hp == NULL) 03401 return RESULT_SHOWUSAGE; 03402 rtcpdebugaddr.sin_family = AF_INET; 03403 memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr)); 03404 rtcpdebugaddr.sin_port = htons(port); 03405 if (port == 0) 03406 ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr)); 03407 else 03408 ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port); 03409 rtcpdebug = 1; 03410 return RESULT_SUCCESS; 03411 }
static int rtcp_do_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3489 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03489 { 03490 if (argc != 2) { 03491 return RESULT_SHOWUSAGE; 03492 } 03493 rtcpstats = 1; 03494 ast_cli(fd, "RTCP Stats Enabled\n"); 03495 return RESULT_SUCCESS; 03496 }
static int rtcp_do_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3480 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03480 { 03481 if (argc != 3) { 03482 return RESULT_SHOWUSAGE; 03483 } 03484 rtcpstats = 1; 03485 ast_cli(fd, "RTCP Stats Enabled\n"); 03486 return RESULT_SUCCESS; 03487 }
static int rtcp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3516 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03517 { 03518 if (argc != 3) 03519 return RESULT_SHOWUSAGE; 03520 rtcpdebug = 0; 03521 ast_cli(fd,"RTCP Debugging Disabled\n"); 03522 return RESULT_SUCCESS; 03523 }
static int rtcp_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3507 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03508 { 03509 if (argc != 4) 03510 return RESULT_SHOWUSAGE; 03511 rtcpdebug = 0; 03512 ast_cli(fd,"RTCP Debugging Disabled\n"); 03513 return RESULT_SUCCESS; 03514 }
static int rtcp_no_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3534 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03535 { 03536 if (argc != 3) 03537 return RESULT_SHOWUSAGE; 03538 rtcpstats = 0; 03539 ast_cli(fd,"RTCP Stats Disabled\n"); 03540 return RESULT_SUCCESS; 03541 }
static int rtcp_no_stats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3525 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03526 { 03527 if (argc != 4) 03528 return RESULT_SHOWUSAGE; 03529 rtcpstats = 0; 03530 ast_cli(fd,"RTCP Stats Disabled\n"); 03531 return RESULT_SUCCESS; 03532 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 642 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().
00643 { 00644 if (rtpdebug == 0) 00645 return 0; 00646 if (rtpdebugaddr.sin_addr.s_addr) { 00647 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00648 && (rtpdebugaddr.sin_port != addr->sin_port)) 00649 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00650 return 0; 00651 } 00652 return 1; 00653 }
static int rtp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3443 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtp_do_debug_ip(), and rtpdebugaddr.
03444 { 03445 if (argc != 2) { 03446 if (argc != 4) 03447 return RESULT_SHOWUSAGE; 03448 return rtp_do_debug_ip(fd, argc, argv); 03449 } 03450 rtpdebug = 1; 03451 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 03452 ast_cli(fd, "RTP Debugging Enabled\n"); 03453 return RESULT_SUCCESS; 03454 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3353 of file rtp.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtpdebugaddr.
Referenced by rtp_do_debug().
03354 { 03355 struct hostent *hp; 03356 struct ast_hostent ahp; 03357 int port = 0; 03358 char *p, *arg; 03359 03360 if (argc != 4) 03361 return RESULT_SHOWUSAGE; 03362 arg = argv[3]; 03363 p = strstr(arg, ":"); 03364 if (p) { 03365 *p = '\0'; 03366 p++; 03367 port = atoi(p); 03368 } 03369 hp = ast_gethostbyname(arg, &ahp); 03370 if (hp == NULL) 03371 return RESULT_SHOWUSAGE; 03372 rtpdebugaddr.sin_family = AF_INET; 03373 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 03374 rtpdebugaddr.sin_port = htons(port); 03375 if (port == 0) 03376 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr)); 03377 else 03378 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port); 03379 rtpdebug = 1; 03380 return RESULT_SUCCESS; 03381 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3498 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03499 { 03500 if (argc != 3) 03501 return RESULT_SHOWUSAGE; 03502 rtpdebug = 0; 03503 ast_cli(fd,"RTP Debugging Disabled\n"); 03504 return RESULT_SUCCESS; 03505 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 1812 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
01813 { 01814 int s; 01815 long flags; 01816 s = socket(AF_INET, SOCK_DGRAM, 0); 01817 if (s > -1) { 01818 flags = fcntl(s, F_GETFL); 01819 fcntl(s, F_SETFL, flags | O_NONBLOCK); 01820 #ifdef SO_NO_CHECK 01821 if (nochecksums) 01822 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 01823 #endif 01824 } 01825 return s; 01826 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 810 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().
00811 { 00812 struct ast_rtp *rtp = cbdata; 00813 struct ast_frame *f; 00814 f = ast_rtp_read(rtp); 00815 if (f) { 00816 if (rtp->callback) 00817 rtp->callback(rtp, f, rtp->data); 00818 } 00819 return 1; 00820 }
static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp, | |
enum ast_frame_type | type | |||
) | [static, read] |
Definition at line 615 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().
00616 { 00617 if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) || 00618 (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00619 if (option_debug) 00620 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr)); 00621 rtp->resp = 0; 00622 rtp->dtmfsamples = 0; 00623 return &ast_null_frame; 00624 } 00625 if (option_debug) 00626 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr)); 00627 if (rtp->resp == 'X') { 00628 rtp->f.frametype = AST_FRAME_CONTROL; 00629 rtp->f.subclass = AST_CONTROL_FLASH; 00630 } else { 00631 rtp->f.frametype = type; 00632 rtp->f.subclass = rtp->resp; 00633 } 00634 rtp->f.datalen = 0; 00635 rtp->f.samples = 0; 00636 rtp->f.mallocd = 0; 00637 rtp->f.src = "RTP"; 00638 return &rtp->f; 00639 00640 }
static const char* stun_attr2str | ( | int | msg | ) | [static] |
Definition at line 299 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().
00300 { 00301 switch(msg) { 00302 case STUN_MAPPED_ADDRESS: 00303 return "Mapped Address"; 00304 case STUN_RESPONSE_ADDRESS: 00305 return "Response Address"; 00306 case STUN_CHANGE_REQUEST: 00307 return "Change Request"; 00308 case STUN_SOURCE_ADDRESS: 00309 return "Source Address"; 00310 case STUN_CHANGED_ADDRESS: 00311 return "Changed Address"; 00312 case STUN_USERNAME: 00313 return "Username"; 00314 case STUN_PASSWORD: 00315 return "Password"; 00316 case STUN_MESSAGE_INTEGRITY: 00317 return "Message Integrity"; 00318 case STUN_ERROR_CODE: 00319 return "Error Code"; 00320 case STUN_UNKNOWN_ATTRIBUTES: 00321 return "Unknown Attributes"; 00322 case STUN_REFLECTED_FROM: 00323 return "Reflected From"; 00324 } 00325 return "Non-RFC3489 Attribute"; 00326 }
static int stun_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3543 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03544 { 03545 if (argc != 2) { 03546 return RESULT_SHOWUSAGE; 03547 } 03548 stundebug = 1; 03549 ast_cli(fd, "STUN Debugging Enabled\n"); 03550 return RESULT_SUCCESS; 03551 }
static int stun_handle_packet | ( | int | s, | |
struct sockaddr_in * | src, | |||
unsigned char * | data, | |||
size_t | len | |||
) | [static] |
Definition at line 423 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().
00424 { 00425 struct stun_header *resp, *hdr = (struct stun_header *)data; 00426 struct stun_attr *attr; 00427 struct stun_state st; 00428 int ret = STUN_IGNORE; 00429 unsigned char respdata[1024]; 00430 int resplen, respleft; 00431 00432 if (len < sizeof(struct stun_header)) { 00433 if (option_debug) 00434 ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header)); 00435 return -1; 00436 } 00437 if (stundebug) 00438 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen)); 00439 if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) { 00440 if (option_debug) 00441 ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header)); 00442 } else 00443 len = ntohs(hdr->msglen); 00444 data += sizeof(struct stun_header); 00445 memset(&st, 0, sizeof(st)); 00446 while(len) { 00447 if (len < sizeof(struct stun_attr)) { 00448 if (option_debug) 00449 ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr)); 00450 break; 00451 } 00452 attr = (struct stun_attr *)data; 00453 if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) { 00454 if (option_debug) 00455 ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len); 00456 break; 00457 } 00458 if (stun_process_attr(&st, attr)) { 00459 if (option_debug) 00460 ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 00461 break; 00462 } 00463 /* Clear attribute in case previous entry was a string */ 00464 attr->attr = 0; 00465 data += ntohs(attr->len) + sizeof(struct stun_attr); 00466 len -= ntohs(attr->len) + sizeof(struct stun_attr); 00467 } 00468 /* Null terminate any string */ 00469 *data = '\0'; 00470 resp = (struct stun_header *)respdata; 00471 resplen = 0; 00472 respleft = sizeof(respdata) - sizeof(struct stun_header); 00473 resp->id = hdr->id; 00474 resp->msgtype = 0; 00475 resp->msglen = 0; 00476 attr = (struct stun_attr *)resp->ies; 00477 if (!len) { 00478 switch(ntohs(hdr->msgtype)) { 00479 case STUN_BINDREQ: 00480 if (stundebug) 00481 ast_verbose("STUN Bind Request, username: %s\n", 00482 st.username ? st.username : "<none>"); 00483 if (st.username) 00484 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft); 00485 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft); 00486 resp->msglen = htons(resplen); 00487 resp->msgtype = htons(STUN_BINDRESP); 00488 stun_send(s, src, resp); 00489 ret = STUN_ACCEPT; 00490 break; 00491 default: 00492 if (stundebug) 00493 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype))); 00494 } 00495 } 00496 return ret; 00497 }
static const char* stun_msg2str | ( | int | msg | ) | [static] |
Definition at line 280 of file rtp.c.
References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.
Referenced by stun_handle_packet().
00281 { 00282 switch(msg) { 00283 case STUN_BINDREQ: 00284 return "Binding Request"; 00285 case STUN_BINDRESP: 00286 return "Binding Response"; 00287 case STUN_BINDERR: 00288 return "Binding Error Response"; 00289 case STUN_SECREQ: 00290 return "Shared Secret Request"; 00291 case STUN_SECRESP: 00292 return "Shared Secret Response"; 00293 case STUN_SECERR: 00294 return "Shared Secret Error Response"; 00295 } 00296 return "Non-RFC3489 Message"; 00297 }
static int stun_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3553 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03554 { 03555 if (argc != 3) 03556 return RESULT_SHOWUSAGE; 03557 stundebug = 0; 03558 ast_cli(fd, "STUN Debugging Disabled\n"); 03559 return RESULT_SUCCESS; 03560 }
static int stun_process_attr | ( | struct stun_state * | state, | |
struct stun_attr * | attr | |||
) | [static] |
Definition at line 333 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().
00334 { 00335 if (stundebug) 00336 ast_verbose("Found STUN Attribute %s (%04x), length %d\n", 00337 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00338 switch(ntohs(attr->attr)) { 00339 case STUN_USERNAME: 00340 state->username = (const char *) (attr->value); 00341 break; 00342 case STUN_PASSWORD: 00343 state->password = (const char *) (attr->value); 00344 break; 00345 default: 00346 if (stundebug) 00347 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 00348 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 00349 } 00350 return 0; 00351 }
static void stun_req_id | ( | struct stun_header * | req | ) | [static] |
Definition at line 390 of file rtp.c.
References ast_random(), and stun_header::id.
Referenced by ast_rtp_stun_request().
00391 { 00392 int x; 00393 for (x=0;x<4;x++) 00394 req->id.id[x] = ast_random(); 00395 }
static int stun_send | ( | int | s, | |
struct sockaddr_in * | dst, | |||
struct stun_header * | resp | |||
) | [static] |
Definition at line 384 of file rtp.c.
References stun_header::msglen.
Referenced by ast_rtp_stun_request(), and stun_handle_packet().
00385 { 00386 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0, 00387 (struct sockaddr *)dst, sizeof(*dst)); 00388 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 502 of file rtp.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00503 { 00504 unsigned int sec, usec, frac; 00505 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00506 usec = tv.tv_usec; 00507 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00508 *msw = sec; 00509 *lsw = frac; 00510 }
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] |
struct stun_header packed |
Referenced by get_unaligned_uint16(), get_unaligned_uint32(), put_unaligned_uint16(), and put_unaligned_uint32().
struct rtpPayloadType payloadType |
Definition at line 1327 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 1328 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(), misdn_cfg_get(), misdn_cfg_get_config_string(), parse_information(), parse_setup(), sla_load_config(), subscription_type2str(), and yyparse().