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