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