#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
Go to the source code of this file.
Data Structures | |
struct | ast_rtcp |
Structure defining an RTCP session. More... | |
struct | ast_rtp |
RTP session description. More... | |
struct | frame_list |
struct | rtp_red |
Defines | |
#define | DEFAULT_DTMF_TIMEOUT (150 * (8000 / 1000)) |
#define | DEFAULT_RTP_END 31000 |
#define | DEFAULT_RTP_START 5000 |
#define | FLAG_3389_WARNING (1 << 0) |
#define | FLAG_DTMF_COMPENSATE (1 << 4) |
#define | FLAG_NAT_ACTIVE (3 << 1) |
#define | FLAG_NAT_INACTIVE (0 << 1) |
#define | FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
#define | FLAG_NEED_MARKER_BIT (1 << 3) |
#define | MAX_TIMESTAMP_SKEW 640 |
#define | MAXIMUM_RTP_PORT 65535 |
#define | MINIMUM_RTP_PORT 1024 |
#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 | SQUARE(x) ((x) * (x)) |
#define | ZFONE_PROFILE_ID 0x505a |
Enumerations | |
enum | strict_rtp_state { STRICT_RTP_OPEN = 0, STRICT_RTP_LEARN, STRICT_RTP_CLOSED } |
Functions | |
static void | __reg_module (void) |
static int | __rtp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp) |
static int | __rtp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp) |
static void | __unreg_module (void) |
static unsigned int | ast_rtcp_calc_interval (struct ast_rtp *rtp) |
static struct ast_frame * | ast_rtcp_read (struct ast_rtp_instance *instance) |
static int | ast_rtcp_write (const void *data) |
Write and RTCP packet to the far end. | |
static int | ast_rtcp_write_rr (struct ast_rtp_instance *instance) |
Send RTCP recipient's report. | |
static int | ast_rtcp_write_sr (struct ast_rtp_instance *instance) |
Send RTCP sender's report. | |
static void | ast_rtp_alt_remote_address_set (struct ast_rtp_instance *instance, struct ast_sockaddr *addr) |
static void | ast_rtp_change_source (struct ast_rtp_instance *instance) |
static int | ast_rtp_destroy (struct ast_rtp_instance *instance) |
static int | ast_rtp_dtmf_begin (struct ast_rtp_instance *instance, char digit) |
static int | ast_rtp_dtmf_compatible (struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1) |
static int | ast_rtp_dtmf_continuation (struct ast_rtp_instance *instance) |
static int | ast_rtp_dtmf_end (struct ast_rtp_instance *instance, char digit) |
static int | ast_rtp_dtmf_end_with_duration (struct ast_rtp_instance *instance, char digit, unsigned int duration) |
static int | ast_rtp_fd (struct ast_rtp_instance *instance, int rtcp) |
static int | ast_rtp_get_stat (struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat) |
static int | ast_rtp_local_bridge (struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1) |
static int | ast_rtp_new (struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data) |
static void | ast_rtp_prop_set (struct ast_rtp_instance *instance, enum ast_rtp_property property, int value) |
static int | ast_rtp_qos_set (struct ast_rtp_instance *instance, int tos, int cos, const char *desc) |
static int | ast_rtp_raw_write (struct ast_rtp_instance *instance, struct ast_frame *frame, int codec) |
static struct ast_frame * | ast_rtp_read (struct ast_rtp_instance *instance, int rtcp) |
static void | ast_rtp_remote_address_set (struct ast_rtp_instance *instance, struct ast_sockaddr *addr) |
static void | ast_rtp_stop (struct ast_rtp_instance *instance) |
static void | ast_rtp_stun_request (struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username) |
static void | ast_rtp_update_source (struct ast_rtp_instance *instance) |
static int | ast_rtp_write (struct ast_rtp_instance *instance, struct ast_frame *frame) |
static int | bridge_p2p_rtp_write (struct ast_rtp_instance *instance, unsigned int *rtpheader, int len, int hdrlen) |
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_frame * | create_dtmf_frame (struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate) |
static int | create_new_socket (const char *type, int af) |
static char * | handle_cli_rtcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rtcp_set_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rtp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | load_module (void) |
static double | normdev_compute (double normdev, double sample, unsigned int sample_count) |
Calculate normal deviation. | |
static struct ast_frame * | process_cn_rfc3389 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark) |
static struct ast_frame * | process_dtmf_cisco (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark) |
static void | process_dtmf_rfc2833 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark, struct frame_list *frames) |
static struct ast_frame * | red_t140_to_red (struct rtp_red *red) |
static int | red_write (const void *data) |
Write t140 redundacy frame. | |
static int | reload_module (void) |
static int | rtcp_debug_test_addr (struct ast_sockaddr *addr) |
static char * | rtcp_do_debug_ip (struct ast_cli_args *a) |
static int | rtcp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa) |
static int | rtcp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa) |
static int | rtp_debug_test_addr (struct ast_sockaddr *addr) |
static char * | rtp_do_debug_ip (struct ast_cli_args *a) |
static int | rtp_get_rate (format_t subclass) |
static int | rtp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa) |
static int | rtp_red_buffer (struct ast_rtp_instance *instance, struct ast_frame *frame) |
static int | rtp_red_init (struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations) |
static int | rtp_reload (int reload) |
static int | rtp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa) |
static double | stddev_compute (double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count) |
static void | timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RTP Stack" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_rtp_engine | asterisk_rtp_engine |
static struct ast_cli_entry | cli_rtp [] |
static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
ast_srtp_res * | res_srtp |
static int | rtcpdebug |
static struct ast_sockaddr | rtcpdebugaddr |
static int | rtcpinterval = RTCP_DEFAULT_INTERVALMS |
static int | rtcpstats |
static int | rtpdebug |
static struct ast_sockaddr | rtpdebugaddr |
static int | rtpend = DEFAULT_RTP_END |
static int | rtpstart = DEFAULT_RTP_START |
static int | strictrtp |
Definition in file res_rtp_asterisk.c.
#define DEFAULT_DTMF_TIMEOUT (150 * (8000 / 1000)) |
#define DEFAULT_RTP_END 31000 |
Default maximum port number to end allocating RTP ports at
Definition at line 61 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
#define DEFAULT_RTP_START 5000 |
Default port number to start allocating RTP ports from
Definition at line 60 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
#define FLAG_3389_WARNING (1 << 0) |
#define FLAG_DTMF_COMPENSATE (1 << 4) |
Definition at line 106 of file res_rtp_asterisk.c.
#define FLAG_NAT_ACTIVE (3 << 1) |
Definition at line 102 of file res_rtp_asterisk.c.
Referenced by ast_rtp_raw_write(), ast_rtp_read(), and bridge_p2p_rtp_write().
#define FLAG_NAT_INACTIVE (0 << 1) |
Definition at line 103 of file res_rtp_asterisk.c.
Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().
#define FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
Definition at line 104 of file res_rtp_asterisk.c.
Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().
#define FLAG_NEED_MARKER_BIT (1 << 3) |
Definition at line 105 of file res_rtp_asterisk.c.
Referenced by ast_rtp_change_source(), ast_rtp_local_bridge(), ast_rtp_raw_write(), ast_rtp_stop(), ast_rtp_update_source(), and bridge_p2p_rtp_write().
#define MAX_TIMESTAMP_SKEW 640 |
Definition at line 53 of file res_rtp_asterisk.c.
#define MAXIMUM_RTP_PORT 65535 |
Maximum port number to accept
Definition at line 64 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
#define MINIMUM_RTP_PORT 1024 |
Minimum port number to accept
Definition at line 63 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
#define RTCP_DEFAULT_INTERVALMS 5000 |
Default milli-seconds between RTCP reports we send
Definition at line 56 of file res_rtp_asterisk.c.
#define RTCP_MAX_INTERVALMS 60000 |
Max milli-seconds between RTCP reports we send
Definition at line 58 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
#define RTCP_MIN_INTERVALMS 500 |
Min milli-seconds between RTCP reports we send
Definition at line 57 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
#define RTCP_PT_APP 204 |
Definition at line 71 of file res_rtp_asterisk.c.
#define RTCP_PT_BYE 203 |
#define RTCP_PT_FUR 192 |
#define RTCP_PT_RR 201 |
Definition at line 68 of file res_rtp_asterisk.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().
#define RTCP_PT_SDES 202 |
Definition at line 69 of file res_rtp_asterisk.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr().
#define RTCP_PT_SR 200 |
Definition at line 67 of file res_rtp_asterisk.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
#define RTP_MTU 1200 |
Definition at line 73 of file res_rtp_asterisk.c.
#define RTP_SEQ_MOD (1<<16) |
A sequence number can't be more than 16 bits
Definition at line 55 of file res_rtp_asterisk.c.
Referenced by ast_rtp_read().
#define SQUARE | ( | x | ) | ((x) * (x)) |
Referenced by stddev_compute().
#define ZFONE_PROFILE_ID 0x505a |
Definition at line 77 of file res_rtp_asterisk.c.
enum strict_rtp_state |
STRICT_RTP_OPEN | |
STRICT_RTP_LEARN | No RTP packets should be dropped, all sources accepted |
STRICT_RTP_CLOSED | Accept next packet as source |
Definition at line 95 of file res_rtp_asterisk.c.
00095 { 00096 STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */ 00097 STRICT_RTP_LEARN, /*! Accept next packet as source */ 00098 STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */ 00099 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 2825 of file res_rtp_asterisk.c.
static int __rtp_recvfrom | ( | struct ast_rtp_instance * | instance, | |
void * | buf, | |||
size_t | size, | |||
int | flags, | |||
struct ast_sockaddr * | sa, | |||
int | rtcp | |||
) | [static] |
Definition at line 320 of file res_rtp_asterisk.c.
References ast_recvfrom(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), len(), res_srtp, ast_srtp::rtp, and ast_srtp_res::unprotect.
Referenced by rtcp_recvfrom(), and rtp_recvfrom().
00321 { 00322 int len; 00323 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00324 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance); 00325 00326 if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) { 00327 return len; 00328 } 00329 00330 if (res_srtp && srtp && res_srtp->unprotect(srtp, buf, &len, rtcp) < 0) { 00331 return -1; 00332 } 00333 00334 return len; 00335 }
static int __rtp_sendto | ( | struct ast_rtp_instance * | instance, | |
void * | buf, | |||
size_t | size, | |||
int | flags, | |||
struct ast_sockaddr * | sa, | |||
int | rtcp | |||
) | [static] |
Definition at line 347 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_sendto(), len(), ast_srtp_res::protect, res_srtp, and ast_srtp::rtp.
Referenced by rtcp_sendto(), and rtp_sendto().
00348 { 00349 int len = size; 00350 void *temp = buf; 00351 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00352 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance); 00353 00354 if (res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) { 00355 return -1; 00356 } 00357 00358 return ast_sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa); 00359 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 2825 of file res_rtp_asterisk.c.
static unsigned int ast_rtcp_calc_interval | ( | struct ast_rtp * | rtp | ) | [static] |
Definition at line 376 of file res_rtp_asterisk.c.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
00377 { 00378 unsigned int interval; 00379 /*! \todo XXX Do a more reasonable calculation on this one 00380 * Look in RFC 3550 Section A.7 for an example*/ 00381 interval = rtcpinterval; 00382 return interval; 00383 }
static struct ast_frame* ast_rtcp_read | ( | struct ast_rtp_instance * | instance | ) | [static] |
Definition at line 1640 of file res_rtp_asterisk.c.
References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_log(), ast_null_frame, ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_NAT, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_verbose, ast_frame::datalen, errno, EVENT_FLAG_REPORTING, ast_rtp::f, f, ast_frame::frametype, ast_frame_subclass::integer, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, normdev_compute(), ast_rtcp::normdevrtt, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_jitter_count, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtcp_info, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, rtcp_recvfrom(), rtpdebug, ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::rxlsr, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, stddev_compute(), ast_rtcp::stdevrtt, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().
Referenced by ast_rtp_read().
01641 { 01642 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01643 struct ast_sockaddr addr; 01644 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 01645 unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 01646 int res, packetwords, position = 0; 01647 struct ast_frame *f = &ast_null_frame; 01648 01649 /* Read in RTCP data from the socket */ 01650 if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET, 01651 sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 01652 0, &addr)) < 0) { 01653 ast_assert(errno != EBADF); 01654 if (errno != EAGAIN) { 01655 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 01656 return NULL; 01657 } 01658 return &ast_null_frame; 01659 } 01660 01661 packetwords = res / 4; 01662 01663 if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) { 01664 /* Send to whoever sent to us */ 01665 if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) { 01666 ast_sockaddr_copy(&rtp->rtcp->them, &addr); 01667 if (option_debug || rtpdebug) 01668 ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n", 01669 ast_sockaddr_stringify(&rtp->rtcp->them)); 01670 } 01671 } 01672 01673 ast_debug(1, "Got RTCP report of %d bytes\n", res); 01674 01675 while (position < packetwords) { 01676 int i, pt, rc; 01677 unsigned int length, dlsr, lsr, msw, lsw, comp; 01678 struct timeval now; 01679 double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current; 01680 uint64_t rtt = 0; 01681 01682 i = position; 01683 length = ntohl(rtcpheader[i]); 01684 pt = (length & 0xff0000) >> 16; 01685 rc = (length & 0x1f000000) >> 24; 01686 length &= 0xffff; 01687 01688 if ((i + length) > packetwords) { 01689 if (option_debug || rtpdebug) 01690 ast_log(LOG_DEBUG, "RTCP Read too short\n"); 01691 return &ast_null_frame; 01692 } 01693 01694 if (rtcp_debug_test_addr(&addr)) { 01695 ast_verbose("\n\nGot RTCP from %s\n", 01696 ast_sockaddr_stringify(&addr)); 01697 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 01698 ast_verbose("Reception reports: %d\n", rc); 01699 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 01700 } 01701 01702 i += 2; /* Advance past header and ssrc */ 01703 if (rc == 0 && pt == RTCP_PT_RR) { /* We're receiving a receiver report with no reports, which is ok */ 01704 position += (length + 1); 01705 continue; 01706 } 01707 01708 switch (pt) { 01709 case RTCP_PT_SR: 01710 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 01711 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 01712 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 01713 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 01714 01715 if (rtcp_debug_test_addr(&addr)) { 01716 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 01717 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 01718 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 01719 } 01720 i += 5; 01721 if (rc < 1) 01722 break; 01723 /* Intentional fall through */ 01724 case RTCP_PT_RR: 01725 /* Don't handle multiple reception reports (rc > 1) yet */ 01726 /* Calculate RTT per RFC */ 01727 gettimeofday(&now, NULL); 01728 timeval2ntp(now, &msw, &lsw); 01729 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 01730 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 01731 lsr = ntohl(rtcpheader[i + 4]); 01732 dlsr = ntohl(rtcpheader[i + 5]); 01733 rtt = comp - lsr - dlsr; 01734 01735 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 01736 sess->ee_delay = (eedelay * 1000) / 65536; */ 01737 if (rtt < 4294) { 01738 rtt = (rtt * 1000000) >> 16; 01739 } else { 01740 rtt = (rtt * 1000) >> 16; 01741 rtt *= 1000; 01742 } 01743 rtt = rtt / 1000.; 01744 rttsec = rtt / 1000.; 01745 rtp->rtcp->rtt = rttsec; 01746 01747 if (comp - dlsr >= lsr) { 01748 rtp->rtcp->accumulated_transit += rttsec; 01749 01750 if (rtp->rtcp->rtt_count == 0) 01751 rtp->rtcp->minrtt = rttsec; 01752 01753 if (rtp->rtcp->maxrtt<rttsec) 01754 rtp->rtcp->maxrtt = rttsec; 01755 if (rtp->rtcp->minrtt>rttsec) 01756 rtp->rtcp->minrtt = rttsec; 01757 01758 normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count); 01759 01760 rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count); 01761 01762 rtp->rtcp->normdevrtt = normdevrtt_current; 01763 01764 rtp->rtcp->rtt_count++; 01765 } else if (rtcp_debug_test_addr(&addr)) { 01766 ast_verbose("Internal RTCP NTP clock skew detected: " 01767 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 01768 "diff=%d\n", 01769 lsr, comp, dlsr, dlsr / 65536, 01770 (dlsr % 65536) * 1000 / 65536, 01771 dlsr - (comp - lsr)); 01772 } 01773 } 01774 01775 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 01776 reported_jitter = (double) rtp->rtcp->reported_jitter; 01777 01778 if (rtp->rtcp->reported_jitter_count == 0) 01779 rtp->rtcp->reported_minjitter = reported_jitter; 01780 01781 if (reported_jitter < rtp->rtcp->reported_minjitter) 01782 rtp->rtcp->reported_minjitter = reported_jitter; 01783 01784 if (reported_jitter > rtp->rtcp->reported_maxjitter) 01785 rtp->rtcp->reported_maxjitter = reported_jitter; 01786 01787 reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count); 01788 01789 rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count); 01790 01791 rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current; 01792 01793 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 01794 01795 reported_lost = (double) rtp->rtcp->reported_lost; 01796 01797 /* using same counter as for jitter */ 01798 if (rtp->rtcp->reported_jitter_count == 0) 01799 rtp->rtcp->reported_minlost = reported_lost; 01800 01801 if (reported_lost < rtp->rtcp->reported_minlost) 01802 rtp->rtcp->reported_minlost = reported_lost; 01803 01804 if (reported_lost > rtp->rtcp->reported_maxlost) 01805 rtp->rtcp->reported_maxlost = reported_lost; 01806 reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count); 01807 01808 rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count); 01809 01810 rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current; 01811 01812 rtp->rtcp->reported_jitter_count++; 01813 01814 if (rtcp_debug_test_addr(&addr)) { 01815 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 01816 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 01817 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 01818 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 01819 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 01820 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 01821 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 01822 if (rtt) 01823 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 01824 } 01825 if (rtt) { 01826 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s\r\n" 01827 "PT: %d(%s)\r\n" 01828 "ReceptionReports: %d\r\n" 01829 "SenderSSRC: %u\r\n" 01830 "FractionLost: %ld\r\n" 01831 "PacketsLost: %d\r\n" 01832 "HighestSequence: %ld\r\n" 01833 "SequenceNumberCycles: %ld\r\n" 01834 "IAJitter: %u\r\n" 01835 "LastSR: %lu.%010lu\r\n" 01836 "DLSR: %4.4f(sec)\r\n" 01837 "RTT: %llu(sec)\r\n", 01838 ast_sockaddr_stringify(&addr), 01839 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01840 rc, 01841 rtcpheader[i + 1], 01842 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01843 rtp->rtcp->reported_lost, 01844 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01845 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01846 rtp->rtcp->reported_jitter, 01847 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01848 ntohl(rtcpheader[i + 5])/65536.0, 01849 (unsigned long long)rtt); 01850 } else { 01851 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s\r\n" 01852 "PT: %d(%s)\r\n" 01853 "ReceptionReports: %d\r\n" 01854 "SenderSSRC: %u\r\n" 01855 "FractionLost: %ld\r\n" 01856 "PacketsLost: %d\r\n" 01857 "HighestSequence: %ld\r\n" 01858 "SequenceNumberCycles: %ld\r\n" 01859 "IAJitter: %u\r\n" 01860 "LastSR: %lu.%010lu\r\n" 01861 "DLSR: %4.4f(sec)\r\n", 01862 ast_sockaddr_stringify(&addr), 01863 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01864 rc, 01865 rtcpheader[i + 1], 01866 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01867 rtp->rtcp->reported_lost, 01868 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01869 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01870 rtp->rtcp->reported_jitter, 01871 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, 01872 ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01873 ntohl(rtcpheader[i + 5])/65536.0); 01874 } 01875 break; 01876 case RTCP_PT_FUR: 01877 if (rtcp_debug_test_addr(&addr)) 01878 ast_verbose("Received an RTCP Fast Update Request\n"); 01879 rtp->f.frametype = AST_FRAME_CONTROL; 01880 rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE; 01881 rtp->f.datalen = 0; 01882 rtp->f.samples = 0; 01883 rtp->f.mallocd = 0; 01884 rtp->f.src = "RTP"; 01885 f = &rtp->f; 01886 break; 01887 case RTCP_PT_SDES: 01888 if (rtcp_debug_test_addr(&addr)) 01889 ast_verbose("Received an SDES from %s\n", 01890 ast_sockaddr_stringify(&rtp->rtcp->them)); 01891 break; 01892 case RTCP_PT_BYE: 01893 if (rtcp_debug_test_addr(&addr)) 01894 ast_verbose("Received a BYE from %s\n", 01895 ast_sockaddr_stringify(&rtp->rtcp->them)); 01896 break; 01897 default: 01898 ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s\n", 01899 pt, ast_sockaddr_stringify(&rtp->rtcp->them)); 01900 break; 01901 } 01902 position += (length + 1); 01903 } 01904 01905 rtp->rtcp->rtcp_info = 1; 01906 01907 return f; 01908 }
static int ast_rtcp_write | ( | const void * | data | ) | [static] |
Write and RTCP packet to the far end.
Definition at line 1017 of file res_rtp_asterisk.c.
References ast_rtcp_write_rr(), ast_rtcp_write_sr(), ast_rtp_instance_get_data(), ast_rtcp::lastsrtxcount, ast_rtp::rtcp, and ast_rtp::txcount.
Referenced by ast_rtp_raw_write(), and ast_rtp_read().
01018 { 01019 struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data; 01020 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01021 int res; 01022 01023 if (!rtp || !rtp->rtcp) 01024 return 0; 01025 01026 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 01027 res = ast_rtcp_write_sr(instance); 01028 else 01029 res = ast_rtcp_write_rr(instance); 01030 01031 return res; 01032 }
static int ast_rtcp_write_rr | ( | struct ast_rtp_instance * | instance | ) | [static] |
Send RTCP recipient's report.
Definition at line 786 of file res_rtp_asterisk.c.
References ast_log(), ast_rtp_instance_get_data(), AST_SCHED_DEL, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, ast_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, len(), LOG_ERROR, ast_rtcp::maxrxlost, ast_rtcp::minrxlost, normdev_compute(), ast_rtcp::normdev_rxlost, ast_rtcp::received_prior, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_RR, RTCP_PT_SDES, rtcp_sendto(), ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlost, ast_rtcp::rxlost_count, ast_rtcp::rxlsr, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::ssrc, stddev_compute(), ast_rtcp::stdev_rxlost, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, and timersub().
Referenced by ast_rtcp_write().
00787 { 00788 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00789 int res; 00790 int len = 32; 00791 unsigned int lost; 00792 unsigned int extended; 00793 unsigned int expected; 00794 unsigned int expected_interval; 00795 unsigned int received_interval; 00796 int lost_interval; 00797 struct timeval now; 00798 unsigned int *rtcpheader; 00799 char bdata[1024]; 00800 struct timeval dlsr; 00801 int fraction; 00802 00803 double rxlost_current; 00804 00805 if (!rtp || !rtp->rtcp) 00806 return 0; 00807 00808 if (ast_sockaddr_isnull(&rtp->rtcp->them)) { 00809 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n"); 00810 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 00811 return 0; 00812 } 00813 00814 extended = rtp->cycles + rtp->lastrxseqno; 00815 expected = extended - rtp->seedrxseqno + 1; 00816 lost = expected - rtp->rxcount; 00817 expected_interval = expected - rtp->rtcp->expected_prior; 00818 rtp->rtcp->expected_prior = expected; 00819 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 00820 rtp->rtcp->received_prior = rtp->rxcount; 00821 lost_interval = expected_interval - received_interval; 00822 00823 if (lost_interval <= 0) 00824 rtp->rtcp->rxlost = 0; 00825 else rtp->rtcp->rxlost = rtp->rtcp->rxlost; 00826 if (rtp->rtcp->rxlost_count == 0) 00827 rtp->rtcp->minrxlost = rtp->rtcp->rxlost; 00828 if (lost_interval < rtp->rtcp->minrxlost) 00829 rtp->rtcp->minrxlost = rtp->rtcp->rxlost; 00830 if (lost_interval > rtp->rtcp->maxrxlost) 00831 rtp->rtcp->maxrxlost = rtp->rtcp->rxlost; 00832 00833 rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count); 00834 rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count); 00835 rtp->rtcp->normdev_rxlost = rxlost_current; 00836 rtp->rtcp->rxlost_count++; 00837 00838 if (expected_interval == 0 || lost_interval <= 0) 00839 fraction = 0; 00840 else 00841 fraction = (lost_interval << 8) / expected_interval; 00842 gettimeofday(&now, NULL); 00843 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 00844 rtcpheader = (unsigned int *)bdata; 00845 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 00846 rtcpheader[1] = htonl(rtp->ssrc); 00847 rtcpheader[2] = htonl(rtp->themssrc); 00848 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 00849 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 00850 rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 00851 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 00852 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 00853 00854 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 00855 it can change mid call, and SDES can't) */ 00856 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 00857 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 00858 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 00859 len += 12; 00860 00861 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them); 00862 00863 if (res < 0) { 00864 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 00865 /* Remove the scheduler */ 00866 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 00867 return 0; 00868 } 00869 00870 rtp->rtcp->rr_count++; 00871 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 00872 ast_verbose("\n* Sending RTCP RR to %s\n" 00873 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 00874 " IA jitter: %.4f\n" 00875 " Their last SR: %u\n" 00876 " DLSR: %4.4f (sec)\n\n", 00877 ast_sockaddr_stringify(&rtp->rtcp->them), 00878 rtp->ssrc, rtp->themssrc, fraction, lost, 00879 rtp->rxjitter, 00880 rtp->rtcp->themrxlsr, 00881 (double)(ntohl(rtcpheader[7])/65536.0)); 00882 } 00883 00884 return res; 00885 }
static int ast_rtcp_write_sr | ( | struct ast_rtp_instance * | instance | ) | [static] |
Send RTCP sender's report.
Definition at line 888 of file res_rtp_asterisk.c.
References ast_log(), ast_rtp_instance_get_data(), AST_SCHED_DEL, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, ast_rtp::cycles, errno, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len(), LOG_ERROR, manager_event, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_SDES, RTCP_PT_SR, rtcp_sendto(), ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, timersub(), timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.
Referenced by ast_rtcp_write().
00889 { 00890 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00891 int res; 00892 int len = 0; 00893 struct timeval now; 00894 unsigned int now_lsw; 00895 unsigned int now_msw; 00896 unsigned int *rtcpheader; 00897 unsigned int lost; 00898 unsigned int extended; 00899 unsigned int expected; 00900 unsigned int expected_interval; 00901 unsigned int received_interval; 00902 int lost_interval; 00903 int fraction; 00904 struct timeval dlsr; 00905 char bdata[512]; 00906 00907 if (!rtp || !rtp->rtcp) 00908 return 0; 00909 00910 if (ast_sockaddr_isnull(&rtp->rtcp->them)) { /* This'll stop rtcp for this rtp session */ 00911 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 00912 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 00913 return 0; 00914 } 00915 00916 gettimeofday(&now, NULL); 00917 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 00918 rtcpheader = (unsigned int *)bdata; 00919 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 00920 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 00921 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 00922 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 00923 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 00924 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 00925 len += 28; 00926 00927 extended = rtp->cycles + rtp->lastrxseqno; 00928 expected = extended - rtp->seedrxseqno + 1; 00929 if (rtp->rxcount > expected) 00930 expected += rtp->rxcount - expected; 00931 lost = expected - rtp->rxcount; 00932 expected_interval = expected - rtp->rtcp->expected_prior; 00933 rtp->rtcp->expected_prior = expected; 00934 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 00935 rtp->rtcp->received_prior = rtp->rxcount; 00936 lost_interval = expected_interval - received_interval; 00937 if (expected_interval == 0 || lost_interval <= 0) 00938 fraction = 0; 00939 else 00940 fraction = (lost_interval << 8) / expected_interval; 00941 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 00942 rtcpheader[7] = htonl(rtp->themssrc); 00943 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 00944 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 00945 rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.)); 00946 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 00947 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 00948 len += 24; 00949 00950 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 00951 00952 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 00953 /* it can change mid call, and SDES can't) */ 00954 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 00955 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 00956 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 00957 len += 12; 00958 00959 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them); 00960 if (res < 0) { 00961 ast_log(LOG_ERROR, "RTCP SR transmission error to %s, rtcp halted %s\n", 00962 ast_sockaddr_stringify(&rtp->rtcp->them), 00963 strerror(errno)); 00964 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 00965 return 0; 00966 } 00967 00968 /* FIXME Don't need to get a new one */ 00969 gettimeofday(&rtp->rtcp->txlsr, NULL); 00970 rtp->rtcp->sr_count++; 00971 00972 rtp->rtcp->lastsrtxcount = rtp->txcount; 00973 00974 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 00975 ast_verbose("* Sent RTCP SR to %s\n", ast_sockaddr_stringify(&rtp->rtcp->them)); 00976 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 00977 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 00978 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 00979 ast_verbose(" Sent packets: %u\n", rtp->txcount); 00980 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 00981 ast_verbose(" Report block:\n"); 00982 ast_verbose(" Fraction lost: %u\n", fraction); 00983 ast_verbose(" Cumulative loss: %u\n", lost); 00984 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 00985 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 00986 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 00987 } 00988 manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s\r\n" 00989 "OurSSRC: %u\r\n" 00990 "SentNTP: %u.%010u\r\n" 00991 "SentRTP: %u\r\n" 00992 "SentPackets: %u\r\n" 00993 "SentOctets: %u\r\n" 00994 "ReportBlock:\r\n" 00995 "FractionLost: %u\r\n" 00996 "CumulativeLoss: %u\r\n" 00997 "IAJitter: %.4f\r\n" 00998 "TheirLastSR: %u\r\n" 00999 "DLSR: %4.4f (sec)\r\n", 01000 ast_sockaddr_stringify(&rtp->rtcp->them), 01001 rtp->ssrc, 01002 (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096, 01003 rtp->lastts, 01004 rtp->txcount, 01005 rtp->txoctetcount, 01006 fraction, 01007 lost, 01008 rtp->rxjitter, 01009 rtp->rtcp->themrxlsr, 01010 (double)(ntohl(rtcpheader[12])/65536.0)); 01011 return res; 01012 }
static void ast_rtp_alt_remote_address_set | ( | struct ast_rtp_instance * | instance, | |
struct ast_sockaddr * | addr | |||
) | [static] |
Definition at line 2408 of file res_rtp_asterisk.c.
References ast_rtp::alt_rtp_address, ast_rtp_instance_get_data(), and ast_sockaddr_copy().
02409 { 02410 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02411 02412 /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving 02413 * RTCP from an "unexpected" source 02414 */ 02415 ast_sockaddr_copy(&rtp->alt_rtp_address, addr); 02416 02417 return; 02418 }
static void ast_rtp_change_source | ( | struct ast_rtp_instance * | instance | ) | [static] |
Definition at line 730 of file res_rtp_asterisk.c.
References ast_debug, ast_random(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_set_flag, ast_srtp_res::change_source, FLAG_NEED_MARKER_BIT, res_srtp, and ast_srtp::rtp.
00731 { 00732 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00733 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance); 00734 unsigned int ssrc = ast_random(); 00735 00736 if (!rtp->lastts) { 00737 ast_debug(3, "Not changing SSRC since we haven't sent any RTP yet\n"); 00738 return; 00739 } 00740 00741 /* We simply set this bit so that the next packet sent will have the marker bit turned on */ 00742 ast_set_flag(rtp, FLAG_NEED_MARKER_BIT); 00743 00744 ast_debug(3, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc); 00745 00746 if (srtp) { 00747 ast_debug(3, "Changing ssrc for SRTP from %u to %u\n", rtp->ssrc, ssrc); 00748 res_srtp->change_source(srtp, rtp->ssrc, ssrc); 00749 } 00750 00751 rtp->ssrc = ssrc; 00752 00753 return; 00754 }
static int ast_rtp_destroy | ( | struct ast_rtp_instance * | instance | ) | [static] |
Definition at line 498 of file res_rtp_asterisk.c.
References ast_free, ast_rtp_instance_get_data(), AST_SCHED_DEL, ast_smoother_free(), ast_rtp::red, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, rtp_red::schedid, ast_rtcp::schedid, and ast_rtp::smoother.
00499 { 00500 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00501 00502 /* Destroy the smoother that was smoothing out audio if present */ 00503 if (rtp->smoother) { 00504 ast_smoother_free(rtp->smoother); 00505 } 00506 00507 /* Close our own socket so we no longer get packets */ 00508 if (rtp->s > -1) { 00509 close(rtp->s); 00510 } 00511 00512 /* Destroy RTCP if it was being used */ 00513 if (rtp->rtcp) { 00514 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 00515 close(rtp->rtcp->s); 00516 ast_free(rtp->rtcp); 00517 } 00518 00519 /* Destroy RED if it was being used */ 00520 if (rtp->red) { 00521 AST_SCHED_DEL(rtp->sched, rtp->red->schedid); 00522 ast_free(rtp->red); 00523 } 00524 00525 /* Finally destroy ourselves */ 00526 ast_free(rtp); 00527 00528 return 0; 00529 }
static int ast_rtp_dtmf_begin | ( | struct ast_rtp_instance * | instance, | |
char | digit | |||
) | [static] |
Definition at line 531 of file res_rtp_asterisk.c.
References ast_log(), ast_rtp_codecs_payload_code(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, and ast_rtp::ssrc.
00532 { 00533 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00534 struct ast_sockaddr remote_address = { {0,} }; 00535 int hdrlen = 12, res = 0, i = 0, payload = 101; 00536 char data[256]; 00537 unsigned int *rtpheader = (unsigned int*)data; 00538 00539 ast_rtp_instance_get_remote_address(instance, &remote_address); 00540 00541 /* If we have no remote address information bail out now */ 00542 if (ast_sockaddr_isnull(&remote_address)) { 00543 return -1; 00544 } 00545 00546 /* Convert given digit into what we want to transmit */ 00547 if ((digit <= '9') && (digit >= '0')) { 00548 digit -= '0'; 00549 } else if (digit == '*') { 00550 digit = 10; 00551 } else if (digit == '#') { 00552 digit = 11; 00553 } else if ((digit >= 'A') && (digit <= 'D')) { 00554 digit = digit - 'A' + 12; 00555 } else if ((digit >= 'a') && (digit <= 'd')) { 00556 digit = digit - 'a' + 12; 00557 } else { 00558 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 00559 return -1; 00560 } 00561 00562 /* Grab the payload that they expect the RFC2833 packet to be received in */ 00563 payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, AST_RTP_DTMF); 00564 00565 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 00566 rtp->send_duration = 160; 00567 rtp->lastdigitts = rtp->lastts + rtp->send_duration; 00568 00569 /* Create the actual packet that we will be sending */ 00570 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 00571 rtpheader[1] = htonl(rtp->lastdigitts); 00572 rtpheader[2] = htonl(rtp->ssrc); 00573 00574 /* Actually send the packet */ 00575 for (i = 0; i < 2; i++) { 00576 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 00577 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address); 00578 if (res < 0) { 00579 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n", 00580 ast_sockaddr_stringify(&remote_address), 00581 strerror(errno)); 00582 } 00583 if (rtp_debug_test_addr(&remote_address)) { 00584 ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 00585 ast_sockaddr_stringify(&remote_address), 00586 payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 00587 } 00588 rtp->seqno++; 00589 rtp->send_duration += 160; 00590 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 00591 } 00592 00593 /* Record that we are in the process of sending a digit and information needed to continue doing so */ 00594 rtp->sending_digit = 1; 00595 rtp->send_digit = digit; 00596 rtp->send_payload = payload; 00597 00598 return 0; 00599 }
static int ast_rtp_dtmf_compatible | ( | struct ast_channel * | chan0, | |
struct ast_rtp_instance * | instance0, | |||
struct ast_channel * | chan1, | |||
struct ast_rtp_instance * | instance1 | |||
) | [static] |
Definition at line 2539 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_DTMF, ast_channel_tech::send_digit_begin, and ast_channel::tech.
02540 { 02541 /* If both sides are not using the same method of DTMF transmission 02542 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 02543 * -------------------------------------------------- 02544 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 02545 * |-----------|------------|-----------------------| 02546 * | Inband | False | True | 02547 * | RFC2833 | True | True | 02548 * | SIP INFO | False | False | 02549 * -------------------------------------------------- 02550 */ 02551 return (((ast_rtp_instance_get_prop(instance0, AST_RTP_PROPERTY_DTMF) != ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_DTMF)) || 02552 (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1); 02553 }
static int ast_rtp_dtmf_continuation | ( | struct ast_rtp_instance * | instance | ) | [static] |
Definition at line 601 of file res_rtp_asterisk.c.
References ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, errno, ast_rtp::lastdigitts, LOG_ERROR, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, and ast_rtp::ssrc.
Referenced by ast_rtp_read().
00602 { 00603 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00604 struct ast_sockaddr remote_address = { {0,} }; 00605 int hdrlen = 12, res = 0; 00606 char data[256]; 00607 unsigned int *rtpheader = (unsigned int*)data; 00608 00609 ast_rtp_instance_get_remote_address(instance, &remote_address); 00610 00611 /* Make sure we know where the other side is so we can send them the packet */ 00612 if (ast_sockaddr_isnull(&remote_address)) { 00613 return -1; 00614 } 00615 00616 /* Actually create the packet we will be sending */ 00617 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 00618 rtpheader[1] = htonl(rtp->lastdigitts); 00619 rtpheader[2] = htonl(rtp->ssrc); 00620 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 00621 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 00622 00623 /* Boom, send it on out */ 00624 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address); 00625 if (res < 0) { 00626 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n", 00627 ast_sockaddr_stringify(&remote_address), 00628 strerror(errno)); 00629 } 00630 00631 if (rtp_debug_test_addr(&remote_address)) { 00632 ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 00633 ast_sockaddr_stringify(&remote_address), 00634 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 00635 } 00636 00637 /* And now we increment some values for the next time we swing by */ 00638 rtp->seqno++; 00639 rtp->send_duration += 160; 00640 00641 return 0; 00642 }
static int ast_rtp_dtmf_end | ( | struct ast_rtp_instance * | instance, | |
char | digit | |||
) | [static] |
Definition at line 714 of file res_rtp_asterisk.c.
References ast_rtp_dtmf_end_with_duration().
00715 { 00716 return ast_rtp_dtmf_end_with_duration(instance, digit, 0); 00717 }
static int ast_rtp_dtmf_end_with_duration | ( | struct ast_rtp_instance * | instance, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 644 of file res_rtp_asterisk.c.
References ast_debug, ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_frame_subclass::codec, ast_rtp::dtmfmute, errno, ast_rtp::f, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), rtp_get_rate(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_frame::subclass.
Referenced by ast_rtp_dtmf_end().
00645 { 00646 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00647 struct ast_sockaddr remote_address = { {0,} }; 00648 int hdrlen = 12, res = 0, i = 0; 00649 char data[256]; 00650 unsigned int *rtpheader = (unsigned int*)data; 00651 unsigned int measured_samples; 00652 00653 ast_rtp_instance_get_remote_address(instance, &remote_address); 00654 00655 /* Make sure we know where the remote side is so we can send them the packet we construct */ 00656 if (ast_sockaddr_isnull(&remote_address)) { 00657 return -1; 00658 } 00659 00660 /* Convert the given digit to the one we are going to send */ 00661 if ((digit <= '9') && (digit >= '0')) { 00662 digit -= '0'; 00663 } else if (digit == '*') { 00664 digit = 10; 00665 } else if (digit == '#') { 00666 digit = 11; 00667 } else if ((digit >= 'A') && (digit <= 'D')) { 00668 digit = digit - 'A' + 12; 00669 } else if ((digit >= 'a') && (digit <= 'd')) { 00670 digit = digit - 'a' + 12; 00671 } else { 00672 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 00673 return -1; 00674 } 00675 00676 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 00677 00678 if (duration > 0 && (measured_samples = duration * rtp_get_rate(rtp->f.subclass.codec) / 1000) > rtp->send_duration) { 00679 ast_debug(2, "Adjusting final end duration from %u to %u\n", rtp->send_duration, measured_samples); 00680 rtp->send_duration = measured_samples; 00681 } 00682 00683 /* Construct the packet we are going to send */ 00684 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 00685 rtpheader[1] = htonl(rtp->lastdigitts); 00686 rtpheader[2] = htonl(rtp->ssrc); 00687 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 00688 rtpheader[3] |= htonl((1 << 23)); 00689 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 00690 00691 /* Send it 3 times, that's the magical number */ 00692 for (i = 0; i < 3; i++) { 00693 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address); 00694 if (res < 0) { 00695 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n", 00696 ast_sockaddr_stringify(&remote_address), 00697 strerror(errno)); 00698 } 00699 if (rtp_debug_test_addr(&remote_address)) { 00700 ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 00701 ast_sockaddr_stringify(&remote_address), 00702 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 00703 } 00704 } 00705 00706 /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */ 00707 rtp->lastts += rtp->send_duration; 00708 rtp->sending_digit = 0; 00709 rtp->send_digit = 0; 00710 00711 return 0; 00712 }
static int ast_rtp_fd | ( | struct ast_rtp_instance * | instance, | |
int | rtcp | |||
) | [static] |
Definition at line 2379 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_rtp::rtcp, ast_rtp::s, and ast_rtcp::s.
02380 { 02381 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02382 02383 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s; 02384 }
static int ast_rtp_get_stat | ( | struct ast_rtp_instance * | instance, | |
struct ast_rtp_instance_stats * | stats, | |||
enum ast_rtp_instance_stat | stat | |||
) | [static] |
Definition at line 2491 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), AST_RTP_INSTANCE_STAT_COMBINED_JITTER, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, AST_RTP_INSTANCE_STAT_COMBINED_RTT, AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_SSRC, AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_SSRC, AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_RXCOUNT, AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_TXCOUNT, AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_STAT_SET, AST_RTP_STAT_TERMINATOR, ast_rtcp::expected_prior, ast_rtp_instance_stats::local_maxjitter, ast_rtp_instance_stats::local_maxrxploss, ast_rtp_instance_stats::local_minjitter, ast_rtp_instance_stats::local_minrxploss, ast_rtp_instance_stats::local_normdevjitter, ast_rtp_instance_stats::local_normdevrxploss, ast_rtp_instance_stats::local_ssrc, ast_rtp_instance_stats::local_stdevjitter, ast_rtp_instance_stats::local_stdevrxploss, ast_rtcp::maxrtt, ast_rtp_instance_stats::maxrtt, ast_rtcp::maxrxjitter, ast_rtcp::maxrxlost, ast_rtcp::minrtt, ast_rtp_instance_stats::minrtt, ast_rtcp::minrxjitter, ast_rtcp::minrxlost, ast_rtcp::normdev_rxjitter, ast_rtcp::normdev_rxlost, ast_rtcp::normdevrtt, ast_rtp_instance_stats::normdevrtt, ast_rtcp::received_prior, ast_rtp_instance_stats::remote_maxjitter, ast_rtp_instance_stats::remote_maxrxploss, ast_rtp_instance_stats::remote_minjitter, ast_rtp_instance_stats::remote_minrxploss, ast_rtp_instance_stats::remote_normdevjitter, ast_rtp_instance_stats::remote_normdevrxploss, ast_rtp_instance_stats::remote_ssrc, ast_rtp_instance_stats::remote_stdevjitter, ast_rtp_instance_stats::remote_stdevrxploss, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp_instance_stats::rtt, ast_rtp::rxcount, ast_rtp_instance_stats::rxcount, ast_rtp_instance_stats::rxjitter, ast_rtp::rxjitter, ast_rtp_instance_stats::rxploss, ast_rtp::ssrc, ast_rtcp::stdev_rxjitter, ast_rtcp::stdev_rxlost, ast_rtcp::stdevrtt, ast_rtp_instance_stats::stdevrtt, ast_rtp::themssrc, ast_rtp::txcount, ast_rtp_instance_stats::txcount, ast_rtp_instance_stats::txjitter, and ast_rtp_instance_stats::txploss.
02492 { 02493 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02494 02495 if (!rtp->rtcp) { 02496 return -1; 02497 } 02498 02499 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount); 02500 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount); 02501 02502 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->txploss, rtp->rtcp->reported_lost); 02503 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->rxploss, rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02504 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_maxrxploss, rtp->rtcp->reported_maxlost); 02505 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_minrxploss, rtp->rtcp->reported_minlost); 02506 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_normdevrxploss, rtp->rtcp->reported_normdev_lost); 02507 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_stdevrxploss, rtp->rtcp->reported_stdev_lost); 02508 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_maxrxploss, rtp->rtcp->maxrxlost); 02509 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_minrxploss, rtp->rtcp->minrxlost); 02510 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_normdevrxploss, rtp->rtcp->normdev_rxlost); 02511 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_stdevrxploss, rtp->rtcp->stdev_rxlost); 02512 AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_LOSS); 02513 02514 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->txjitter, rtp->rxjitter); 02515 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->rxjitter, rtp->rtcp->reported_jitter / (unsigned int) 65536.0); 02516 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_maxjitter, rtp->rtcp->reported_maxjitter); 02517 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_minjitter, rtp->rtcp->reported_minjitter); 02518 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_normdevjitter, rtp->rtcp->reported_normdev_jitter); 02519 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_stdevjitter, rtp->rtcp->reported_stdev_jitter); 02520 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_maxjitter, rtp->rtcp->maxrxjitter); 02521 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_minjitter, rtp->rtcp->minrxjitter); 02522 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_normdevjitter, rtp->rtcp->normdev_rxjitter); 02523 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_stdevjitter, rtp->rtcp->stdev_rxjitter); 02524 AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_JITTER); 02525 02526 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->rtt, rtp->rtcp->rtt); 02527 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->maxrtt, rtp->rtcp->maxrtt); 02528 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->minrtt, rtp->rtcp->minrtt); 02529 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->normdevrtt, rtp->rtcp->normdevrtt); 02530 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->stdevrtt, rtp->rtcp->stdevrtt); 02531 AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_RTT); 02532 02533 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc); 02534 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc); 02535 02536 return 0; 02537 }
static int ast_rtp_local_bridge | ( | struct ast_rtp_instance * | instance0, | |
struct ast_rtp_instance * | instance1 | |||
) | [static] |
Definition at line 2482 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.
02483 { 02484 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0); 02485 02486 ast_set_flag(rtp, FLAG_NEED_MARKER_BIT); 02487 02488 return 0; 02489 }
static int ast_rtp_new | ( | struct ast_rtp_instance * | instance, | |
struct sched_context * | sched, | |||
struct ast_sockaddr * | addr, | |||
void * | data | |||
) | [static] |
Definition at line 436 of file res_rtp_asterisk.c.
References ast_bind(), ast_calloc, ast_debug, ast_free, ast_log(), ast_random(), ast_rtp_instance_set_local_address(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_set_port, create_new_socket(), errno, LOG_ERROR, STRICT_RTP_LEARN, and STRICT_RTP_OPEN.
00439 { 00440 struct ast_rtp *rtp = NULL; 00441 int x, startplace; 00442 00443 /* Create a new RTP structure to hold all of our data */ 00444 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) { 00445 return -1; 00446 } 00447 00448 /* Set default parameters on the newly created RTP structure */ 00449 rtp->ssrc = ast_random(); 00450 rtp->seqno = ast_random() & 0xffff; 00451 rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN); 00452 00453 /* Create a new socket for us to listen on and use */ 00454 if ((rtp->s = 00455 create_new_socket("RTP", 00456 ast_sockaddr_is_ipv4(addr) ? AF_INET : 00457 ast_sockaddr_is_ipv6(addr) ? AF_INET6 : -1)) < 0) { 00458 ast_debug(1, "Failed to create a new socket for RTP instance '%p'\n", instance); 00459 ast_free(rtp); 00460 return -1; 00461 } 00462 00463 /* Now actually find a free RTP port to use */ 00464 x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart; 00465 x = x & ~1; 00466 startplace = x; 00467 00468 for (;;) { 00469 ast_sockaddr_set_port(addr, x); 00470 /* Try to bind, this will tell us whether the port is available or not */ 00471 if (!ast_bind(rtp->s, addr)) { 00472 ast_debug(1, "Allocated port %d for RTP instance '%p'\n", x, instance); 00473 ast_rtp_instance_set_local_address(instance, addr); 00474 break; 00475 } 00476 00477 x += 2; 00478 if (x > rtpend) { 00479 x = (rtpstart + 1) & ~1; 00480 } 00481 00482 /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */ 00483 if (x == startplace || errno != EADDRINUSE) { 00484 ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance); 00485 return -1; 00486 } 00487 } 00488 00489 /* Record any information we may need */ 00490 rtp->sched = sched; 00491 00492 /* Associate the RTP structure with the RTP instance and be done */ 00493 ast_rtp_instance_set_data(instance, rtp); 00494 00495 return 0; 00496 }
static void ast_rtp_prop_set | ( | struct ast_rtp_instance * | instance, | |
enum ast_rtp_property | property, | |||
int | value | |||
) | [static] |
Definition at line 2331 of file res_rtp_asterisk.c.
References ast_bind(), ast_calloc, ast_debug, ast_free, ast_rtp_instance_get_data(), ast_rtp_instance_get_local_address(), AST_RTP_PROPERTY_RTCP, ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_port, ast_sockaddr_set_port, create_new_socket(), ast_rtp::rtcp, ast_rtcp::s, ast_rtcp::schedid, and ast_rtcp::us.
02332 { 02333 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02334 02335 if (property == AST_RTP_PROPERTY_RTCP) { 02336 if (rtp->rtcp) { 02337 ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance); 02338 return; 02339 } 02340 if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) { 02341 return; 02342 } 02343 02344 /* Grab the IP address and port we are going to use */ 02345 ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us); 02346 ast_sockaddr_set_port(&rtp->rtcp->us, 02347 ast_sockaddr_port(&rtp->rtcp->us) + 1); 02348 02349 if ((rtp->rtcp->s = 02350 create_new_socket("RTCP", 02351 ast_sockaddr_is_ipv4(&rtp->rtcp->us) ? 02352 AF_INET : 02353 ast_sockaddr_is_ipv6(&rtp->rtcp->us) ? 02354 AF_INET6 : -1)) < 0) { 02355 ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance); 02356 ast_free(rtp->rtcp); 02357 rtp->rtcp = NULL; 02358 return; 02359 } 02360 02361 /* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */ 02362 if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) { 02363 ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance); 02364 close(rtp->rtcp->s); 02365 ast_free(rtp->rtcp); 02366 rtp->rtcp = NULL; 02367 return; 02368 } 02369 02370 ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance); 02371 rtp->rtcp->schedid = -1; 02372 02373 return; 02374 } 02375 02376 return; 02377 }
static int ast_rtp_qos_set | ( | struct ast_rtp_instance * | instance, | |
int | tos, | |||
int | cos, | |||
const char * | desc | |||
) | [static] |
Definition at line 2587 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_set_qos(), and ast_rtp::s.
02588 { 02589 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02590 02591 return ast_set_qos(rtp->s, tos, cos, desc); 02592 }
static int ast_rtp_raw_write | ( | struct ast_rtp_instance * | instance, | |
struct ast_frame * | frame, | |||
int | codec | |||
) | [static] |
Definition at line 1034 of file res_rtp_asterisk.c.
References ast_clear_flag, ast_debug, AST_FORMAT_G722, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, ast_rtcp_calc_interval(), ast_rtcp_write(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), AST_RTP_PROPERTY_NAT, ast_sched_add(), ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_flag, ast_tvzero(), ast_verbose, calc_txstamp(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, ast_frame::frametype, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, MAX_TIMESTAMP_SKEW, option_debug, ast_frame::ptr, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), rtp_sendto(), rtpdebug, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
01035 { 01036 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01037 int pred, mark = 0; 01038 unsigned int ms = calc_txstamp(rtp, &frame->delivery); 01039 struct ast_sockaddr remote_address = { {0,} }; 01040 int rate = rtp_get_rate(frame->subclass.codec) / 1000; 01041 01042 if (frame->subclass.codec == AST_FORMAT_G722) { 01043 frame->samples /= 2; 01044 } 01045 01046 if (rtp->sending_digit) { 01047 return 0; 01048 } 01049 01050 if (frame->frametype == AST_FRAME_VOICE) { 01051 pred = rtp->lastts + frame->samples; 01052 01053 /* Re-calculate last TS */ 01054 rtp->lastts = rtp->lastts + ms * rate; 01055 if (ast_tvzero(frame->delivery)) { 01056 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 01057 and if so, go with our prediction */ 01058 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) { 01059 rtp->lastts = pred; 01060 } else { 01061 ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 01062 mark = 1; 01063 } 01064 } 01065 } else if (frame->frametype == AST_FRAME_VIDEO) { 01066 mark = frame->subclass.codec & 0x1; 01067 pred = rtp->lastovidtimestamp + frame->samples; 01068 /* Re-calculate last TS */ 01069 rtp->lastts = rtp->lastts + ms * 90; 01070 /* If it's close to our prediction, go for it */ 01071 if (ast_tvzero(frame->delivery)) { 01072 if (abs(rtp->lastts - pred) < 7200) { 01073 rtp->lastts = pred; 01074 rtp->lastovidtimestamp += frame->samples; 01075 } else { 01076 ast_debug(3, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, frame->samples); 01077 rtp->lastovidtimestamp = rtp->lastts; 01078 } 01079 } 01080 } else { 01081 pred = rtp->lastotexttimestamp + frame->samples; 01082 /* Re-calculate last TS */ 01083 rtp->lastts = rtp->lastts + ms; 01084 /* If it's close to our prediction, go for it */ 01085 if (ast_tvzero(frame->delivery)) { 01086 if (abs(rtp->lastts - pred) < 7200) { 01087 rtp->lastts = pred; 01088 rtp->lastotexttimestamp += frame->samples; 01089 } else { 01090 ast_debug(3, "Difference is %d, ms is %d, pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, rtp->lastts, pred, frame->samples); 01091 rtp->lastotexttimestamp = rtp->lastts; 01092 } 01093 } 01094 } 01095 01096 /* If we have been explicitly told to set the marker bit then do so */ 01097 if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) { 01098 mark = 1; 01099 ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT); 01100 } 01101 01102 /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */ 01103 if (rtp->lastts > rtp->lastdigitts) { 01104 rtp->lastdigitts = rtp->lastts; 01105 } 01106 01107 if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) { 01108 rtp->lastts = frame->ts * rate; 01109 } 01110 01111 ast_rtp_instance_get_remote_address(instance, &remote_address); 01112 01113 /* If we know the remote address construct a packet and send it out */ 01114 if (!ast_sockaddr_isnull(&remote_address)) { 01115 int hdrlen = 12, res; 01116 unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen); 01117 01118 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 01119 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 01120 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 01121 01122 if ((res = rtp_sendto(instance, (void *)rtpheader, frame->datalen + hdrlen, 0, &remote_address)) < 0) { 01123 if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01124 ast_debug(1, "RTP Transmission error of packet %d to %s: %s\n", 01125 rtp->seqno, 01126 ast_sockaddr_stringify(&remote_address), 01127 strerror(errno)); 01128 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 01129 /* Only give this error message once if we are not RTP debugging */ 01130 if (option_debug || rtpdebug) 01131 ast_debug(0, "RTP NAT: Can't write RTP to private address %s, waiting for other end to send audio...\n", 01132 ast_sockaddr_stringify(&remote_address)); 01133 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 01134 } 01135 } else { 01136 rtp->txcount++; 01137 rtp->txoctetcount += (res - hdrlen); 01138 01139 if (rtp->rtcp && rtp->rtcp->schedid < 1) { 01140 ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", instance); 01141 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance); 01142 } 01143 } 01144 01145 if (rtp_debug_test_addr(&remote_address)) { 01146 ast_verbose("Sent RTP packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01147 ast_sockaddr_stringify(&remote_address), 01148 codec, rtp->seqno, rtp->lastts, res - hdrlen); 01149 } 01150 } 01151 01152 rtp->seqno++; 01153 01154 return 0; 01155 }
static struct ast_frame * ast_rtp_read | ( | struct ast_rtp_instance * | instance, | |
int | rtcp | |||
) | [static] |
Definition at line 1980 of file res_rtp_asterisk.c.
References ast_rtp::alt_rtp_address, ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_read(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, ast_rtp_codecs_payload_lookup(), AST_RTP_DTMF, ast_rtp_dtmf_continuation(), ast_rtp_instance_get_bridged(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), ast_rtp_instance_set_remote_address(), AST_RTP_PROPERTY_NAT, ast_samp2tv(), ast_sched_add(), ast_set_flag, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_from_sin, ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_sockaddr_to_sin, ast_strdupa, AST_STUN_ACCEPT, ast_stun_handle_packet(), ast_tv(), ast_tvdiff_ms(), ast_verbose, ast_rtp_payload_type::asterisk_format, bridge_p2p_rtp_write(), ast_rtp_payload_type::code, ast_frame_subclass::codec, create_dtmf_frame(), ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, frames, ast_frame::frametype, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len(), LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, option_debug, process_cn_rfc3389(), process_dtmf_cisco(), process_dtmf_rfc2833(), ast_frame::ptr, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), rtp_recvfrom(), RTP_SEQ_MOD, rtpdebug, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, ast_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, ast_frame::subclass, ast_rtcp::them, ast_rtp::themssrc, and version.
01981 { 01982 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01983 struct ast_sockaddr addr; 01984 int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno; 01985 unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp; 01986 struct ast_rtp_payload_type payload; 01987 struct ast_sockaddr remote_address = { {0,} }; 01988 struct frame_list frames; 01989 01990 /* If this is actually RTCP let's hop on over and handle it */ 01991 if (rtcp) { 01992 if (rtp->rtcp) { 01993 return ast_rtcp_read(instance); 01994 } 01995 return &ast_null_frame; 01996 } 01997 01998 /* If we are currently sending DTMF to the remote party send a continuation packet */ 01999 if (rtp->sending_digit) { 02000 ast_rtp_dtmf_continuation(instance); 02001 } 02002 02003 /* Actually read in the data from the socket */ 02004 if ((res = rtp_recvfrom(instance, rtp->rawdata + AST_FRIENDLY_OFFSET, 02005 sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, 02006 &addr)) < 0) { 02007 ast_assert(errno != EBADF); 02008 if (errno != EAGAIN) { 02009 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 02010 return NULL; 02011 } 02012 return &ast_null_frame; 02013 } 02014 02015 /* Make sure the data that was read in is actually enough to make up an RTP packet */ 02016 if (res < hdrlen) { 02017 ast_log(LOG_WARNING, "RTP Read too short\n"); 02018 return &ast_null_frame; 02019 } 02020 02021 /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */ 02022 if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { 02023 ast_sockaddr_copy(&rtp->strict_rtp_address, &addr); 02024 rtp->strict_rtp_state = STRICT_RTP_CLOSED; 02025 } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { 02026 if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) { 02027 /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */ 02028 if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) { 02029 /* ooh, we did! You're now the new expected address, son! */ 02030 ast_sockaddr_copy(&rtp->strict_rtp_address, 02031 &addr); 02032 } else { 02033 const char *real_addr = ast_strdupa(ast_sockaddr_stringify(&addr)); 02034 const char *expected_addr = ast_strdupa(ast_sockaddr_stringify(&rtp->strict_rtp_address)); 02035 02036 ast_debug(1, "Received RTP packet from %s, dropping due to strict RTP protection. Expected it to be from %s\n", 02037 real_addr, expected_addr); 02038 02039 return &ast_null_frame; 02040 } 02041 } 02042 } 02043 02044 /* Get fields and verify this is an RTP packet */ 02045 seqno = ntohl(rtpheader[0]); 02046 02047 ast_rtp_instance_get_remote_address(instance, &remote_address); 02048 02049 if (!(version = (seqno & 0xC0000000) >> 30)) { 02050 struct sockaddr_in addr_tmp; 02051 ast_sockaddr_to_sin(&addr, &addr_tmp); 02052 if ((ast_stun_handle_packet(rtp->s, &addr_tmp, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) && 02053 ast_sockaddr_isnull(&remote_address)) { 02054 ast_sockaddr_from_sin(&addr, &addr_tmp); 02055 ast_rtp_instance_set_remote_address(instance, &addr); 02056 } 02057 return &ast_null_frame; 02058 } 02059 02060 /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */ 02061 if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) { 02062 if (ast_sockaddr_cmp(&remote_address, &addr)) { 02063 ast_rtp_instance_set_remote_address(instance, &addr); 02064 ast_sockaddr_copy(&remote_address, &addr); 02065 if (rtp->rtcp) { 02066 ast_sockaddr_copy(&rtp->rtcp->them, &addr); 02067 ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(&addr) + 1); 02068 } 02069 rtp->rxseqno = 0; 02070 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 02071 if (option_debug || rtpdebug) 02072 ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s\n", 02073 ast_sockaddr_stringify(&remote_address)); 02074 } 02075 } 02076 02077 /* If we are directly bridged to another instance send the audio directly out */ 02078 if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) { 02079 return &ast_null_frame; 02080 } 02081 02082 /* If the version is not what we expected by this point then just drop the packet */ 02083 if (version != 2) { 02084 return &ast_null_frame; 02085 } 02086 02087 /* Pull out the various other fields we will need */ 02088 payloadtype = (seqno & 0x7f0000) >> 16; 02089 padding = seqno & (1 << 29); 02090 mark = seqno & (1 << 23); 02091 ext = seqno & (1 << 28); 02092 cc = (seqno & 0xF000000) >> 24; 02093 seqno &= 0xffff; 02094 timestamp = ntohl(rtpheader[1]); 02095 ssrc = ntohl(rtpheader[2]); 02096 02097 AST_LIST_HEAD_INIT_NOLOCK(&frames); 02098 /* Force a marker bit and change SSRC if the SSRC changes */ 02099 if (rtp->rxssrc && rtp->rxssrc != ssrc) { 02100 struct ast_frame *f, srcupdate = { 02101 AST_FRAME_CONTROL, 02102 .subclass.integer = AST_CONTROL_SRCCHANGE, 02103 }; 02104 02105 if (!mark) { 02106 if (option_debug || rtpdebug) { 02107 ast_debug(1, "Forcing Marker bit, because SSRC has changed\n"); 02108 } 02109 mark = 1; 02110 } 02111 02112 f = ast_frisolate(&srcupdate); 02113 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 02114 } 02115 02116 rtp->rxssrc = ssrc; 02117 02118 /* Remove any padding bytes that may be present */ 02119 if (padding) { 02120 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 02121 } 02122 02123 /* Skip over any CSRC fields */ 02124 if (cc) { 02125 hdrlen += cc * 4; 02126 } 02127 02128 /* Look for any RTP extensions, currently we do not support any */ 02129 if (ext) { 02130 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 02131 hdrlen += 4; 02132 if (option_debug) { 02133 int profile; 02134 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 02135 if (profile == 0x505a) 02136 ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 02137 else 02138 ast_debug(1, "Found unknown RTP Extensions %x\n", profile); 02139 } 02140 } 02141 02142 /* Make sure after we potentially mucked with the header length that it is once again valid */ 02143 if (res < hdrlen) { 02144 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen); 02145 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 02146 } 02147 02148 rtp->rxcount++; 02149 if (rtp->rxcount == 1) { 02150 rtp->seedrxseqno = seqno; 02151 } 02152 02153 /* Do not schedule RR if RTCP isn't run */ 02154 if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 1) { 02155 /* Schedule transmission of Receiver Report */ 02156 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance); 02157 } 02158 if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 02159 rtp->cycles += RTP_SEQ_MOD; 02160 02161 prev_seqno = rtp->lastrxseqno; 02162 rtp->lastrxseqno = seqno; 02163 02164 if (!rtp->themssrc) { 02165 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 02166 } 02167 02168 if (rtp_debug_test_addr(&addr)) { 02169 ast_verbose("Got RTP packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02170 ast_sockaddr_stringify(&addr), 02171 payloadtype, seqno, timestamp,res - hdrlen); 02172 } 02173 02174 payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype); 02175 02176 /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */ 02177 if (!payload.asterisk_format) { 02178 struct ast_frame *f = NULL; 02179 if (payload.code == AST_RTP_DTMF) { 02180 /* process_dtmf_rfc2833 may need to return multiple frames. We do this 02181 * by passing the pointer to the frame list to it so that the method 02182 * can append frames to the list as needed. 02183 */ 02184 process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames); 02185 } else if (payload.code == AST_RTP_CISCO_DTMF) { 02186 f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark); 02187 } else if (payload.code == AST_RTP_CN) { 02188 f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark); 02189 } else { 02190 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", 02191 payloadtype, 02192 ast_sockaddr_stringify(&remote_address)); 02193 } 02194 02195 if (f) { 02196 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 02197 } 02198 /* Even if no frame was returned by one of the above methods, 02199 * we may have a frame to return in our frame list 02200 */ 02201 if (!AST_LIST_EMPTY(&frames)) { 02202 return AST_LIST_FIRST(&frames); 02203 } 02204 return &ast_null_frame; 02205 } 02206 02207 rtp->lastrxformat = rtp->f.subclass.codec = payload.code; 02208 rtp->f.frametype = (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass.codec & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT; 02209 02210 rtp->rxseqno = seqno; 02211 02212 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) { 02213 rtp->dtmf_timeout = 0; 02214 02215 if (rtp->resp) { 02216 struct ast_frame *f; 02217 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0); 02218 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0)); 02219 rtp->resp = 0; 02220 rtp->dtmf_timeout = rtp->dtmf_duration = 0; 02221 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 02222 return AST_LIST_FIRST(&frames); 02223 } 02224 } 02225 02226 rtp->lastrxts = timestamp; 02227 02228 rtp->f.src = "RTP"; 02229 rtp->f.mallocd = 0; 02230 rtp->f.datalen = res - hdrlen; 02231 rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 02232 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 02233 rtp->f.seqno = seqno; 02234 02235 if (rtp->f.subclass.codec == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) { 02236 unsigned char *data = rtp->f.data.ptr; 02237 02238 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen); 02239 rtp->f.datalen +=3; 02240 *data++ = 0xEF; 02241 *data++ = 0xBF; 02242 *data = 0xBD; 02243 } 02244 02245 if (rtp->f.subclass.codec == AST_FORMAT_T140RED) { 02246 unsigned char *data = rtp->f.data.ptr; 02247 unsigned char *header_end; 02248 int num_generations; 02249 int header_length; 02250 int len; 02251 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/ 02252 int x; 02253 02254 rtp->f.subclass.codec = AST_FORMAT_T140; 02255 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); 02256 if (header_end == NULL) { 02257 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 02258 } 02259 header_end++; 02260 02261 header_length = header_end - data; 02262 num_generations = header_length / 4; 02263 len = header_length; 02264 02265 if (!diff) { 02266 for (x = 0; x < num_generations; x++) 02267 len += data[x * 4 + 3]; 02268 02269 if (!(rtp->f.datalen - len)) 02270 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 02271 02272 rtp->f.data.ptr += len; 02273 rtp->f.datalen -= len; 02274 } else if (diff > num_generations && diff < 10) { 02275 len -= 3; 02276 rtp->f.data.ptr += len; 02277 rtp->f.datalen -= len; 02278 02279 data = rtp->f.data.ptr; 02280 *data++ = 0xEF; 02281 *data++ = 0xBF; 02282 *data = 0xBD; 02283 } else { 02284 for ( x = 0; x < num_generations - diff; x++) 02285 len += data[x * 4 + 3]; 02286 02287 rtp->f.data.ptr += len; 02288 rtp->f.datalen -= len; 02289 } 02290 } 02291 02292 if (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) { 02293 rtp->f.samples = ast_codec_get_samples(&rtp->f); 02294 if ((rtp->f.subclass.codec == AST_FORMAT_SLINEAR) || (rtp->f.subclass.codec == AST_FORMAT_SLINEAR16)) { 02295 ast_frame_byteswap_be(&rtp->f); 02296 } 02297 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 02298 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 02299 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 02300 rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass.codec) / 1000); 02301 rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass.codec) / 1000)); 02302 } else if (rtp->f.subclass.codec & AST_FORMAT_VIDEO_MASK) { 02303 /* Video -- samples is # of samples vs. 90000 */ 02304 if (!rtp->lastividtimestamp) 02305 rtp->lastividtimestamp = timestamp; 02306 rtp->f.samples = timestamp - rtp->lastividtimestamp; 02307 rtp->lastividtimestamp = timestamp; 02308 rtp->f.delivery.tv_sec = 0; 02309 rtp->f.delivery.tv_usec = 0; 02310 /* Pass the RTP marker bit as bit 0 in the subclass field. 02311 * This is ok because subclass is actually a bitmask, and 02312 * the low bits represent audio formats, that are not 02313 * involved here since we deal with video. 02314 */ 02315 if (mark) 02316 rtp->f.subclass.codec |= 0x1; 02317 } else { 02318 /* TEXT -- samples is # of samples vs. 1000 */ 02319 if (!rtp->lastitexttimestamp) 02320 rtp->lastitexttimestamp = timestamp; 02321 rtp->f.samples = timestamp - rtp->lastitexttimestamp; 02322 rtp->lastitexttimestamp = timestamp; 02323 rtp->f.delivery.tv_sec = 0; 02324 rtp->f.delivery.tv_usec = 0; 02325 } 02326 02327 AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list); 02328 return AST_LIST_FIRST(&frames); 02329 }
static void ast_rtp_remote_address_set | ( | struct ast_rtp_instance * | instance, | |
struct ast_sockaddr * | addr | |||
) | [static] |
Definition at line 2386 of file res_rtp_asterisk.c.
References ast_debug, ast_rtp_instance_get_data(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_rtp::rtcp, ast_rtp::rxseqno, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, strictrtp, and ast_rtcp::them.
02387 { 02388 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02389 02390 if (rtp->rtcp) { 02391 ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance); 02392 ast_sockaddr_copy(&rtp->rtcp->them, addr); 02393 if (!ast_sockaddr_isnull(addr)) { 02394 ast_sockaddr_set_port(&rtp->rtcp->them, 02395 ast_sockaddr_port(addr) + 1); 02396 } 02397 } 02398 02399 rtp->rxseqno = 0; 02400 02401 if (strictrtp) { 02402 rtp->strict_rtp_state = STRICT_RTP_LEARN; 02403 } 02404 02405 return; 02406 }
static void ast_rtp_stop | ( | struct ast_rtp_instance * | instance | ) | [static] |
Definition at line 2565 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_rtp_instance_set_remote_address(), AST_SCHED_DEL, ast_set_flag, ast_sockaddr_setnull(), FLAG_NEED_MARKER_BIT, free, ast_rtp::red, ast_rtp::rtcp, ast_rtp::sched, rtp_red::schedid, ast_rtcp::schedid, and ast_rtcp::them.
02566 { 02567 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02568 struct ast_sockaddr addr = { {0,} }; 02569 02570 if (rtp->rtcp) { 02571 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02572 } 02573 if (rtp->red) { 02574 AST_SCHED_DEL(rtp->sched, rtp->red->schedid); 02575 free(rtp->red); 02576 rtp->red = NULL; 02577 } 02578 02579 ast_rtp_instance_set_remote_address(instance, &addr); 02580 if (rtp->rtcp) { 02581 ast_sockaddr_setnull(&rtp->rtcp->them); 02582 } 02583 02584 ast_set_flag(rtp, FLAG_NEED_MARKER_BIT); 02585 }
static void ast_rtp_stun_request | ( | struct ast_rtp_instance * | instance, | |
struct ast_sockaddr * | suggestion, | |||
const char * | username | |||
) | [static] |
Definition at line 2555 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_stun_request(), and ast_rtp::s.
02556 { 02557 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02558 struct sockaddr_in suggestion_tmp; 02559 02560 ast_sockaddr_to_sin(suggestion, &suggestion_tmp); 02561 ast_stun_request(rtp->s, &suggestion_tmp, username, NULL); 02562 ast_sockaddr_from_sin(suggestion, &suggestion_tmp); 02563 }
static void ast_rtp_update_source | ( | struct ast_rtp_instance * | instance | ) | [static] |
Definition at line 719 of file res_rtp_asterisk.c.
References ast_debug, ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.
00720 { 00721 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 00722 00723 /* We simply set this bit so that the next packet sent will have the marker bit turned on */ 00724 ast_set_flag(rtp, FLAG_NEED_MARKER_BIT); 00725 ast_debug(3, "Setting the marker bit due to a source update\n"); 00726 00727 return; 00728 }
static int ast_rtp_write | ( | struct ast_rtp_instance * | instance, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 1194 of file res_rtp_asterisk.c.
References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G719, AST_FORMAT_G723_1, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, AST_FORMAT_SPEEX, AST_FORMAT_SPEEX16, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_sockaddr_isnull(), ast_frame_subclass::codec, ast_format_list::cur_ms, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, and ast_frame::subclass.
Referenced by red_write().
01195 { 01196 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01197 struct ast_sockaddr remote_address = { {0,} }; 01198 format_t codec, subclass; 01199 01200 ast_rtp_instance_get_remote_address(instance, &remote_address); 01201 01202 /* If we don't actually know the remote address don't even bother doing anything */ 01203 if (ast_sockaddr_isnull(&remote_address)) { 01204 ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance); 01205 return 0; 01206 } 01207 01208 /* If there is no data length we can't very well send the packet */ 01209 if (!frame->datalen) { 01210 ast_debug(1, "Received frame with no data for RTP instance '%p' so dropping frame\n", instance); 01211 return 0; 01212 } 01213 01214 /* If the packet is not one our RTP stack supports bail out */ 01215 if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) { 01216 ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n"); 01217 return -1; 01218 } 01219 01220 if (rtp->red) { 01221 /* return 0; */ 01222 /* no primary data or generations to send */ 01223 if ((frame = red_t140_to_red(rtp->red)) == NULL) 01224 return 0; 01225 } 01226 01227 /* Grab the subclass and look up the payload we are going to use */ 01228 subclass = frame->subclass.codec; 01229 if (frame->frametype == AST_FRAME_VIDEO) { 01230 subclass &= ~0x1LL; 01231 } 01232 if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, subclass)) < 0) { 01233 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(frame->subclass.codec)); 01234 return -1; 01235 } 01236 01237 /* Oh dear, if the format changed we will have to set up a new smoother */ 01238 if (rtp->lasttxformat != subclass) { 01239 ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01240 rtp->lasttxformat = subclass; 01241 if (rtp->smoother) { 01242 ast_smoother_free(rtp->smoother); 01243 rtp->smoother = NULL; 01244 } 01245 } 01246 01247 /* If no smoother is present see if we have to set one up */ 01248 if (!rtp->smoother) { 01249 struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, subclass); 01250 01251 switch (subclass) { 01252 case AST_FORMAT_SPEEX: 01253 case AST_FORMAT_SPEEX16: 01254 case AST_FORMAT_G723_1: 01255 case AST_FORMAT_SIREN7: 01256 case AST_FORMAT_SIREN14: 01257 case AST_FORMAT_G719: 01258 /* these are all frame-based codecs and cannot be safely run through 01259 a smoother */ 01260 break; 01261 default: 01262 if (fmt.inc_ms) { 01263 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 01264 ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); 01265 return -1; 01266 } 01267 if (fmt.flags) { 01268 ast_smoother_set_flags(rtp->smoother, fmt.flags); 01269 } 01270 ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); 01271 } 01272 } 01273 } 01274 01275 /* Feed audio frames into the actual function that will create a frame and send it */ 01276 if (rtp->smoother) { 01277 struct ast_frame *f; 01278 01279 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 01280 ast_smoother_feed_be(rtp->smoother, frame); 01281 } else { 01282 ast_smoother_feed(rtp->smoother, frame); 01283 } 01284 01285 while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) { 01286 ast_rtp_raw_write(instance, f, codec); 01287 } 01288 } else { 01289 int hdrlen = 12; 01290 struct ast_frame *f = NULL; 01291 01292 if (frame->offset < hdrlen) { 01293 f = ast_frdup(frame); 01294 } else { 01295 f = frame; 01296 } 01297 if (f->data.ptr) { 01298 ast_rtp_raw_write(instance, f, codec); 01299 } 01300 if (f != frame) { 01301 ast_frfree(f); 01302 } 01303 01304 } 01305 01306 return 0; 01307 }
static int bridge_p2p_rtp_write | ( | struct ast_rtp_instance * | instance, | |
unsigned int * | rtpheader, | |||
int | len, | |||
int | hdrlen | |||
) | [static] |
Definition at line 1910 of file res_rtp_asterisk.c.
References ast_clear_flag, ast_debug, ast_log(), ast_rtp_codecs_payload_code(), ast_rtp_codecs_payload_lookup(), ast_rtp_instance_get_bridged(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), AST_RTP_PROPERTY_NAT, ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_flag, ast_verbose, ast_rtp_payload_type::asterisk_format, ast_rtp::bridged, ast_rtp_payload_type::code, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, LOG_WARNING, option_debug, reconstruct(), rtp_debug_test_addr(), rtp_sendto(), and rtpdebug.
Referenced by ast_rtp_read().
01911 { 01912 struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance); 01913 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1); 01914 int res = 0, payload = 0, bridged_payload = 0, mark; 01915 struct ast_rtp_payload_type payload_type; 01916 int reconstruct = ntohl(rtpheader[0]); 01917 struct ast_sockaddr remote_address = { {0,} }; 01918 01919 /* Get fields from packet */ 01920 payload = (reconstruct & 0x7f0000) >> 16; 01921 mark = (((reconstruct & 0x800000) >> 23) != 0); 01922 01923 /* Check what the payload value should be */ 01924 payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload); 01925 01926 /* Otherwise adjust bridged payload to match */ 01927 bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, payload_type.code); 01928 01929 /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */ 01930 if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].code)) { 01931 return -1; 01932 } 01933 01934 /* If the marker bit has been explicitly set turn it on */ 01935 if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) { 01936 mark = 1; 01937 ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT); 01938 } 01939 01940 /* Reconstruct part of the packet */ 01941 reconstruct &= 0xFF80FFFF; 01942 reconstruct |= (bridged_payload << 16); 01943 reconstruct |= (mark << 23); 01944 rtpheader[0] = htonl(reconstruct); 01945 01946 ast_rtp_instance_get_remote_address(instance1, &remote_address); 01947 01948 if (ast_sockaddr_isnull(&remote_address)) { 01949 ast_debug(1, "Remote address is null, most likely RTP has been stopped\n"); 01950 return 0; 01951 } 01952 01953 /* Send the packet back out */ 01954 res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address); 01955 if (res < 0) { 01956 if (!ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01957 ast_log(LOG_WARNING, 01958 "RTP Transmission error of packet to %s: %s\n", 01959 ast_sockaddr_stringify(&remote_address), 01960 strerror(errno)); 01961 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 01962 if (option_debug || rtpdebug) 01963 ast_log(LOG_WARNING, 01964 "RTP NAT: Can't write RTP to private " 01965 "address %s, waiting for other end to " 01966 "send audio...\n", 01967 ast_sockaddr_stringify(&remote_address)); 01968 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 01969 } 01970 return 0; 01971 } else if (rtp_debug_test_addr(&remote_address)) { 01972 ast_verbose("Sent RTP P2P packet to %s (type %-2.2d, len %-6.6u)\n", 01973 ast_sockaddr_stringify(&remote_address), 01974 bridged_payload, len - hdrlen); 01975 } 01976 01977 return 0; 01978 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 1309 of file res_rtp_asterisk.c.
References ast_samp2tv(), ast_tvadd(), ast_tvsub(), ast_frame_subclass::codec, ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, normdev_compute(), ast_rtcp::normdev_rxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxtransit, ast_rtp::seedrxts, stddev_compute(), ast_rtcp::stdev_rxjitter, and ast_frame::subclass.
01310 { 01311 struct timeval now; 01312 struct timeval tmp; 01313 double transit; 01314 double current_time; 01315 double d; 01316 double dtv; 01317 double prog; 01318 int rate = rtp_get_rate(rtp->f.subclass.codec); 01319 01320 double normdev_rxjitter_current; 01321 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01322 gettimeofday(&rtp->rxcore, NULL); 01323 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01324 /* map timestamp to a real time */ 01325 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01326 tmp = ast_samp2tv(timestamp, rate); 01327 rtp->rxcore = ast_tvsub(rtp->rxcore, tmp); 01328 /* Round to 0.1ms for nice, pretty timestamps */ 01329 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01330 } 01331 01332 gettimeofday(&now,NULL); 01333 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01334 tmp = ast_samp2tv(timestamp, rate); 01335 *tv = ast_tvadd(rtp->rxcore, tmp); 01336 01337 prog = (double)((timestamp-rtp->seedrxts)/(float)(rate)); 01338 dtv = (double)rtp->drxcore + (double)(prog); 01339 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01340 transit = current_time - dtv; 01341 d = transit - rtp->rxtransit; 01342 rtp->rxtransit = transit; 01343 if (d<0) 01344 d=-d; 01345 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01346 01347 if (rtp->rtcp) { 01348 if (rtp->rxjitter > rtp->rtcp->maxrxjitter) 01349 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01350 if (rtp->rtcp->rxjitter_count == 1) 01351 rtp->rtcp->minrxjitter = rtp->rxjitter; 01352 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01353 rtp->rtcp->minrxjitter = rtp->rxjitter; 01354 01355 normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count); 01356 rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count); 01357 01358 rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current; 01359 rtp->rtcp->rxjitter_count++; 01360 } 01361 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 756 of file res_rtp_asterisk.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
00757 { 00758 struct timeval t; 00759 long ms; 00760 00761 if (ast_tvzero(rtp->txcore)) { 00762 rtp->txcore = ast_tvnow(); 00763 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 00764 } 00765 00766 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 00767 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) { 00768 ms = 0; 00769 } 00770 rtp->txcore = t; 00771 00772 return (unsigned int) ms; 00773 }
static struct ast_frame* create_dtmf_frame | ( | struct ast_rtp_instance * | instance, | |
enum ast_frame_type | type, | |||
int | compensate | |||
) | [static] |
Definition at line 1363 of file res_rtp_asterisk.c.
References AST_CONTROL_FLASH, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_LIST_NEXT, ast_null_frame, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_stringify(), ast_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::f, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, ast_rtp::resp, ast_frame::samples, ast_frame::src, and ast_frame::subclass.
Referenced by ast_rtp_read(), process_dtmf_cisco(), and process_dtmf_rfc2833().
01364 { 01365 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01366 struct ast_sockaddr remote_address = { {0,} }; 01367 01368 ast_rtp_instance_get_remote_address(instance, &remote_address); 01369 01370 if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 01371 ast_debug(1, "Ignore potential DTMF echo from '%s'\n", 01372 ast_sockaddr_stringify(&remote_address)); 01373 rtp->resp = 0; 01374 rtp->dtmfsamples = 0; 01375 return &ast_null_frame; 01376 } 01377 ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, 01378 ast_sockaddr_stringify(&remote_address)); 01379 if (rtp->resp == 'X') { 01380 rtp->f.frametype = AST_FRAME_CONTROL; 01381 rtp->f.subclass.integer = AST_CONTROL_FLASH; 01382 } else { 01383 rtp->f.frametype = type; 01384 rtp->f.subclass.integer = rtp->resp; 01385 } 01386 rtp->f.datalen = 0; 01387 rtp->f.samples = 0; 01388 rtp->f.mallocd = 0; 01389 rtp->f.src = "RTP"; 01390 AST_LIST_NEXT(&rtp->f, frame_list) = NULL; 01391 01392 return &rtp->f; 01393 }
static int create_new_socket | ( | const char * | type, | |
int | af | |||
) | [static] |
Definition at line 414 of file res_rtp_asterisk.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by ast_rtp_new(), and ast_rtp_prop_set().
00415 { 00416 int sock = socket(af, SOCK_DGRAM, 0); 00417 00418 if (sock < 0) { 00419 if (!type) { 00420 type = "RTP/RTCP"; 00421 } 00422 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno)); 00423 } else { 00424 long flags = fcntl(sock, F_GETFL); 00425 fcntl(sock, F_SETFL, flags | O_NONBLOCK); 00426 #ifdef SO_NO_CHECK 00427 if (nochecksums) { 00428 setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00429 } 00430 #endif 00431 } 00432 00433 return sock; 00434 }
static char* handle_cli_rtcp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2655 of file res_rtp_asterisk.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcp_do_debug_ip(), rtcpdebug, rtcpdebugaddr, and ast_cli_entry::usage.
02656 { 02657 switch (cmd) { 02658 case CLI_INIT: 02659 e->command = "rtcp set debug {on|off|ip}"; 02660 e->usage = 02661 "Usage: rtcp set debug {on|off|ip host[:port]}\n" 02662 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 02663 " specified, limit the dumped packets to those to and from\n" 02664 " the specified 'host' with optional port.\n"; 02665 return NULL; 02666 case CLI_GENERATE: 02667 return NULL; 02668 } 02669 02670 if (a->argc == e->args) { /* set on or off */ 02671 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 02672 rtcpdebug = 1; 02673 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 02674 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 02675 return CLI_SUCCESS; 02676 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 02677 rtcpdebug = 0; 02678 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 02679 return CLI_SUCCESS; 02680 } 02681 } else if (a->argc == e->args +1) { /* ip */ 02682 return rtcp_do_debug_ip(a); 02683 } 02684 02685 return CLI_SHOWUSAGE; /* default, failure */ 02686 }
static char* handle_cli_rtcp_set_stats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2688 of file res_rtp_asterisk.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcpstats, and ast_cli_entry::usage.
02689 { 02690 switch (cmd) { 02691 case CLI_INIT: 02692 e->command = "rtcp set stats {on|off}"; 02693 e->usage = 02694 "Usage: rtcp set stats {on|off}\n" 02695 " Enable/Disable dumping of RTCP stats.\n"; 02696 return NULL; 02697 case CLI_GENERATE: 02698 return NULL; 02699 } 02700 02701 if (a->argc != e->args) 02702 return CLI_SHOWUSAGE; 02703 02704 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 02705 rtcpstats = 1; 02706 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 02707 rtcpstats = 0; 02708 else 02709 return CLI_SHOWUSAGE; 02710 02711 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 02712 return CLI_SUCCESS; 02713 }
static char* handle_cli_rtp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2622 of file res_rtp_asterisk.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtp_do_debug_ip(), rtpdebug, rtpdebugaddr, and ast_cli_entry::usage.
02623 { 02624 switch (cmd) { 02625 case CLI_INIT: 02626 e->command = "rtp set debug {on|off|ip}"; 02627 e->usage = 02628 "Usage: rtp set debug {on|off|ip host[:port]}\n" 02629 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 02630 " specified, limit the dumped packets to those to and from\n" 02631 " the specified 'host' with optional port.\n"; 02632 return NULL; 02633 case CLI_GENERATE: 02634 return NULL; 02635 } 02636 02637 if (a->argc == e->args) { /* set on or off */ 02638 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 02639 rtpdebug = 1; 02640 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 02641 ast_cli(a->fd, "RTP Debugging Enabled\n"); 02642 return CLI_SUCCESS; 02643 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 02644 rtpdebug = 0; 02645 ast_cli(a->fd, "RTP Debugging Disabled\n"); 02646 return CLI_SUCCESS; 02647 } 02648 } else if (a->argc == e->args +1) { /* ip */ 02649 return rtp_do_debug_ip(a); 02650 } 02651 02652 return CLI_SHOWUSAGE; /* default, failure */ 02653 }
static int load_module | ( | void | ) | [static] |
Definition at line 2796 of file res_rtp_asterisk.c.
References ARRAY_LEN, ast_cli_register_multiple(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_rtp_engine_register, ast_rtp_engine_unregister(), asterisk_rtp_engine, cli_rtp, and rtp_reload().
02797 { 02798 if (ast_rtp_engine_register(&asterisk_rtp_engine)) { 02799 return AST_MODULE_LOAD_DECLINE; 02800 } 02801 02802 if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) { 02803 ast_rtp_engine_unregister(&asterisk_rtp_engine); 02804 return AST_MODULE_LOAD_DECLINE; 02805 } 02806 02807 rtp_reload(0); 02808 02809 return AST_MODULE_LOAD_SUCCESS; 02810 }
static double normdev_compute | ( | double | normdev, | |
double | sample, | |||
unsigned int | sample_count | |||
) | [static] |
Calculate normal deviation.
Definition at line 386 of file res_rtp_asterisk.c.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().
00387 { 00388 normdev = normdev * sample_count + sample; 00389 sample_count++; 00390 00391 return normdev / sample_count; 00392 }
static struct ast_frame* process_cn_rfc3389 | ( | struct ast_rtp_instance * | instance, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp, | |||
struct ast_sockaddr * | addr, | |||
int | payloadtype, | |||
int | mark | |||
) | [static] |
Definition at line 1599 of file res_rtp_asterisk.c.
References ast_debug, AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_set_flag, ast_sockaddr_stringify(), ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, FLAG_3389_WARNING, ast_frame::frametype, ast_frame_subclass::integer, ast_rtp::lastrxformat, LOG_NOTICE, ast_frame::offset, ast_frame::ptr, ast_rtp::rawdata, rtpdebug, ast_frame::samples, and ast_frame::subclass.
Referenced by ast_rtp_read().
01600 { 01601 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01602 01603 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 01604 totally help us out becuase we don't have an engine to keep it going and we are not 01605 guaranteed to have it every 20ms or anything */ 01606 if (rtpdebug) 01607 ast_debug(0, "- RTP 3389 Comfort noise event: Level %" PRId64 " (len = %d)\n", rtp->lastrxformat, len); 01608 01609 if (ast_test_flag(rtp, FLAG_3389_WARNING)) { 01610 struct ast_sockaddr remote_address = { {0,} }; 01611 01612 ast_rtp_instance_get_remote_address(instance, &remote_address); 01613 01614 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n", 01615 ast_sockaddr_stringify(&remote_address)); 01616 ast_set_flag(rtp, FLAG_3389_WARNING); 01617 } 01618 01619 /* Must have at least one byte */ 01620 if (!len) 01621 return NULL; 01622 if (len < 24) { 01623 rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET; 01624 rtp->f.datalen = len - 1; 01625 rtp->f.offset = AST_FRIENDLY_OFFSET; 01626 memcpy(rtp->f.data.ptr, data + 1, len - 1); 01627 } else { 01628 rtp->f.data.ptr = NULL; 01629 rtp->f.offset = 0; 01630 rtp->f.datalen = 0; 01631 } 01632 rtp->f.frametype = AST_FRAME_CNG; 01633 rtp->f.subclass.integer = data[0] & 0x7f; 01634 rtp->f.samples = 0; 01635 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 01636 01637 return &rtp->f; 01638 }
static struct ast_frame* process_dtmf_cisco | ( | struct ast_rtp_instance * | instance, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp, | |||
struct ast_sockaddr * | addr, | |||
int | payloadtype, | |||
int | mark | |||
) | [static] |
Definition at line 1520 of file res_rtp_asterisk.c.
References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_DTMF_COMPENSATE, create_dtmf_frame(), ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, ast_rtp::flags, ast_rtp::lastrxformat, option_debug, ast_rtp::resp, rtp_get_rate(), rtpdebug, and seq.
Referenced by ast_rtp_read().
01521 { 01522 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01523 unsigned int event, flags, power; 01524 char resp = 0; 01525 unsigned char seq; 01526 struct ast_frame *f = NULL; 01527 01528 if (len < 4) { 01529 return NULL; 01530 } 01531 01532 /* The format of Cisco RTP DTMF packet looks like next: 01533 +0 - sequence number of DTMF RTP packet (begins from 1, 01534 wrapped to 0) 01535 +1 - set of flags 01536 +1 (bit 0) - flaps by different DTMF digits delimited by audio 01537 or repeated digit without audio??? 01538 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone 01539 then falls to 0 at its end) 01540 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...) 01541 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right 01542 by each new packet and thus provides some redudancy. 01543 01544 Sample of Cisco RTP DTMF packet is (all data in hex): 01545 19 07 00 02 12 02 20 02 01546 showing end of DTMF digit '2'. 01547 01548 The packets 01549 27 07 00 02 0A 02 20 02 01550 28 06 20 02 00 02 0A 02 01551 shows begin of new digit '2' with very short pause (20 ms) after 01552 previous digit '2'. Bit +1.0 flips at begin of new digit. 01553 01554 Cisco RTP DTMF packets comes as replacement of audio RTP packets 01555 so its uses the same sequencing and timestamping rules as replaced 01556 audio packets. Repeat interval of DTMF packets is 20 ms and not rely 01557 on audio framing parameters. Marker bit isn't used within stream of 01558 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps 01559 are not sequential at borders between DTMF and audio streams, 01560 */ 01561 01562 seq = data[0]; 01563 flags = data[1]; 01564 power = data[2]; 01565 event = data[3] & 0x1f; 01566 01567 if (option_debug > 2 || rtpdebug) 01568 ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2); 01569 if (event < 10) { 01570 resp = '0' + event; 01571 } else if (event < 11) { 01572 resp = '*'; 01573 } else if (event < 12) { 01574 resp = '#'; 01575 } else if (event < 16) { 01576 resp = 'A' + (event - 12); 01577 } else if (event < 17) { 01578 resp = 'X'; 01579 } 01580 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) { 01581 rtp->resp = resp; 01582 /* Why we should care on DTMF compensation at reception? */ 01583 if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) { 01584 f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0); 01585 rtp->dtmfsamples = 0; 01586 } 01587 } else if ((rtp->resp == resp) && !power) { 01588 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)); 01589 f->samples = rtp->dtmfsamples * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8); 01590 rtp->resp = 0; 01591 } else if (rtp->resp == resp) 01592 rtp->dtmfsamples += 20 * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8); 01593 01594 rtp->dtmf_timeout = 0; 01595 01596 return f; 01597 }
static void process_dtmf_rfc2833 | ( | struct ast_rtp_instance * | instance, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno, | |||
unsigned int | timestamp, | |||
struct ast_sockaddr * | addr, | |||
int | payloadtype, | |||
int | mark, | |||
struct frame_list * | frames | |||
) | [static] |
Definition at line 1395 of file res_rtp_asterisk.c.
References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup(), AST_LIST_INSERT_TAIL, ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_samp2tv(), ast_sockaddr_stringify(), ast_tv(), ast_tvdiff_ms(), ast_verbose, create_dtmf_frame(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, dtmftimeout, f, frames, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_debug_test_addr(), rtp_get_rate(), and rtpdebug.
Referenced by ast_rtp_read().
01396 { 01397 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01398 struct ast_sockaddr remote_address = { {0,} }; 01399 unsigned int event, event_end, samples; 01400 char resp = 0; 01401 struct ast_frame *f = NULL; 01402 01403 ast_rtp_instance_get_remote_address(instance, &remote_address); 01404 01405 /* Figure out event, event end, and samples */ 01406 event = ntohl(*((unsigned int *)(data))); 01407 event >>= 24; 01408 event_end = ntohl(*((unsigned int *)(data))); 01409 event_end <<= 8; 01410 event_end >>= 24; 01411 samples = ntohl(*((unsigned int *)(data))); 01412 samples &= 0xFFFF; 01413 01414 if (rtp_debug_test_addr(&remote_address)) { 01415 ast_verbose("Got RTP RFC2833 from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", 01416 ast_sockaddr_stringify(&remote_address), 01417 payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples); 01418 } 01419 01420 /* Print out debug if turned on */ 01421 if (rtpdebug || option_debug > 2) 01422 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 01423 01424 /* Figure out what digit was pressed */ 01425 if (event < 10) { 01426 resp = '0' + event; 01427 } else if (event < 11) { 01428 resp = '*'; 01429 } else if (event < 12) { 01430 resp = '#'; 01431 } else if (event < 16) { 01432 resp = 'A' + (event - 12); 01433 } else if (event < 17) { /* Event 16: Hook flash */ 01434 resp = 'X'; 01435 } else { 01436 /* Not a supported event */ 01437 ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 01438 return; 01439 } 01440 01441 if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) { 01442 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 01443 rtp->resp = resp; 01444 rtp->dtmf_timeout = 0; 01445 f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE))); 01446 f->len = 0; 01447 rtp->lastevent = timestamp; 01448 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01449 } 01450 } else { 01451 /* The duration parameter measures the complete 01452 duration of the event (from the beginning) - RFC2833. 01453 Account for the fact that duration is only 16 bits long 01454 (about 8 seconds at 8000 Hz) and can wrap is digit 01455 is hold for too long. */ 01456 unsigned int new_duration = rtp->dtmf_duration; 01457 unsigned int last_duration = new_duration & 0xFFFF; 01458 01459 if (last_duration > 64000 && samples < last_duration) { 01460 new_duration += 0xFFFF + 1; 01461 } 01462 new_duration = (new_duration & ~0xFFFF) | samples; 01463 01464 /* The second portion of this check is to not mistakenly 01465 * stop accepting DTMF if the seqno rolls over beyond 01466 * 65535. 01467 */ 01468 if (rtp->lastevent > seqno && rtp->lastevent - seqno < 50) { 01469 /* Out of order frame. Processing this can cause us to 01470 * improperly duplicate incoming DTMF, so just drop 01471 * this. 01472 */ 01473 return; 01474 } 01475 01476 if (event_end & 0x80) { 01477 /* End event */ 01478 if ((rtp->lastevent != seqno) && rtp->resp) { 01479 rtp->dtmf_duration = new_duration; 01480 f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0)); 01481 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0)); 01482 rtp->resp = 0; 01483 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01484 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01485 } 01486 } else { 01487 /* Begin/continuation */ 01488 01489 if (rtp->resp && rtp->resp != resp) { 01490 /* Another digit already began. End it */ 01491 f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0)); 01492 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0)); 01493 rtp->resp = 0; 01494 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01495 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01496 } 01497 01498 if (rtp->resp) { 01499 /* Digit continues */ 01500 rtp->dtmf_duration = new_duration; 01501 } else { 01502 /* New digit began */ 01503 rtp->resp = resp; 01504 f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0)); 01505 rtp->dtmf_duration = samples; 01506 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01507 } 01508 01509 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout; 01510 } 01511 01512 rtp->lastevent = seqno; 01513 } 01514 01515 rtp->dtmfsamples = samples; 01516 01517 return; 01518 }
Definition at line 1157 of file res_rtp_asterisk.c.
References ast_frame::data, ast_frame::datalen, rtp_red::hdrlen, rtp_red::len, len(), rtp_red::num_gen, ast_frame::ptr, rtp_red::t140, and rtp_red::t140red.
Referenced by ast_rtp_write().
01157 { 01158 unsigned char *data = red->t140red.data.ptr; 01159 int len = 0; 01160 int i; 01161 01162 /* replace most aged generation */ 01163 if (red->len[0]) { 01164 for (i = 1; i < red->num_gen+1; i++) 01165 len += red->len[i]; 01166 01167 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len); 01168 } 01169 01170 /* Store length of each generation and primary data length*/ 01171 for (i = 0; i < red->num_gen; i++) 01172 red->len[i] = red->len[i+1]; 01173 red->len[i] = red->t140.datalen; 01174 01175 /* write each generation length in red header */ 01176 len = red->hdrlen; 01177 for (i = 0; i < red->num_gen; i++) 01178 len += data[i*4+3] = red->len[i]; 01179 01180 /* add primary data to buffer */ 01181 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen); 01182 red->t140red.datalen = len + red->t140.datalen; 01183 01184 /* no primary data and no generations to send */ 01185 if (len == red->hdrlen && !red->t140.datalen) 01186 return NULL; 01187 01188 /* reset t.140 buffer */ 01189 red->t140.datalen = 0; 01190 01191 return &red->t140red; 01192 }
static int red_write | ( | const void * | data | ) | [static] |
Write t140 redundacy frame.
data | primary data to be buffered |
Definition at line 2423 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_rtp_write(), ast_rtp::red, and rtp_red::t140.
Referenced by rtp_red_init().
02424 { 02425 struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data; 02426 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02427 02428 ast_rtp_write(instance, &rtp->red->t140); 02429 02430 return 1; 02431 }
static int reload_module | ( | void | ) | [static] |
Definition at line 2790 of file res_rtp_asterisk.c.
References rtp_reload().
02791 { 02792 rtp_reload(1); 02793 return 0; 02794 }
static int rtcp_debug_test_addr | ( | struct ast_sockaddr * | addr | ) | [inline, static] |
Definition at line 311 of file res_rtp_asterisk.c.
References ast_sockaddr_cmp(), ast_sockaddr_isnull(), and rtcpdebugaddr.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr().
00312 { 00313 if (!rtcpdebug) { 00314 return 0; 00315 } 00316 00317 return ast_sockaddr_isnull(&rtcpdebugaddr) ? 1 : ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0; 00318 }
static char* rtcp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 2608 of file res_rtp_asterisk.c.
References ast_cli_args::argv, ast_cli(), ast_sockaddr_parse(), ast_sockaddr_stringify(), ast_strdupa, CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, rtcpdebug, and rtcpdebugaddr.
Referenced by handle_cli_rtcp_set_debug().
02609 { 02610 char *arg = ast_strdupa(a->argv[4]); 02611 02612 if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0)) { 02613 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 02614 return CLI_FAILURE; 02615 } 02616 ast_cli(a->fd, "RTCP Debugging Enabled for address: %s\n", 02617 ast_sockaddr_stringify(&rtcpdebugaddr)); 02618 rtcpdebug = 1; 02619 return CLI_SUCCESS; 02620 }
static int rtcp_recvfrom | ( | struct ast_rtp_instance * | instance, | |
void * | buf, | |||
size_t | size, | |||
int | flags, | |||
struct ast_sockaddr * | sa | |||
) | [static] |
Definition at line 337 of file res_rtp_asterisk.c.
References __rtp_recvfrom().
Referenced by ast_rtcp_read().
00338 { 00339 return __rtp_recvfrom(instance, buf, size, flags, sa, 1); 00340 }
static int rtcp_sendto | ( | struct ast_rtp_instance * | instance, | |
void * | buf, | |||
size_t | size, | |||
int | flags, | |||
struct ast_sockaddr * | sa | |||
) | [static] |
Definition at line 361 of file res_rtp_asterisk.c.
References __rtp_sendto().
Referenced by ast_rtcp_write_rr(), and ast_rtcp_write_sr().
00362 { 00363 return __rtp_sendto(instance, buf, size, flags, sa, 1); 00364 }
static int rtp_debug_test_addr | ( | struct ast_sockaddr * | addr | ) | [inline, static] |
Definition at line 302 of file res_rtp_asterisk.c.
References ast_sockaddr_cmp(), ast_sockaddr_isnull(), and rtpdebugaddr.
Referenced by ast_rtp_dtmf_begin(), ast_rtp_dtmf_continuation(), ast_rtp_dtmf_end_with_duration(), ast_rtp_raw_write(), ast_rtp_read(), bridge_p2p_rtp_write(), and process_dtmf_rfc2833().
00303 { 00304 if (!rtpdebug) { 00305 return 0; 00306 } 00307 00308 return ast_sockaddr_isnull(&rtpdebugaddr) ? 1 : ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0; 00309 }
static char* rtp_do_debug_ip | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 2594 of file res_rtp_asterisk.c.
References ast_cli_args::argv, ast_cli(), ast_sockaddr_parse(), ast_sockaddr_stringify(), ast_strdupa, CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, rtpdebug, and rtpdebugaddr.
Referenced by handle_cli_rtp_set_debug().
02595 { 02596 char *arg = ast_strdupa(a->argv[4]); 02597 02598 if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0)) { 02599 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 02600 return CLI_FAILURE; 02601 } 02602 ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n", 02603 ast_sockaddr_stringify(&rtpdebugaddr)); 02604 rtpdebug = 1; 02605 return CLI_SUCCESS; 02606 }
static int rtp_get_rate | ( | format_t | subclass | ) | [static] |
Definition at line 371 of file res_rtp_asterisk.c.
References AST_FORMAT_G722, and ast_format_rate().
Referenced by ast_rtp_dtmf_end_with_duration(), ast_rtp_raw_write(), ast_rtp_read(), calc_rxstamp(), process_dtmf_cisco(), and process_dtmf_rfc2833().
00372 { 00373 return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass); 00374 }
static int rtp_recvfrom | ( | struct ast_rtp_instance * | instance, | |
void * | buf, | |||
size_t | size, | |||
int | flags, | |||
struct ast_sockaddr * | sa | |||
) | [static] |
Definition at line 342 of file res_rtp_asterisk.c.
References __rtp_recvfrom().
Referenced by ast_rtp_read().
00343 { 00344 return __rtp_recvfrom(instance, buf, size, flags, sa, 0); 00345 }
static int rtp_red_buffer | ( | struct ast_rtp_instance * | instance, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 2468 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::ptr, ast_rtp::red, rtp_red::t140, and ast_frame::ts.
02469 { 02470 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02471 02472 if (frame->datalen > -1) { 02473 struct rtp_red *red = rtp->red; 02474 memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen); 02475 red->t140.datalen += frame->datalen; 02476 red->t140.ts = frame->ts; 02477 } 02478 02479 return 0; 02480 }
static int rtp_red_init | ( | struct ast_rtp_instance * | instance, | |
int | buffer_time, | |||
int * | payloads, | |||
int | generations | |||
) | [static] |
Definition at line 2433 of file res_rtp_asterisk.c.
References ast_calloc, AST_FORMAT_T140RED, AST_FRAME_TEXT, ast_rtp_instance_get_data(), ast_sched_add(), rtp_red::buf_data, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, rtp_red::hdrlen, rtp_red::num_gen, rtp_red::prev_ts, rtp_red::pt, ast_frame::ptr, ast_rtp::red, red_write(), ast_rtp::sched, rtp_red::schedid, ast_frame::subclass, rtp_red::t140, rtp_red::t140red, rtp_red::t140red_data, rtp_red::ti, and ast_frame::ts.
02434 { 02435 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02436 int x; 02437 02438 if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) { 02439 return -1; 02440 } 02441 02442 rtp->red->t140.frametype = AST_FRAME_TEXT; 02443 rtp->red->t140.subclass.codec = AST_FORMAT_T140RED; 02444 rtp->red->t140.data.ptr = &rtp->red->buf_data; 02445 02446 rtp->red->t140.ts = 0; 02447 rtp->red->t140red = rtp->red->t140; 02448 rtp->red->t140red.data.ptr = &rtp->red->t140red_data; 02449 rtp->red->t140red.datalen = 0; 02450 rtp->red->ti = buffer_time; 02451 rtp->red->num_gen = generations; 02452 rtp->red->hdrlen = generations * 4 + 1; 02453 rtp->red->prev_ts = 0; 02454 02455 for (x = 0; x < generations; x++) { 02456 rtp->red->pt[x] = payloads[x]; 02457 rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */ 02458 rtp->red->t140red_data[x*4] = rtp->red->pt[x]; 02459 } 02460 rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */ 02461 rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance); 02462 02463 rtp->red->t140.datalen = 0; 02464 02465 return 0; 02466 }
static int rtp_reload | ( | int | reload | ) | [static] |
Definition at line 2721 of file res_rtp_asterisk.c.
References ast_config_destroy(), ast_config_load2(), ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTMF_TIMEOUT, DEFAULT_RTP_END, DEFAULT_RTP_START, dtmftimeout, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, STRICT_RTP_OPEN, and strictrtp.
Referenced by load_module(), and reload_module().
02722 { 02723 struct ast_config *cfg; 02724 const char *s; 02725 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02726 02727 cfg = ast_config_load2("rtp.conf", "rtp", config_flags); 02728 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) { 02729 return 0; 02730 } 02731 02732 rtpstart = DEFAULT_RTP_START; 02733 rtpend = DEFAULT_RTP_END; 02734 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 02735 strictrtp = STRICT_RTP_OPEN; 02736 if (cfg) { 02737 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 02738 rtpstart = atoi(s); 02739 if (rtpstart < MINIMUM_RTP_PORT) 02740 rtpstart = MINIMUM_RTP_PORT; 02741 if (rtpstart > MAXIMUM_RTP_PORT) 02742 rtpstart = MAXIMUM_RTP_PORT; 02743 } 02744 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 02745 rtpend = atoi(s); 02746 if (rtpend < MINIMUM_RTP_PORT) 02747 rtpend = MINIMUM_RTP_PORT; 02748 if (rtpend > MAXIMUM_RTP_PORT) 02749 rtpend = MAXIMUM_RTP_PORT; 02750 } 02751 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 02752 rtcpinterval = atoi(s); 02753 if (rtcpinterval == 0) 02754 rtcpinterval = 0; /* Just so we're clear... it's zero */ 02755 if (rtcpinterval < RTCP_MIN_INTERVALMS) 02756 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 02757 if (rtcpinterval > RTCP_MAX_INTERVALMS) 02758 rtcpinterval = RTCP_MAX_INTERVALMS; 02759 } 02760 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 02761 #ifdef SO_NO_CHECK 02762 nochecksums = ast_false(s) ? 1 : 0; 02763 #else 02764 if (ast_false(s)) 02765 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 02766 #endif 02767 } 02768 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 02769 dtmftimeout = atoi(s); 02770 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) { 02771 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 02772 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 02773 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 02774 }; 02775 } 02776 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) { 02777 strictrtp = ast_true(s); 02778 } 02779 ast_config_destroy(cfg); 02780 } 02781 if (rtpstart >= rtpend) { 02782 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 02783 rtpstart = DEFAULT_RTP_START; 02784 rtpend = DEFAULT_RTP_END; 02785 } 02786 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 02787 return 0; 02788 }
static int rtp_sendto | ( | struct ast_rtp_instance * | instance, | |
void * | buf, | |||
size_t | size, | |||
int | flags, | |||
struct ast_sockaddr * | sa | |||
) | [static] |
Definition at line 366 of file res_rtp_asterisk.c.
References __rtp_sendto().
Referenced by ast_rtp_dtmf_begin(), ast_rtp_dtmf_continuation(), ast_rtp_dtmf_end_with_duration(), ast_rtp_raw_write(), and bridge_p2p_rtp_write().
00367 { 00368 return __rtp_sendto(instance, buf, size, flags, sa, 0); 00369 }
static double stddev_compute | ( | double | stddev, | |
double | sample, | |||
double | normdev, | |||
double | normdev_curent, | |||
unsigned int | sample_count | |||
) | [static] |
Definition at line 394 of file res_rtp_asterisk.c.
References SQUARE.
Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().
00395 { 00396 /* 00397 for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf 00398 return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1)); 00399 we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute 00400 optimized formula 00401 */ 00402 #define SQUARE(x) ((x) * (x)) 00403 00404 stddev = sample_count * stddev; 00405 sample_count++; 00406 00407 return stddev + 00408 ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) + 00409 ( SQUARE(sample - normdev_curent) / sample_count ); 00410 00411 #undef SQUARE 00412 }
static void timeval2ntp | ( | struct timeval | tv, | |
unsigned int * | msw, | |||
unsigned int * | lsw | |||
) | [static] |
Definition at line 775 of file res_rtp_asterisk.c.
Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().
00776 { 00777 unsigned int sec, usec, frac; 00778 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */ 00779 usec = tv.tv_usec; 00780 frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6); 00781 *msw = sec; 00782 *lsw = frac; 00783 }
static int unload_module | ( | void | ) | [static] |
Definition at line 2812 of file res_rtp_asterisk.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_rtp_engine_unregister(), asterisk_rtp_engine, and cli_rtp.
02813 { 02814 ast_rtp_engine_unregister(&asterisk_rtp_engine); 02815 ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp)); 02816 02817 return 0; 02818 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RTP Stack" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 2825 of file res_rtp_asterisk.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 2825 of file res_rtp_asterisk.c.
struct ast_rtp_engine asterisk_rtp_engine [static] |
Definition at line 277 of file res_rtp_asterisk.c.
Referenced by load_module(), and unload_module().
struct ast_cli_entry cli_rtp[] [static] |
Initial value:
{ { .handler = handle_cli_rtp_set_debug , .summary = "Enable/Disable RTP debugging" ,__VA_ARGS__ }, { .handler = handle_cli_rtcp_set_debug , .summary = "Enable/Disable RTCP debugging" ,__VA_ARGS__ }, { .handler = handle_cli_rtcp_set_stats , .summary = "Enable/Disable RTCP stats" ,__VA_ARGS__ }, }
Definition at line 2715 of file res_rtp_asterisk.c.
Referenced by load_module(), and unload_module().
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
Definition at line 80 of file res_rtp_asterisk.c.
Referenced by process_dtmf_rfc2833(), and rtp_reload().
struct ast_srtp_res* res_srtp |
Definition at line 43 of file rtp_engine.c.
Referenced by __rtp_recvfrom(), __rtp_sendto(), ast_rtp_change_source(), ast_rtp_engine_register_srtp(), ast_rtp_engine_srtp_is_registered(), ast_rtp_engine_unregister_srtp(), ast_rtp_instance_add_srtp_policy(), and instance_destructor().
int rtcpdebug [static] |
Are we debugging RTCP?
Definition at line 85 of file res_rtp_asterisk.c.
Referenced by handle_cli_rtcp_set_debug(), and rtcp_do_debug_ip().
struct ast_sockaddr rtcpdebugaddr [static] |
Debug RTCP packets to/from this host
Definition at line 89 of file res_rtp_asterisk.c.
Referenced by handle_cli_rtcp_set_debug(), rtcp_debug_test_addr(), and rtcp_do_debug_ip().
int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static] |
Time between rtcp reports in millisecs
Definition at line 87 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
int rtcpstats [static] |
Are we debugging RTCP?
Definition at line 86 of file res_rtp_asterisk.c.
Referenced by handle_cli_rtcp_set_stats().
int rtpdebug [static] |
Are we debugging?
Definition at line 84 of file res_rtp_asterisk.c.
Referenced by ast_rtcp_read(), ast_rtp_raw_write(), ast_rtp_read(), bridge_p2p_rtp_write(), handle_cli_rtp_set_debug(), process_cn_rfc3389(), process_dtmf_cisco(), process_dtmf_rfc2833(), and rtp_do_debug_ip().
struct ast_sockaddr rtpdebugaddr [static] |
Debug packets to/from this host
Definition at line 88 of file res_rtp_asterisk.c.
Referenced by handle_cli_rtp_set_debug(), rtp_debug_test_addr(), and rtp_do_debug_ip().
int rtpend = DEFAULT_RTP_END [static] |
Last port for RTP sessions (set in rtp.conf)
Definition at line 83 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
int rtpstart = DEFAULT_RTP_START [static] |
First port for RTP sessions (set in rtp.conf)
Definition at line 82 of file res_rtp_asterisk.c.
Referenced by rtp_reload().
int strictrtp [static] |
Definition at line 93 of file res_rtp_asterisk.c.
Referenced by ast_rtp_remote_address_set(), and rtp_reload().