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