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