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