#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 ast_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 (struct ast_format *format) |
| 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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_rtp_engine | asterisk_rtp_engine |
| static struct ast_cli_entry | cli_rtp [] |
| static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
| static int | learning_min_sequential |
| struct ast_srtp_res * | res_srtp |
| static int | rtcpdebug |
| static struct ast_sockaddr | rtcpdebugaddr |
| static int | rtcpdebugport |
| static int | rtcpinterval = RTCP_DEFAULT_INTERVALMS |
| static int | rtcpstats |
| static int | rtpdebug |
| static struct ast_sockaddr | rtpdebugaddr |
| static int | rtpdebugport |
| static int | rtpend = DEFAULT_RTP_END |
| static int | rtpstart = DEFAULT_RTP_START |
| static int | strictrtp |
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 3053 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(), ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, 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, ast_rtp::rtcp, ast_rtp::s, and ast_rtcp::s.
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 3053 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, read] |
Definition at line 1760 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_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, normdev_compute(), ast_rtcp::normdevrtt, ast_rtcp::reported_jitter, ast_rtcp::reported_jitter_count, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtcp_info, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, rtcp_recvfrom(), ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::rxlsr, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, stddev_compute(), ast_rtcp::stdevrtt, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().
Referenced by ast_rtp_read().
01761 { 01762 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01763 struct ast_sockaddr addr; 01764 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 01765 unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 01766 int res, packetwords, position = 0; 01767 struct ast_frame *f = &ast_null_frame; 01768 01769 /* Read in RTCP data from the socket */ 01770 if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET, 01771 sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 01772 0, &addr)) < 0) { 01773 ast_assert(errno != EBADF); 01774 if (errno != EAGAIN) { 01775 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 01776 return NULL; 01777 } 01778 return &ast_null_frame; 01779 } 01780 01781 packetwords = res / 4; 01782 01783 if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) { 01784 /* Send to whoever sent to us */ 01785 if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) { 01786 ast_sockaddr_copy(&rtp->rtcp->them, &addr); 01787 if (rtpdebug) 01788 ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n", 01789 ast_sockaddr_stringify(&rtp->rtcp->them)); 01790 } 01791 } 01792 01793 ast_debug(1, "Got RTCP report of %d bytes\n", res); 01794 01795 while (position < packetwords) { 01796 int i, pt, rc; 01797 unsigned int length, dlsr, lsr, msw, lsw, comp; 01798 struct timeval now; 01799 double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current; 01800 uint64_t rtt = 0; 01801 01802 i = position; 01803 length = ntohl(rtcpheader[i]); 01804 pt = (length & 0xff0000) >> 16; 01805 rc = (length & 0x1f000000) >> 24; 01806 length &= 0xffff; 01807 01808 if ((i + length) > packetwords) { 01809 if (rtpdebug) 01810 ast_debug(1, "RTCP Read too short\n"); 01811 return &ast_null_frame; 01812 } 01813 01814 if (rtcp_debug_test_addr(&addr)) { 01815 ast_verbose("\n\nGot RTCP from %s\n", 01816 ast_sockaddr_stringify(&addr)); 01817 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 01818 ast_verbose("Reception reports: %d\n", rc); 01819 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 01820 } 01821 01822 i += 2; /* Advance past header and ssrc */ 01823 if (rc == 0 && pt == RTCP_PT_RR) { /* We're receiving a receiver report with no reports, which is ok */ 01824 position += (length + 1); 01825 continue; 01826 } 01827 01828 switch (pt) { 01829 case RTCP_PT_SR: 01830 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 01831 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 01832 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 01833 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 01834 01835 if (rtcp_debug_test_addr(&addr)) { 01836 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 01837 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 01838 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 01839 } 01840 i += 5; 01841 if (rc < 1) 01842 break; 01843 /* Intentional fall through */ 01844 case RTCP_PT_RR: 01845 /* Don't handle multiple reception reports (rc > 1) yet */ 01846 /* Calculate RTT per RFC */ 01847 gettimeofday(&now, NULL); 01848 timeval2ntp(now, &msw, &lsw); 01849 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 01850 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 01851 lsr = ntohl(rtcpheader[i + 4]); 01852 dlsr = ntohl(rtcpheader[i + 5]); 01853 rtt = comp - lsr - dlsr; 01854 01855 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 01856 sess->ee_delay = (eedelay * 1000) / 65536; */ 01857 if (rtt < 4294) { 01858 rtt = (rtt * 1000000) >> 16; 01859 } else { 01860 rtt = (rtt * 1000) >> 16; 01861 rtt *= 1000; 01862 } 01863 rtt = rtt / 1000.; 01864 rttsec = rtt / 1000.; 01865 rtp->rtcp->rtt = rttsec; 01866 01867 if (comp - dlsr >= lsr) { 01868 rtp->rtcp->accumulated_transit += rttsec; 01869 01870 if (rtp->rtcp->rtt_count == 0) 01871 rtp->rtcp->minrtt = rttsec; 01872 01873 if (rtp->rtcp->maxrtt<rttsec) 01874 rtp->rtcp->maxrtt = rttsec; 01875 if (rtp->rtcp->minrtt>rttsec) 01876 rtp->rtcp->minrtt = rttsec; 01877 01878 normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count); 01879 01880 rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count); 01881 01882 rtp->rtcp->normdevrtt = normdevrtt_current; 01883 01884 rtp->rtcp->rtt_count++; 01885 } else if (rtcp_debug_test_addr(&addr)) { 01886 ast_verbose("Internal RTCP NTP clock skew detected: " 01887 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 01888 "diff=%d\n", 01889 lsr, comp, dlsr, dlsr / 65536, 01890 (dlsr % 65536) * 1000 / 65536, 01891 dlsr - (comp - lsr)); 01892 } 01893 } 01894 01895 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 01896 reported_jitter = (double) rtp->rtcp->reported_jitter; 01897 01898 if (rtp->rtcp->reported_jitter_count == 0) 01899 rtp->rtcp->reported_minjitter = reported_jitter; 01900 01901 if (reported_jitter < rtp->rtcp->reported_minjitter) 01902 rtp->rtcp->reported_minjitter = reported_jitter; 01903 01904 if (reported_jitter > rtp->rtcp->reported_maxjitter) 01905 rtp->rtcp->reported_maxjitter = reported_jitter; 01906 01907 reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count); 01908 01909 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); 01910 01911 rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current; 01912 01913 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 01914 01915 reported_lost = (double) rtp->rtcp->reported_lost; 01916 01917 /* using same counter as for jitter */ 01918 if (rtp->rtcp->reported_jitter_count == 0) 01919 rtp->rtcp->reported_minlost = reported_lost; 01920 01921 if (reported_lost < rtp->rtcp->reported_minlost) 01922 rtp->rtcp->reported_minlost = reported_lost; 01923 01924 if (reported_lost > rtp->rtcp->reported_maxlost) 01925 rtp->rtcp->reported_maxlost = reported_lost; 01926 reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count); 01927 01928 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); 01929 01930 rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current; 01931 01932 rtp->rtcp->reported_jitter_count++; 01933 01934 if (rtcp_debug_test_addr(&addr)) { 01935 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 01936 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 01937 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 01938 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 01939 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 01940 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 01941 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 01942 if (rtt) 01943 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 01944 } 01945 if (rtt) { 01946 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s\r\n" 01947 "PT: %d(%s)\r\n" 01948 "ReceptionReports: %d\r\n" 01949 "SenderSSRC: %u\r\n" 01950 "FractionLost: %ld\r\n" 01951 "PacketsLost: %d\r\n" 01952 "HighestSequence: %ld\r\n" 01953 "SequenceNumberCycles: %ld\r\n" 01954 "IAJitter: %u\r\n" 01955 "LastSR: %lu.%010lu\r\n" 01956 "DLSR: %4.4f(sec)\r\n" 01957 "RTT: %llu(sec)\r\n", 01958 ast_sockaddr_stringify(&addr), 01959 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01960 rc, 01961 rtcpheader[i + 1], 01962 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01963 rtp->rtcp->reported_lost, 01964 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01965 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01966 rtp->rtcp->reported_jitter, 01967 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01968 ntohl(rtcpheader[i + 5])/65536.0, 01969 (unsigned long long)rtt); 01970 } else { 01971 manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s\r\n" 01972 "PT: %d(%s)\r\n" 01973 "ReceptionReports: %d\r\n" 01974 "SenderSSRC: %u\r\n" 01975 "FractionLost: %ld\r\n" 01976 "PacketsLost: %d\r\n" 01977 "HighestSequence: %ld\r\n" 01978 "SequenceNumberCycles: %ld\r\n" 01979 "IAJitter: %u\r\n" 01980 "LastSR: %lu.%010lu\r\n" 01981 "DLSR: %4.4f(sec)\r\n", 01982 ast_sockaddr_stringify(&addr), 01983 pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown", 01984 rc, 01985 rtcpheader[i + 1], 01986 (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24), 01987 rtp->rtcp->reported_lost, 01988 (long) (ntohl(rtcpheader[i + 2]) & 0xffff), 01989 (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16, 01990 rtp->rtcp->reported_jitter, 01991 (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, 01992 ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096, 01993 ntohl(rtcpheader[i + 5])/65536.0); 01994 } 01995 break; 01996 case RTCP_PT_FUR: 01997 if (rtcp_debug_test_addr(&addr)) 01998 ast_verbose("Received an RTCP Fast Update Request\n"); 01999 rtp->f.frametype = AST_FRAME_CONTROL; 02000 rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE; 02001 rtp->f.datalen = 0; 02002 rtp->f.samples = 0; 02003 rtp->f.mallocd = 0; 02004 rtp->f.src = "RTP"; 02005 f = &rtp->f; 02006 break; 02007 case RTCP_PT_SDES: 02008 if (rtcp_debug_test_addr(&addr)) 02009 ast_verbose("Received an SDES from %s\n", 02010 ast_sockaddr_stringify(&rtp->rtcp->them)); 02011 break; 02012 case RTCP_PT_BYE: 02013 if (rtcp_debug_test_addr(&addr)) 02014 ast_verbose("Received a BYE from %s\n", 02015 ast_sockaddr_stringify(&rtp->rtcp->them)); 02016 break; 02017 default: 02018 ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s\n", 02019 pt, ast_sockaddr_stringify(&rtp->rtcp->them)); 02020 break; 02021 } 02022 position += (length + 1); 02023 } 02024 02025 rtp->rtcp->rtcp_info = 1; 02026 02027 return f; 02028 }
| 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_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::f, ast_frame_subclass::format, 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.format); 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_rtp::cycles, errno, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::f, ast_frame_subclass::format, 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.format); 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 2575 of file res_rtp_asterisk.c.
References ast_rtp::alt_rtp_address, ast_rtp_instance_get_data(), and ast_sockaddr_copy().
02576 { 02577 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02578 02579 /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving 02580 * RTCP from an "unexpected" source 02581 */ 02582 ast_sockaddr_copy(&rtp->alt_rtp_address, addr); 02583 02584 return; 02585 }
| 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, ast_rtp::lastts, and ast_rtp::ssrc.
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, NULL, 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 2706 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.
02707 { 02708 /* If both sides are not using the same method of DTMF transmission 02709 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 02710 * -------------------------------------------------- 02711 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 02712 * |-----------|------------|-----------------------| 02713 * | Inband | False | True | 02714 * | RFC2833 | True | True | 02715 * | SIP INFO | False | False | 02716 * -------------------------------------------------- 02717 */ 02718 return (((ast_rtp_instance_get_prop(instance0, AST_RTP_PROPERTY_DTMF) != ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_DTMF)) || 02719 (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1); 02720 }
| 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_rtp::dtmfmute, errno, ast_rtp::f, ast_frame_subclass::format, 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.format) / 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 2545 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_rtp::rtcp, ast_rtp::s, and ast_rtcp::s.
02546 { 02547 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02548 02549 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s; 02550 }
| 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 2658 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.
02659 { 02660 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02661 02662 if (!rtp->rtcp) { 02663 return -1; 02664 } 02665 02666 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount); 02667 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount); 02668 02669 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->txploss, rtp->rtcp->reported_lost); 02670 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); 02671 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_maxrxploss, rtp->rtcp->reported_maxlost); 02672 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_minrxploss, rtp->rtcp->reported_minlost); 02673 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_normdevrxploss, rtp->rtcp->reported_normdev_lost); 02674 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_stdevrxploss, rtp->rtcp->reported_stdev_lost); 02675 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_maxrxploss, rtp->rtcp->maxrxlost); 02676 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_minrxploss, rtp->rtcp->minrxlost); 02677 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_normdevrxploss, rtp->rtcp->normdev_rxlost); 02678 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_stdevrxploss, rtp->rtcp->stdev_rxlost); 02679 AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_LOSS); 02680 02681 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->txjitter, rtp->rxjitter); 02682 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); 02683 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_maxjitter, rtp->rtcp->reported_maxjitter); 02684 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_minjitter, rtp->rtcp->reported_minjitter); 02685 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_normdevjitter, rtp->rtcp->reported_normdev_jitter); 02686 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_stdevjitter, rtp->rtcp->reported_stdev_jitter); 02687 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_maxjitter, rtp->rtcp->maxrxjitter); 02688 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_minjitter, rtp->rtcp->minrxjitter); 02689 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_normdevjitter, rtp->rtcp->normdev_rxjitter); 02690 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_stdevjitter, rtp->rtcp->stdev_rxjitter); 02691 AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_JITTER); 02692 02693 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->rtt, rtp->rtcp->rtt); 02694 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->maxrtt, rtp->rtcp->maxrtt); 02695 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->minrtt, rtp->rtcp->minrtt); 02696 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->normdevrtt, rtp->rtcp->normdevrtt); 02697 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->stdevrtt, rtp->rtcp->stdevrtt); 02698 AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_RTT); 02699 02700 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc); 02701 AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc); 02702 02703 return 0; 02704 }
| static int ast_rtp_local_bridge | ( | struct ast_rtp_instance * | instance0, | |
| struct ast_rtp_instance * | instance1 | |||
| ) | [static] |
Definition at line 2649 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.
02650 { 02651 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0); 02652 02653 ast_set_flag(rtp, FLAG_NEED_MARKER_BIT); 02654 02655 return 0; 02656 }
| static int ast_rtp_new | ( | struct ast_rtp_instance * | instance, | |
| struct ast_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_data(), ast_rtp_instance_set_local_address(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_set_port, create_new_socket(), errno, LOG_ERROR, rtp_learning_seq_init(), ast_rtp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, STRICT_RTP_LEARN, STRICT_RTP_OPEN, and ast_rtp::strict_rtp_state.
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 2476 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.
02477 { 02478 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02479 02480 if (property == AST_RTP_PROPERTY_RTCP) { 02481 if (value) { 02482 if (rtp->rtcp) { 02483 ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance); 02484 return; 02485 } 02486 /* Setup RTCP to be activated on the next RTP write */ 02487 if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) { 02488 return; 02489 } 02490 02491 /* Grab the IP address and port we are going to use */ 02492 ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us); 02493 ast_sockaddr_set_port(&rtp->rtcp->us, 02494 ast_sockaddr_port(&rtp->rtcp->us) + 1); 02495 02496 if ((rtp->rtcp->s = 02497 create_new_socket("RTCP", 02498 ast_sockaddr_is_ipv4(&rtp->rtcp->us) ? 02499 AF_INET : 02500 ast_sockaddr_is_ipv6(&rtp->rtcp->us) ? 02501 AF_INET6 : -1)) < 0) { 02502 ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance); 02503 ast_free(rtp->rtcp); 02504 rtp->rtcp = NULL; 02505 return; 02506 } 02507 02508 /* 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 */ 02509 if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) { 02510 ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance); 02511 close(rtp->rtcp->s); 02512 ast_free(rtp->rtcp); 02513 rtp->rtcp = NULL; 02514 return; 02515 } 02516 02517 ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance); 02518 rtp->rtcp->schedid = -1; 02519 02520 return; 02521 } else { 02522 if (rtp->rtcp) { 02523 if (rtp->rtcp->schedid > 0) { 02524 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) { 02525 /* Successfully cancelled scheduler entry. */ 02526 ao2_ref(instance, -1); 02527 } else { 02528 /* Unable to cancel scheduler entry */ 02529 ast_debug(1, "Failed to tear down RTCP on RTP instance '%p'\n", instance); 02530 return; 02531 } 02532 rtp->rtcp->schedid = -1; 02533 } 02534 close(rtp->rtcp->s); 02535 ast_free(rtp->rtcp); 02536 rtp->rtcp = NULL; 02537 } 02538 return; 02539 } 02540 } 02541 02542 return; 02543 }
| static int ast_rtp_qos_set | ( | struct ast_rtp_instance * | instance, | |
| int | tos, | |||
| int | cos, | |||
| const char * | desc | |||
| ) | [static] |
Definition at line 2759 of file res_rtp_asterisk.c.
References ast_rtp_instance_get_data(), ast_set_qos(), and ast_rtp::s.
02760 { 02761 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02762 02763 return ast_set_qos(rtp->s, tos, cos, desc); 02764 }
| 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_format_get_video_mark(), 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::data, ast_frame::datalen, ast_frame::delivery, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, ast_frame_subclass::format, ast_frame::frametype, ast_format::id, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_WARNING, MAX_TIMESTAMP_SKEW, ast_frame::ptr, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), rtp_sendto(), ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.
Referenced by ast_rtp_write().
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.format) / 1000; 01154 01155 if (frame->subclass.format.id == 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 = ast_format_get_video_mark(&frame->subclass.format); 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 (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, read] |
Definition at line 2101 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_copy(), AST_FORMAT_GET_TYPE, ast_format_is_slinear(), ast_format_rate(), ast_format_set(), ast_format_set_video_mark(), AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_TYPE_AUDIO, AST_FORMAT_TYPE_VIDEO, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_frisolate(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_read(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, ast_rtp_codecs_payload_lookup(), AST_RTP_DTMF, ast_rtp_dtmf_continuation(), ast_rtp_instance_get_bridged(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), ast_rtp_instance_set_remote_address(), AST_RTP_PROPERTY_NAT, ast_samp2tv(), ast_sched_add(), ast_set_flag, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_from_sin, ast_sockaddr_ipv4_mapped(), ast_sockaddr_is_ipv4(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_sockaddr_to_sin, ast_strdupa, AST_STUN_ACCEPT, ast_stun_handle_packet(), ast_tv(), ast_tvdiff_ms(), ast_verbose, ast_rtp_payload_type::asterisk_format, bridge_p2p_rtp_write(), calc_rxstamp(), create_dtmf_frame(), ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, ast_frame_subclass::format, ast_rtp_payload_type::format, ast_frame::frametype, ast_format::id, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len(), ast_frame::len, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, option_debug, process_cn_rfc3389(), process_dtmf_cisco(), process_dtmf_rfc2833(), ast_frame::ptr, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, ast_rtp_payload_type::rtp_code, rtp_debug_test_addr(), rtp_get_rate(), rtp_learning_rtp_seq_update(), rtp_recvfrom(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, ast_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, ast_frame::subclass, ast_rtcp::them, ast_rtp::themssrc, ast_frame::ts, and version.
02102 { 02103 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02104 struct ast_sockaddr addr; 02105 int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno; 02106 unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp; 02107 struct ast_rtp_payload_type payload; 02108 struct ast_sockaddr remote_address = { {0,} }; 02109 struct frame_list frames; 02110 02111 /* If this is actually RTCP let's hop on over and handle it */ 02112 if (rtcp) { 02113 if (rtp->rtcp) { 02114 return ast_rtcp_read(instance); 02115 } 02116 return &ast_null_frame; 02117 } 02118 02119 /* If we are currently sending DTMF to the remote party send a continuation packet */ 02120 if (rtp->sending_digit) { 02121 ast_rtp_dtmf_continuation(instance); 02122 } 02123 02124 /* Actually read in the data from the socket */ 02125 if ((res = rtp_recvfrom(instance, rtp->rawdata + AST_FRIENDLY_OFFSET, 02126 sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, 02127 &addr)) < 0) { 02128 ast_assert(errno != EBADF); 02129 if (errno != EAGAIN) { 02130 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 02131 return NULL; 02132 } 02133 return &ast_null_frame; 02134 } 02135 02136 /* Make sure the data that was read in is actually enough to make up an RTP packet */ 02137 if (res < hdrlen) { 02138 ast_log(LOG_WARNING, "RTP Read too short\n"); 02139 return &ast_null_frame; 02140 } 02141 02142 /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */ 02143 if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { 02144 ast_debug(1, "%p -- start learning mode pass with addr = %s\n", rtp, ast_sockaddr_stringify(&addr)); 02145 /* For now, we always copy the address. */ 02146 ast_sockaddr_copy(&rtp->strict_rtp_address, &addr); 02147 02148 /* Send the rtp and the seqno from header to rtp_learning_rtp_seq_update to see whether we can exit or not*/ 02149 if (rtp_learning_rtp_seq_update(rtp, ntohl(rtpheader[0]))) { 02150 ast_debug(1, "%p -- Condition for learning hasn't exited, so reject the frame.\n", rtp); 02151 return &ast_null_frame; 02152 } 02153 02154 ast_debug(1, "%p -- Probation Ended. Set strict_rtp_state to STRICT_RTP_CLOSED with address %s\n", rtp, ast_sockaddr_stringify(&addr)); 02155 rtp->strict_rtp_state = STRICT_RTP_CLOSED; 02156 } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { 02157 if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) { 02158 /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */ 02159 if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) { 02160 /* ooh, we did! You're now the new expected address, son! */ 02161 ast_sockaddr_copy(&rtp->strict_rtp_address, 02162 &addr); 02163 } else { 02164 const char *real_addr = ast_strdupa(ast_sockaddr_stringify(&addr)); 02165 const char *expected_addr = ast_strdupa(ast_sockaddr_stringify(&rtp->strict_rtp_address)); 02166 02167 ast_debug(1, "Received RTP packet from %s, dropping due to strict RTP protection. Expected it to be from %s\n", 02168 real_addr, expected_addr); 02169 02170 return &ast_null_frame; 02171 } 02172 } 02173 } 02174 02175 /* Get fields and verify this is an RTP packet */ 02176 seqno = ntohl(rtpheader[0]); 02177 02178 ast_rtp_instance_get_remote_address(instance, &remote_address); 02179 02180 if (!(version = (seqno & 0xC0000000) >> 30)) { 02181 struct sockaddr_in addr_tmp; 02182 struct ast_sockaddr addr_v4; 02183 if (ast_sockaddr_is_ipv4(&addr)) { 02184 ast_sockaddr_to_sin(&addr, &addr_tmp); 02185 } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) { 02186 ast_debug(1, "Using IPv6 mapped address %s for STUN\n", 02187 ast_sockaddr_stringify(&addr)); 02188 ast_sockaddr_to_sin(&addr_v4, &addr_tmp); 02189 } else { 02190 ast_debug(1, "Cannot do STUN for non IPv4 address %s\n", 02191 ast_sockaddr_stringify(&addr)); 02192 return &ast_null_frame; 02193 } 02194 if ((ast_stun_handle_packet(rtp->s, &addr_tmp, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) && 02195 ast_sockaddr_isnull(&remote_address)) { 02196 ast_sockaddr_from_sin(&addr, &addr_tmp); 02197 ast_rtp_instance_set_remote_address(instance, &addr); 02198 } 02199 return &ast_null_frame; 02200 } 02201 02202 /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */ 02203 if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) { 02204 if (ast_sockaddr_cmp(&remote_address, &addr)) { 02205 ast_rtp_instance_set_remote_address(instance, &addr); 02206 ast_sockaddr_copy(&remote_address, &addr); 02207 if (rtp->rtcp) { 02208 ast_sockaddr_copy(&rtp->rtcp->them, &addr); 02209 ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(&addr) + 1); 02210 } 02211 rtp->rxseqno = 0; 02212 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 02213 if (rtpdebug) 02214 ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s\n", 02215 ast_sockaddr_stringify(&remote_address)); 02216 } 02217 } 02218 02219 /* If we are directly bridged to another instance send the audio directly out */ 02220 if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) { 02221 return &ast_null_frame; 02222 } 02223 02224 /* If the version is not what we expected by this point then just drop the packet */ 02225 if (version != 2) { 02226 return &ast_null_frame; 02227 } 02228 02229 /* Pull out the various other fields we will need */ 02230 payloadtype = (seqno & 0x7f0000) >> 16; 02231 padding = seqno & (1 << 29); 02232 mark = seqno & (1 << 23); 02233 ext = seqno & (1 << 28); 02234 cc = (seqno & 0xF000000) >> 24; 02235 seqno &= 0xffff; 02236 timestamp = ntohl(rtpheader[1]); 02237 ssrc = ntohl(rtpheader[2]); 02238 02239 AST_LIST_HEAD_INIT_NOLOCK(&frames); 02240 /* Force a marker bit and change SSRC if the SSRC changes */ 02241 if (rtp->rxssrc && rtp->rxssrc != ssrc) { 02242 struct ast_frame *f, srcupdate = { 02243 AST_FRAME_CONTROL, 02244 .subclass.integer = AST_CONTROL_SRCCHANGE, 02245 }; 02246 02247 if (!mark) { 02248 if (rtpdebug) { 02249 ast_debug(1, "Forcing Marker bit, because SSRC has changed\n"); 02250 } 02251 mark = 1; 02252 } 02253 02254 f = ast_frisolate(&srcupdate); 02255 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 02256 } 02257 02258 rtp->rxssrc = ssrc; 02259 02260 /* Remove any padding bytes that may be present */ 02261 if (padding) { 02262 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 02263 } 02264 02265 /* Skip over any CSRC fields */ 02266 if (cc) { 02267 hdrlen += cc * 4; 02268 } 02269 02270 /* Look for any RTP extensions, currently we do not support any */ 02271 if (ext) { 02272 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 02273 hdrlen += 4; 02274 if (option_debug) { 02275 int profile; 02276 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 02277 if (profile == 0x505a) 02278 ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 02279 else 02280 ast_debug(1, "Found unknown RTP Extensions %x\n", profile); 02281 } 02282 } 02283 02284 /* Make sure after we potentially mucked with the header length that it is once again valid */ 02285 if (res < hdrlen) { 02286 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen); 02287 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 02288 } 02289 02290 rtp->rxcount++; 02291 if (rtp->rxcount == 1) { 02292 rtp->seedrxseqno = seqno; 02293 } 02294 02295 /* Do not schedule RR if RTCP isn't run */ 02296 if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 1) { 02297 /* Schedule transmission of Receiver Report */ 02298 ao2_ref(instance, +1); 02299 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance); 02300 if (rtp->rtcp->schedid < 0) { 02301 ao2_ref(instance, -1); 02302 ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n"); 02303 } 02304 } 02305 if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 02306 rtp->cycles += RTP_SEQ_MOD; 02307 02308 prev_seqno = rtp->lastrxseqno; 02309 rtp->lastrxseqno = seqno; 02310 02311 if (!rtp->themssrc) { 02312 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 02313 } 02314 02315 if (rtp_debug_test_addr(&addr)) { 02316 ast_verbose("Got RTP packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02317 ast_sockaddr_stringify(&addr), 02318 payloadtype, seqno, timestamp,res - hdrlen); 02319 } 02320 02321 payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype); 02322 02323 /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */ 02324 if (!payload.asterisk_format) { 02325 struct ast_frame *f = NULL; 02326 if (payload.rtp_code == AST_RTP_DTMF) { 02327 /* process_dtmf_rfc2833 may need to return multiple frames. We do this 02328 * by passing the pointer to the frame list to it so that the method 02329 * can append frames to the list as needed. 02330 */ 02331 process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames); 02332 } else if (payload.rtp_code == AST_RTP_CISCO_DTMF) { 02333 f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark); 02334 } else if (payload.rtp_code == AST_RTP_CN) { 02335 f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark); 02336 } else { 02337 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", 02338 payloadtype, 02339 ast_sockaddr_stringify(&remote_address)); 02340 } 02341 02342 if (f) { 02343 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 02344 } 02345 /* Even if no frame was returned by one of the above methods, 02346 * we may have a frame to return in our frame list 02347 */ 02348 if (!AST_LIST_EMPTY(&frames)) { 02349 return AST_LIST_FIRST(&frames); 02350 } 02351 return &ast_null_frame; 02352 } 02353 02354 ast_format_copy(&rtp->lastrxformat, &payload.format); 02355 ast_format_copy(&rtp->f.subclass.format, &payload.format); 02356 rtp->f.frametype = (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) ? AST_FRAME_VOICE : (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_VIDEO) ? AST_FRAME_VIDEO : AST_FRAME_TEXT; 02357 02358 rtp->rxseqno = seqno; 02359 02360 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) { 02361 rtp->dtmf_timeout = 0; 02362 02363 if (rtp->resp) { 02364 struct ast_frame *f; 02365 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0); 02366 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0)); 02367 rtp->resp = 0; 02368 rtp->dtmf_timeout = rtp->dtmf_duration = 0; 02369 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 02370 return AST_LIST_FIRST(&frames); 02371 } 02372 } 02373 02374 rtp->lastrxts = timestamp; 02375 02376 rtp->f.src = "RTP"; 02377 rtp->f.mallocd = 0; 02378 rtp->f.datalen = res - hdrlen; 02379 rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 02380 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 02381 rtp->f.seqno = seqno; 02382 02383 if (rtp->f.subclass.format.id == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) { 02384 unsigned char *data = rtp->f.data.ptr; 02385 02386 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen); 02387 rtp->f.datalen +=3; 02388 *data++ = 0xEF; 02389 *data++ = 0xBF; 02390 *data = 0xBD; 02391 } 02392 02393 if (rtp->f.subclass.format.id == AST_FORMAT_T140RED) { 02394 unsigned char *data = rtp->f.data.ptr; 02395 unsigned char *header_end; 02396 int num_generations; 02397 int header_length; 02398 int len; 02399 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/ 02400 int x; 02401 02402 ast_format_set(&rtp->f.subclass.format, AST_FORMAT_T140, 0); 02403 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); 02404 if (header_end == NULL) { 02405 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 02406 } 02407 header_end++; 02408 02409 header_length = header_end - data; 02410 num_generations = header_length / 4; 02411 len = header_length; 02412 02413 if (!diff) { 02414 for (x = 0; x < num_generations; x++) 02415 len += data[x * 4 + 3]; 02416 02417 if (!(rtp->f.datalen - len)) 02418 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 02419 02420 rtp->f.data.ptr += len; 02421 rtp->f.datalen -= len; 02422 } else if (diff > num_generations && diff < 10) { 02423 len -= 3; 02424 rtp->f.data.ptr += len; 02425 rtp->f.datalen -= len; 02426 02427 data = rtp->f.data.ptr; 02428 *data++ = 0xEF; 02429 *data++ = 0xBF; 02430 *data = 0xBD; 02431 } else { 02432 for ( x = 0; x < num_generations - diff; x++) 02433 len += data[x * 4 + 3]; 02434 02435 rtp->f.data.ptr += len; 02436 rtp->f.datalen -= len; 02437 } 02438 } 02439 02440 if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) { 02441 rtp->f.samples = ast_codec_get_samples(&rtp->f); 02442 if (ast_format_is_slinear(&rtp->f.subclass.format)) { 02443 ast_frame_byteswap_be(&rtp->f); 02444 } 02445 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 02446 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 02447 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 02448 rtp->f.ts = timestamp / (rtp_get_rate(&rtp->f.subclass.format) / 1000); 02449 rtp->f.len = rtp->f.samples / ((ast_format_rate(&rtp->f.subclass.format) / 1000)); 02450 } else if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_VIDEO) { 02451 /* Video -- samples is # of samples vs. 90000 */ 02452 if (!rtp->lastividtimestamp) 02453 rtp->lastividtimestamp = timestamp; 02454 rtp->f.samples = timestamp - rtp->lastividtimestamp; 02455 rtp->lastividtimestamp = timestamp; 02456 rtp->f.delivery.tv_sec = 0; 02457 rtp->f.delivery.tv_usec = 0; 02458 /* Pass the RTP marker bit as bit */ 02459 if (mark) { 02460 ast_format_set_video_mark(&rtp->f.subclass.format); 02461 } 02462 } else { 02463 /* TEXT -- samples is # of samples vs. 1000 */ 02464 if (!rtp->lastitexttimestamp) 02465 rtp->lastitexttimestamp = timestamp; 02466 rtp->f.samples = timestamp - rtp->lastitexttimestamp; 02467 rtp->lastitexttimestamp = timestamp; 02468 rtp->f.delivery.tv_sec = 0; 02469 rtp->f.delivery.tv_usec = 0; 02470 } 02471 02472 AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list); 02473 return AST_LIST_FIRST(&frames); 02474 }
| static void ast_rtp_remote_address_set | ( | struct ast_rtp_instance * | instance, | |
| struct ast_sockaddr * | addr | |||
| ) | [static] |
Definition at line 2552 of file res_rtp_asterisk.c.
References ast_debug, ast_rtp_instance_get_data(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_rtp::rtcp, rtp_learning_seq_init(), ast_rtp::rxseqno, ast_rtp::seqno, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, and ast_rtcp::them.
02553 { 02554 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02555 02556 if (rtp->rtcp) { 02557 ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance); 02558 ast_sockaddr_copy(&rtp->rtcp->them, addr); 02559 if (!ast_sockaddr_isnull(addr)) { 02560 ast_sockaddr_set_port(&rtp->rtcp->them, 02561 ast_sockaddr_port(addr) + 1); 02562 } 02563 } 02564 02565 rtp->rxseqno = 0; 02566 02567 if (strictrtp) { 02568 rtp->strict_rtp_state = STRICT_RTP_LEARN; 02569 rtp_learning_seq_init(rtp, rtp->seqno); 02570 } 02571 02572 return; 02573 }
| static int ast_rtp_sendcng | ( | struct ast_rtp_instance * | instance, | |
| int | level | |||
| ) | [static] |
generate comfort noice (CNG)
Definition at line 2767 of file res_rtp_asterisk.c.
References ast_log(), AST_RTP_CN, ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::data, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::seqno, and ast_rtp::ssrc.
02768 { 02769 unsigned int *rtpheader; 02770 int hdrlen = 12; 02771 int res; 02772 int payload; 02773 char data[256]; 02774 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02775 struct ast_sockaddr remote_address = { {0,} }; 02776 02777 ast_rtp_instance_get_remote_address(instance, &remote_address); 02778 02779 if (ast_sockaddr_isnull(&remote_address)) { 02780 return -1; 02781 } 02782 02783 payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_CN); 02784 02785 level = 127 - (level & 0x7f); 02786 02787 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02788 02789 /* Get a pointer to the header */ 02790 rtpheader = (unsigned int *)data; 02791 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02792 rtpheader[1] = htonl(rtp->lastts); 02793 rtpheader[2] = htonl(rtp->ssrc); 02794 data[12] = level; 02795 02796 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address); 02797 02798 if (res < 0) { 02799 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno)); 02800 } else if (rtp_debug_test_addr(&remote_address)) { 02801 ast_verbose("Sent Comfort Noise RTP packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02802 ast_sockaddr_stringify(&remote_address), 02803 AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02804 } 02805 02806 return res; 02807 }
| static void ast_rtp_stop | ( | struct ast_rtp_instance * | instance | ) | [static] |
Definition at line 2732 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.
02733 { 02734 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02735 struct ast_sockaddr addr = { {0,} }; 02736 02737 if (rtp->rtcp && rtp->rtcp->schedid > 0) { 02738 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) { 02739 /* successfully cancelled scheduler entry. */ 02740 ao2_ref(instance, -1); 02741 } 02742 rtp->rtcp->schedid = -1; 02743 } 02744 02745 if (rtp->red) { 02746 AST_SCHED_DEL(rtp->sched, rtp->red->schedid); 02747 free(rtp->red); 02748 rtp->red = NULL; 02749 } 02750 02751 ast_rtp_instance_set_remote_address(instance, &addr); 02752 if (rtp->rtcp) { 02753 ast_sockaddr_setnull(&rtp->rtcp->them); 02754 } 02755 02756 ast_set_flag(rtp, FLAG_NEED_MARKER_BIT); 02757 }
| static void ast_rtp_stun_request | ( | struct ast_rtp_instance * | instance, | |
| struct ast_sockaddr * | suggestion, | |||
| const char * | username | |||
| ) | [static] |
Definition at line 2722 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.
02723 { 02724 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02725 struct sockaddr_in suggestion_tmp; 02726 02727 ast_sockaddr_to_sin(suggestion, &suggestion_tmp); 02728 ast_stun_request(rtp->s, &suggestion_tmp, username, NULL); 02729 ast_sockaddr_from_sin(suggestion, &suggestion_tmp); 02730 }
| 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_CELT, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_copy(), AST_FORMAT_G719, AST_FORMAT_G723_1, AST_FORMAT_SILK, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, AST_FORMAT_SPEEX, AST_FORMAT_SPEEX16, AST_FORMAT_SPEEX32, 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_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_frame_subclass::format, ast_format_list::fr_len, ast_frame::frametype, ast_format::id, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_frame::ptr, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, and ast_frame::subclass.
Referenced by red_write().
01313 { 01314 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01315 struct ast_sockaddr remote_address = { {0,} }; 01316 struct ast_format subclass; 01317 int codec; 01318 01319 ast_rtp_instance_get_remote_address(instance, &remote_address); 01320 01321 /* If we don't actually know the remote address don't even bother doing anything */ 01322 if (ast_sockaddr_isnull(&remote_address)) { 01323 ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance); 01324 return 0; 01325 } 01326 01327 /* If there is no data length we can't very well send the packet */ 01328 if (!frame->datalen) { 01329 ast_debug(1, "Received frame with no data for RTP instance '%p' so dropping frame\n", instance); 01330 return 0; 01331 } 01332 01333 /* If the packet is not one our RTP stack supports bail out */ 01334 if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) { 01335 ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n"); 01336 return -1; 01337 } 01338 01339 if (rtp->red) { 01340 /* return 0; */ 01341 /* no primary data or generations to send */ 01342 if ((frame = red_t140_to_red(rtp->red)) == NULL) 01343 return 0; 01344 } 01345 01346 /* Grab the subclass and look up the payload we are going to use */ 01347 ast_format_copy(&subclass, &frame->subclass.format); 01348 if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, &subclass, 0)) < 0) { 01349 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(&frame->subclass.format)); 01350 return -1; 01351 } 01352 01353 /* Oh dear, if the format changed we will have to set up a new smoother */ 01354 if (ast_format_cmp(&rtp->lasttxformat, &subclass) == AST_FORMAT_CMP_NOT_EQUAL) { 01355 ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(&rtp->lasttxformat), ast_getformatname(&subclass)); 01356 rtp->lasttxformat = subclass; 01357 ast_format_copy(&rtp->lasttxformat, &subclass); 01358 if (rtp->smoother) { 01359 ast_smoother_free(rtp->smoother); 01360 rtp->smoother = NULL; 01361 } 01362 } 01363 01364 /* If no smoother is present see if we have to set one up */ 01365 if (!rtp->smoother) { 01366 struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, &subclass); 01367 01368 switch (subclass.id) { 01369 case AST_FORMAT_SPEEX: 01370 case AST_FORMAT_SPEEX16: 01371 case AST_FORMAT_SPEEX32: 01372 case AST_FORMAT_SILK: 01373 case AST_FORMAT_CELT: 01374 case AST_FORMAT_G723_1: 01375 case AST_FORMAT_SIREN7: 01376 case AST_FORMAT_SIREN14: 01377 case AST_FORMAT_G719: 01378 /* these are all frame-based codecs and cannot be safely run through 01379 a smoother */ 01380 break; 01381 default: 01382 if (fmt.inc_ms) { 01383 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 01384 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)); 01385 return -1; 01386 } 01387 if (fmt.flags) { 01388 ast_smoother_set_flags(rtp->smoother, fmt.flags); 01389 } 01390 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)); 01391 } 01392 } 01393 } 01394 01395 /* Feed audio frames into the actual function that will create a frame and send it */ 01396 if (rtp->smoother) { 01397 struct ast_frame *f; 01398 01399 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 01400 ast_smoother_feed_be(rtp->smoother, frame); 01401 } else { 01402 ast_smoother_feed(rtp->smoother, frame); 01403 } 01404 01405 while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) { 01406 ast_rtp_raw_write(instance, f, codec); 01407 } 01408 } else { 01409 int hdrlen = 12; 01410 struct ast_frame *f = NULL; 01411 01412 if (frame->offset < hdrlen) { 01413 f = ast_frdup(frame); 01414 } else { 01415 f = frame; 01416 } 01417 if (f->data.ptr) { 01418 ast_rtp_raw_write(instance, f, codec); 01419 } 01420 if (f != frame) { 01421 ast_frfree(f); 01422 } 01423 01424 } 01425 01426 return 0; 01427 }
| static int bridge_p2p_rtp_write | ( | struct ast_rtp_instance * | instance, | |
| unsigned int * | rtpheader, | |||
| int | len, | |||
| int | hdrlen | |||
| ) | [static] |
Definition at line 2030 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, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, ast_rtp_payload_type::format, LOG_WARNING, option_debug, reconstruct(), ast_rtp_payload_type::rtp_code, rtp_debug_test_addr(), and rtp_sendto().
Referenced by ast_rtp_read().
02031 { 02032 struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance); 02033 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1); 02034 int res = 0, payload = 0, bridged_payload = 0, mark; 02035 struct ast_rtp_payload_type payload_type; 02036 int reconstruct = ntohl(rtpheader[0]); 02037 struct ast_sockaddr remote_address = { {0,} }; 02038 02039 /* Get fields from packet */ 02040 payload = (reconstruct & 0x7f0000) >> 16; 02041 mark = (((reconstruct & 0x800000) >> 23) != 0); 02042 02043 /* Check what the payload value should be */ 02044 payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload); 02045 02046 /* Otherwise adjust bridged payload to match */ 02047 bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, &payload_type.format, payload_type.rtp_code); 02048 02049 /* 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 */ 02050 if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].rtp_code) && 02051 !(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].asterisk_format)) { 02052 return -1; 02053 } 02054 02055 /* If the marker bit has been explicitly set turn it on */ 02056 if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) { 02057 mark = 1; 02058 ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT); 02059 } 02060 02061 /* Reconstruct part of the packet */ 02062 reconstruct &= 0xFF80FFFF; 02063 reconstruct |= (bridged_payload << 16); 02064 reconstruct |= (mark << 23); 02065 rtpheader[0] = htonl(reconstruct); 02066 02067 ast_rtp_instance_get_remote_address(instance1, &remote_address); 02068 02069 if (ast_sockaddr_isnull(&remote_address)) { 02070 ast_debug(1, "Remote address is null, most likely RTP has been stopped\n"); 02071 return 0; 02072 } 02073 02074 /* Send the packet back out */ 02075 res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address); 02076 if (res < 0) { 02077 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))) { 02078 ast_log(LOG_WARNING, 02079 "RTP Transmission error of packet to %s: %s\n", 02080 ast_sockaddr_stringify(&remote_address), 02081 strerror(errno)); 02082 } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) { 02083 if (option_debug || rtpdebug) 02084 ast_log(LOG_WARNING, 02085 "RTP NAT: Can't write RTP to private " 02086 "address %s, waiting for other end to " 02087 "send audio...\n", 02088 ast_sockaddr_stringify(&remote_address)); 02089 ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN); 02090 } 02091 return 0; 02092 } else if (rtp_debug_test_addr(&remote_address)) { 02093 ast_verbose("Sent RTP P2P packet to %s (type %-2.2d, len %-6.6u)\n", 02094 ast_sockaddr_stringify(&remote_address), 02095 bridged_payload, len - hdrlen); 02096 } 02097 02098 return 0; 02099 }
| static void calc_rxstamp | ( | struct timeval * | tv, | |
| struct ast_rtp * | rtp, | |||
| unsigned int | timestamp, | |||
| int | mark | |||
| ) | [static] |
Definition at line 1429 of file res_rtp_asterisk.c.
References ast_samp2tv(), ast_tvadd(), ast_tvsub(), ast_rtp::drxcore, ast_rtp::f, ast_frame_subclass::format, 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.
01430 { 01431 struct timeval now; 01432 struct timeval tmp; 01433 double transit; 01434 double current_time; 01435 double d; 01436 double dtv; 01437 double prog; 01438 int rate = rtp_get_rate(&rtp->f.subclass.format); 01439 01440 double normdev_rxjitter_current; 01441 if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { 01442 gettimeofday(&rtp->rxcore, NULL); 01443 rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000; 01444 /* map timestamp to a real time */ 01445 rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */ 01446 tmp = ast_samp2tv(timestamp, rate); 01447 rtp->rxcore = ast_tvsub(rtp->rxcore, tmp); 01448 /* Round to 0.1ms for nice, pretty timestamps */ 01449 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100; 01450 } 01451 01452 gettimeofday(&now,NULL); 01453 /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */ 01454 tmp = ast_samp2tv(timestamp, rate); 01455 *tv = ast_tvadd(rtp->rxcore, tmp); 01456 01457 prog = (double)((timestamp-rtp->seedrxts)/(float)(rate)); 01458 dtv = (double)rtp->drxcore + (double)(prog); 01459 current_time = (double)now.tv_sec + (double)now.tv_usec/1000000; 01460 transit = current_time - dtv; 01461 d = transit - rtp->rxtransit; 01462 rtp->rxtransit = transit; 01463 if (d<0) 01464 d=-d; 01465 rtp->rxjitter += (1./16.) * (d - rtp->rxjitter); 01466 01467 if (rtp->rtcp) { 01468 if (rtp->rxjitter > rtp->rtcp->maxrxjitter) 01469 rtp->rtcp->maxrxjitter = rtp->rxjitter; 01470 if (rtp->rtcp->rxjitter_count == 1) 01471 rtp->rtcp->minrxjitter = rtp->rxjitter; 01472 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter) 01473 rtp->rtcp->minrxjitter = rtp->rxjitter; 01474 01475 normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count); 01476 rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count); 01477 01478 rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current; 01479 rtp->rtcp->rxjitter_count++; 01480 } 01481 }
| 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, read] |
Definition at line 1483 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().
01484 { 01485 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01486 struct ast_sockaddr remote_address = { {0,} }; 01487 01488 ast_rtp_instance_get_remote_address(instance, &remote_address); 01489 01490 if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 01491 ast_debug(1, "Ignore potential DTMF echo from '%s'\n", 01492 ast_sockaddr_stringify(&remote_address)); 01493 rtp->resp = 0; 01494 rtp->dtmfsamples = 0; 01495 return &ast_null_frame; 01496 } 01497 ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, 01498 ast_sockaddr_stringify(&remote_address)); 01499 if (rtp->resp == 'X') { 01500 rtp->f.frametype = AST_FRAME_CONTROL; 01501 rtp->f.subclass.integer = AST_CONTROL_FLASH; 01502 } else { 01503 rtp->f.frametype = type; 01504 rtp->f.subclass.integer = rtp->resp; 01505 } 01506 rtp->f.datalen = 0; 01507 rtp->f.samples = 0; 01508 rtp->f.mallocd = 0; 01509 rtp->f.src = "RTP"; 01510 AST_LIST_NEXT(&rtp->f, frame_list) = NULL; 01511 01512 return &rtp->f; 01513 }
| 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 2876 of file res_rtp_asterisk.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcp_do_debug_ip(), rtcpdebugaddr, and ast_cli_entry::usage.
02877 { 02878 switch (cmd) { 02879 case CLI_INIT: 02880 e->command = "rtcp set debug {on|off|ip}"; 02881 e->usage = 02882 "Usage: rtcp set debug {on|off|ip host[:port]}\n" 02883 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n" 02884 " specified, limit the dumped packets to those to and from\n" 02885 " the specified 'host' with optional port.\n"; 02886 return NULL; 02887 case CLI_GENERATE: 02888 return NULL; 02889 } 02890 02891 if (a->argc == e->args) { /* set on or off */ 02892 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 02893 rtcpdebug = 1; 02894 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr)); 02895 ast_cli(a->fd, "RTCP Debugging Enabled\n"); 02896 return CLI_SUCCESS; 02897 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 02898 rtcpdebug = 0; 02899 ast_cli(a->fd, "RTCP Debugging Disabled\n"); 02900 return CLI_SUCCESS; 02901 } 02902 } else if (a->argc == e->args +1) { /* ip */ 02903 return rtcp_do_debug_ip(a); 02904 } 02905 02906 return CLI_SHOWUSAGE; /* default, failure */ 02907 }
| static char* handle_cli_rtcp_set_stats | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2909 of file res_rtp_asterisk.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02910 { 02911 switch (cmd) { 02912 case CLI_INIT: 02913 e->command = "rtcp set stats {on|off}"; 02914 e->usage = 02915 "Usage: rtcp set stats {on|off}\n" 02916 " Enable/Disable dumping of RTCP stats.\n"; 02917 return NULL; 02918 case CLI_GENERATE: 02919 return NULL; 02920 } 02921 02922 if (a->argc != e->args) 02923 return CLI_SHOWUSAGE; 02924 02925 if (!strncasecmp(a->argv[e->args-1], "on", 2)) 02926 rtcpstats = 1; 02927 else if (!strncasecmp(a->argv[e->args-1], "off", 3)) 02928 rtcpstats = 0; 02929 else 02930 return CLI_SHOWUSAGE; 02931 02932 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled"); 02933 return CLI_SUCCESS; 02934 }
| static char* handle_cli_rtp_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2843 of file res_rtp_asterisk.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtp_do_debug_ip(), rtpdebugaddr, and ast_cli_entry::usage.
02844 { 02845 switch (cmd) { 02846 case CLI_INIT: 02847 e->command = "rtp set debug {on|off|ip}"; 02848 e->usage = 02849 "Usage: rtp set debug {on|off|ip host[:port]}\n" 02850 " Enable/Disable dumping of all RTP packets. If 'ip' is\n" 02851 " specified, limit the dumped packets to those to and from\n" 02852 " the specified 'host' with optional port.\n"; 02853 return NULL; 02854 case CLI_GENERATE: 02855 return NULL; 02856 } 02857 02858 if (a->argc == e->args) { /* set on or off */ 02859 if (!strncasecmp(a->argv[e->args-1], "on", 2)) { 02860 rtpdebug = 1; 02861 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr)); 02862 ast_cli(a->fd, "RTP Debugging Enabled\n"); 02863 return CLI_SUCCESS; 02864 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) { 02865 rtpdebug = 0; 02866 ast_cli(a->fd, "RTP Debugging Disabled\n"); 02867 return CLI_SUCCESS; 02868 } 02869 } else if (a->argc == e->args +1) { /* ip */ 02870 return rtp_do_debug_ip(a); 02871 } 02872 02873 return CLI_SHOWUSAGE; /* default, failure */ 02874 }
| static int load_module | ( | void | ) | [static] |
Definition at line 3024 of file res_rtp_asterisk.c.
References ARRAY_LEN, ast_cli_register_multiple(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_rtp_engine_register, ast_rtp_engine_unregister(), and rtp_reload().
03025 { 03026 if (ast_rtp_engine_register(&asterisk_rtp_engine)) { 03027 return AST_MODULE_LOAD_DECLINE; 03028 } 03029 03030 if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) { 03031 ast_rtp_engine_unregister(&asterisk_rtp_engine); 03032 return AST_MODULE_LOAD_DECLINE; 03033 } 03034 03035 rtp_reload(0); 03036 03037 return AST_MODULE_LOAD_SUCCESS; 03038 }
| 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, read] |
Definition at line 1719 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_format::id, ast_frame_subclass::integer, ast_rtp::lastrxformat, LOG_NOTICE, ast_frame::offset, ast_frame::ptr, ast_rtp::rawdata, ast_frame::samples, and ast_frame::subclass.
Referenced by ast_rtp_read().
01720 { 01721 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01722 01723 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 01724 totally help us out becuase we don't have an engine to keep it going and we are not 01725 guaranteed to have it every 20ms or anything */ 01726 if (rtpdebug) 01727 ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", (int) rtp->lastrxformat.id, len); 01728 01729 if (ast_test_flag(rtp, FLAG_3389_WARNING)) { 01730 struct ast_sockaddr remote_address = { {0,} }; 01731 01732 ast_rtp_instance_get_remote_address(instance, &remote_address); 01733 01734 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n", 01735 ast_sockaddr_stringify(&remote_address)); 01736 ast_set_flag(rtp, FLAG_3389_WARNING); 01737 } 01738 01739 /* Must have at least one byte */ 01740 if (!len) 01741 return NULL; 01742 if (len < 24) { 01743 rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET; 01744 rtp->f.datalen = len - 1; 01745 rtp->f.offset = AST_FRIENDLY_OFFSET; 01746 memcpy(rtp->f.data.ptr, data + 1, len - 1); 01747 } else { 01748 rtp->f.data.ptr = NULL; 01749 rtp->f.offset = 0; 01750 rtp->f.datalen = 0; 01751 } 01752 rtp->f.frametype = AST_FRAME_CNG; 01753 rtp->f.subclass.integer = data[0] & 0x7f; 01754 rtp->f.samples = 0; 01755 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 01756 01757 return &rtp->f; 01758 }
| static struct ast_frame* process_dtmf_cisco | ( | struct ast_rtp_instance * | instance, | |
| unsigned char * | data, | |||
| int | len, | |||
| unsigned int | seqno, | |||
| unsigned int | timestamp, | |||
| struct ast_sockaddr * | addr, | |||
| int | payloadtype, | |||
| int | mark | |||
| ) | [static, read] |
Definition at line 1640 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_format::id, ast_rtp::lastrxformat, ast_rtp::resp, rtp_get_rate(), ast_frame::samples, and seq.
Referenced by ast_rtp_read().
01641 { 01642 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01643 unsigned int event, flags, power; 01644 char resp = 0; 01645 unsigned char seq; 01646 struct ast_frame *f = NULL; 01647 01648 if (len < 4) { 01649 return NULL; 01650 } 01651 01652 /* The format of Cisco RTP DTMF packet looks like next: 01653 +0 - sequence number of DTMF RTP packet (begins from 1, 01654 wrapped to 0) 01655 +1 - set of flags 01656 +1 (bit 0) - flaps by different DTMF digits delimited by audio 01657 or repeated digit without audio??? 01658 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone 01659 then falls to 0 at its end) 01660 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...) 01661 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right 01662 by each new packet and thus provides some redudancy. 01663 01664 Sample of Cisco RTP DTMF packet is (all data in hex): 01665 19 07 00 02 12 02 20 02 01666 showing end of DTMF digit '2'. 01667 01668 The packets 01669 27 07 00 02 0A 02 20 02 01670 28 06 20 02 00 02 0A 02 01671 shows begin of new digit '2' with very short pause (20 ms) after 01672 previous digit '2'. Bit +1.0 flips at begin of new digit. 01673 01674 Cisco RTP DTMF packets comes as replacement of audio RTP packets 01675 so its uses the same sequencing and timestamping rules as replaced 01676 audio packets. Repeat interval of DTMF packets is 20 ms and not rely 01677 on audio framing parameters. Marker bit isn't used within stream of 01678 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps 01679 are not sequential at borders between DTMF and audio streams, 01680 */ 01681 01682 seq = data[0]; 01683 flags = data[1]; 01684 power = data[2]; 01685 event = data[3] & 0x1f; 01686 01687 if (rtpdebug) 01688 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); 01689 if (event < 10) { 01690 resp = '0' + event; 01691 } else if (event < 11) { 01692 resp = '*'; 01693 } else if (event < 12) { 01694 resp = '#'; 01695 } else if (event < 16) { 01696 resp = 'A' + (event - 12); 01697 } else if (event < 17) { 01698 resp = 'X'; 01699 } 01700 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) { 01701 rtp->resp = resp; 01702 /* Why we should care on DTMF compensation at reception? */ 01703 if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) { 01704 f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0); 01705 rtp->dtmfsamples = 0; 01706 } 01707 } else if ((rtp->resp == resp) && !power) { 01708 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)); 01709 f->samples = rtp->dtmfsamples * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8); 01710 rtp->resp = 0; 01711 } else if (rtp->resp == resp) 01712 rtp->dtmfsamples += 20 * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8); 01713 01714 rtp->dtmf_timeout = 0; 01715 01716 return f; 01717 }
| 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 1515 of file res_rtp_asterisk.c.
References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup(), AST_LIST_INSERT_TAIL, 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, f, ast_frame_subclass::format, ast_rtp::lastevent, ast_frame::len, ast_rtp::resp, rtp_debug_test_addr(), rtp_get_rate(), and ast_frame::subclass.
Referenced by ast_rtp_read().
01516 { 01517 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 01518 struct ast_sockaddr remote_address = { {0,} }; 01519 unsigned int event, event_end, samples; 01520 char resp = 0; 01521 struct ast_frame *f = NULL; 01522 01523 ast_rtp_instance_get_remote_address(instance, &remote_address); 01524 01525 /* Figure out event, event end, and samples */ 01526 event = ntohl(*((unsigned int *)(data))); 01527 event >>= 24; 01528 event_end = ntohl(*((unsigned int *)(data))); 01529 event_end <<= 8; 01530 event_end >>= 24; 01531 samples = ntohl(*((unsigned int *)(data))); 01532 samples &= 0xFFFF; 01533 01534 if (rtp_debug_test_addr(&remote_address)) { 01535 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", 01536 ast_sockaddr_stringify(&remote_address), 01537 payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples); 01538 } 01539 01540 /* Print out debug if turned on */ 01541 if (rtpdebug) 01542 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 01543 01544 /* Figure out what digit was pressed */ 01545 if (event < 10) { 01546 resp = '0' + event; 01547 } else if (event < 11) { 01548 resp = '*'; 01549 } else if (event < 12) { 01550 resp = '#'; 01551 } else if (event < 16) { 01552 resp = 'A' + (event - 12); 01553 } else if (event < 17) { /* Event 16: Hook flash */ 01554 resp = 'X'; 01555 } else { 01556 /* Not a supported event */ 01557 ast_debug(1, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event); 01558 return; 01559 } 01560 01561 if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) { 01562 if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) { 01563 rtp->resp = resp; 01564 rtp->dtmf_timeout = 0; 01565 f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE))); 01566 f->len = 0; 01567 rtp->lastevent = timestamp; 01568 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01569 } 01570 } else { 01571 /* The duration parameter measures the complete 01572 duration of the event (from the beginning) - RFC2833. 01573 Account for the fact that duration is only 16 bits long 01574 (about 8 seconds at 8000 Hz) and can wrap is digit 01575 is hold for too long. */ 01576 unsigned int new_duration = rtp->dtmf_duration; 01577 unsigned int last_duration = new_duration & 0xFFFF; 01578 01579 if (last_duration > 64000 && samples < last_duration) { 01580 new_duration += 0xFFFF + 1; 01581 } 01582 new_duration = (new_duration & ~0xFFFF) | samples; 01583 01584 /* The second portion of this check is to not mistakenly 01585 * stop accepting DTMF if the seqno rolls over beyond 01586 * 65535. 01587 */ 01588 if (rtp->lastevent > seqno && rtp->lastevent - seqno < 50) { 01589 /* Out of order frame. Processing this can cause us to 01590 * improperly duplicate incoming DTMF, so just drop 01591 * this. 01592 */ 01593 return; 01594 } 01595 01596 if (event_end & 0x80) { 01597 /* End event */ 01598 if ((rtp->lastevent != seqno) && rtp->resp) { 01599 rtp->dtmf_duration = new_duration; 01600 f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0)); 01601 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0)); 01602 rtp->resp = 0; 01603 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01604 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01605 } 01606 } else { 01607 /* Begin/continuation */ 01608 01609 if (rtp->resp && rtp->resp != resp) { 01610 /* Another digit already began. End it */ 01611 f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0)); 01612 f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0)); 01613 rtp->resp = 0; 01614 rtp->dtmf_duration = rtp->dtmf_timeout = 0; 01615 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01616 } 01617 01618 if (rtp->resp) { 01619 /* Digit continues */ 01620 rtp->dtmf_duration = new_duration; 01621 } else { 01622 /* New digit began */ 01623 rtp->resp = resp; 01624 f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0)); 01625 rtp->dtmf_duration = samples; 01626 AST_LIST_INSERT_TAIL(frames, f, frame_list); 01627 } 01628 01629 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout; 01630 } 01631 01632 rtp->lastevent = seqno; 01633 } 01634 01635 rtp->dtmfsamples = samples; 01636 01637 return; 01638 }
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 2590 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().
02591 { 02592 struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data; 02593 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02594 02595 ast_rtp_write(instance, &rtp->red->t140); 02596 02597 return 1; 02598 }
| static int reload_module | ( | void | ) | [static] |
Definition at line 3018 of file res_rtp_asterisk.c.
References rtp_reload().
03019 { 03020 rtp_reload(1); 03021 return 0; 03022 }
| 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 2826 of file res_rtp_asterisk.c.
References ast_cli_args::argv, ast_cli(), ast_sockaddr_parse(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify(), ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, and rtcpdebugaddr.
Referenced by handle_cli_rtcp_set_debug().
02827 { 02828 char *arg = ast_strdupa(a->argv[4]); 02829 char *debughost = NULL; 02830 char *debugport = NULL; 02831 02832 if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) { 02833 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 02834 return CLI_FAILURE; 02835 } 02836 rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0'); 02837 ast_cli(a->fd, "RTCP Debugging Enabled for address: %s\n", 02838 ast_sockaddr_stringify(&rtcpdebugaddr)); 02839 rtcpdebug = 1; 02840 return CLI_SUCCESS; 02841 }
| 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 2809 of file res_rtp_asterisk.c.
References ast_cli_args::argv, ast_cli(), ast_sockaddr_parse(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify(), ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, and rtpdebugaddr.
Referenced by handle_cli_rtp_set_debug().
02810 { 02811 char *arg = ast_strdupa(a->argv[4]); 02812 char *debughost = NULL; 02813 char *debugport = NULL; 02814 02815 if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) { 02816 ast_cli(a->fd, "Lookup failed for '%s'\n", arg); 02817 return CLI_FAILURE; 02818 } 02819 rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0'); 02820 ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n", 02821 ast_sockaddr_stringify(&rtpdebugaddr)); 02822 rtpdebug = 1; 02823 return CLI_SUCCESS; 02824 }
| static int rtp_get_rate | ( | struct ast_format * | format | ) | [static] |
Definition at line 408 of file res_rtp_asterisk.c.
References AST_FORMAT_G722, ast_format_rate(), and ast_format::id.
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 (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format); 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, ast_rtp::learning_max_seq, and ast_rtp::learning_probation.
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_rtp::learning_max_seq, and ast_rtp::learning_probation.
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 2635 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.
02636 { 02637 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02638 02639 if (frame->datalen > -1) { 02640 struct rtp_red *red = rtp->red; 02641 memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen); 02642 red->t140.datalen += frame->datalen; 02643 red->t140.ts = frame->ts; 02644 } 02645 02646 return 0; 02647 }
| static int rtp_red_init | ( | struct ast_rtp_instance * | instance, | |
| int | buffer_time, | |||
| int * | payloads, | |||
| int | generations | |||
| ) | [static] |
Definition at line 2600 of file res_rtp_asterisk.c.
References ast_calloc, ast_format_set(), AST_FORMAT_T140RED, AST_FRAME_TEXT, ast_rtp_instance_get_data(), ast_sched_add(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, 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.
02601 { 02602 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); 02603 int x; 02604 02605 if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) { 02606 return -1; 02607 } 02608 02609 rtp->red->t140.frametype = AST_FRAME_TEXT; 02610 ast_format_set(&rtp->red->t140.subclass.format, AST_FORMAT_T140RED, 0); 02611 rtp->red->t140.data.ptr = &rtp->red->buf_data; 02612 02613 rtp->red->t140.ts = 0; 02614 rtp->red->t140red = rtp->red->t140; 02615 rtp->red->t140red.data.ptr = &rtp->red->t140red_data; 02616 rtp->red->t140red.datalen = 0; 02617 rtp->red->ti = buffer_time; 02618 rtp->red->num_gen = generations; 02619 rtp->red->hdrlen = generations * 4 + 1; 02620 rtp->red->prev_ts = 0; 02621 02622 for (x = 0; x < generations; x++) { 02623 rtp->red->pt[x] = payloads[x]; 02624 rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */ 02625 rtp->red->t140red_data[x*4] = rtp->red->pt[x]; 02626 } 02627 rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */ 02628 rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance); 02629 02630 rtp->red->t140.datalen = 0; 02631 02632 return 0; 02633 }
| static int rtp_reload | ( | int | reload | ) | [static] |
Definition at line 2942 of file res_rtp_asterisk.c.
References ast_config_destroy(), ast_config_load2(), ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTMF_TIMEOUT, DEFAULT_LEARNING_MIN_SEQUENTIAL, DEFAULT_RTP_END, DEFAULT_RTP_START, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, and STRICT_RTP_CLOSED.
Referenced by load_module(), and reload_module().
02943 { 02944 struct ast_config *cfg; 02945 const char *s; 02946 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02947 02948 cfg = ast_config_load2("rtp.conf", "rtp", config_flags); 02949 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) { 02950 return 0; 02951 } 02952 02953 rtpstart = DEFAULT_RTP_START; 02954 rtpend = DEFAULT_RTP_END; 02955 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 02956 strictrtp = STRICT_RTP_CLOSED; 02957 learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL; 02958 if (cfg) { 02959 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 02960 rtpstart = atoi(s); 02961 if (rtpstart < MINIMUM_RTP_PORT) 02962 rtpstart = MINIMUM_RTP_PORT; 02963 if (rtpstart > MAXIMUM_RTP_PORT) 02964 rtpstart = MAXIMUM_RTP_PORT; 02965 } 02966 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 02967 rtpend = atoi(s); 02968 if (rtpend < MINIMUM_RTP_PORT) 02969 rtpend = MINIMUM_RTP_PORT; 02970 if (rtpend > MAXIMUM_RTP_PORT) 02971 rtpend = MAXIMUM_RTP_PORT; 02972 } 02973 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 02974 rtcpinterval = atoi(s); 02975 if (rtcpinterval == 0) 02976 rtcpinterval = 0; /* Just so we're clear... it's zero */ 02977 if (rtcpinterval < RTCP_MIN_INTERVALMS) 02978 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 02979 if (rtcpinterval > RTCP_MAX_INTERVALMS) 02980 rtcpinterval = RTCP_MAX_INTERVALMS; 02981 } 02982 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 02983 #ifdef SO_NO_CHECK 02984 nochecksums = ast_false(s) ? 1 : 0; 02985 #else 02986 if (ast_false(s)) 02987 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 02988 #endif 02989 } 02990 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 02991 dtmftimeout = atoi(s); 02992 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) { 02993 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 02994 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 02995 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 02996 }; 02997 } 02998 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) { 02999 strictrtp = ast_true(s); 03000 } 03001 if ((s = ast_variable_retrieve(cfg, "general", "probation"))) { 03002 if ((sscanf(s, "%d", &learning_min_sequential) <= 0) || learning_min_sequential <= 0) { 03003 ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n", 03004 DEFAULT_LEARNING_MIN_SEQUENTIAL); 03005 } 03006 } 03007 ast_config_destroy(cfg); 03008 } 03009 if (rtpstart >= rtpend) { 03010 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03011 rtpstart = DEFAULT_RTP_START; 03012 rtpend = DEFAULT_RTP_END; 03013 } 03014 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03015 return 0; 03016 }
| 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 3040 of file res_rtp_asterisk.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), and ast_rtp_engine_unregister().
03041 { 03042 ast_rtp_engine_unregister(&asterisk_rtp_engine); 03043 ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp)); 03044 03045 return 0; 03046 }
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 3053 of file res_rtp_asterisk.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3053 of file res_rtp_asterisk.c.
struct ast_rtp_engine asterisk_rtp_engine [static] |
Definition at line 297 of file res_rtp_asterisk.c.
struct ast_cli_entry cli_rtp[] [static] |
Initial value:
{
AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
}
Definition at line 2936 of file res_rtp_asterisk.c.
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
Definition at line 86 of file res_rtp_asterisk.c.
int learning_min_sequential [static] |
Definition at line 102 of file res_rtp_asterisk.c.
| struct ast_srtp_res* res_srtp |
Definition at line 45 of file rtp_engine.c.
int rtcpdebug [static] |
Are we debugging RTCP?
Definition at line 91 of file res_rtp_asterisk.c.
struct ast_sockaddr rtcpdebugaddr [static] |
Debug RTCP packets to/from this host
Definition at line 95 of file res_rtp_asterisk.c.
Referenced by handle_cli_rtcp_set_debug(), rtcp_debug_test_addr(), and rtcp_do_debug_ip().
int rtcpdebugport [static] |
Definition at line 97 of file res_rtp_asterisk.c.
int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static] |
Time between rtcp reports in millisecs
Definition at line 93 of file res_rtp_asterisk.c.
int rtcpstats [static] |
Are we debugging RTCP?
Definition at line 92 of file res_rtp_asterisk.c.
int rtpdebug [static] |
Are we debugging?
Definition at line 90 of file res_rtp_asterisk.c.
struct ast_sockaddr rtpdebugaddr [static] |
Debug packets to/from this host
Definition at line 94 of file res_rtp_asterisk.c.
Referenced by handle_cli_rtp_set_debug(), rtp_debug_test_addr(), and rtp_do_debug_ip().
int rtpdebugport [static] |
Definition at line 96 of file res_rtp_asterisk.c.
int rtpend = DEFAULT_RTP_END [static] |
Last port for RTP sessions (set in rtp.conf)
Definition at line 89 of file res_rtp_asterisk.c.
int rtpstart = DEFAULT_RTP_START [static] |
First port for RTP sessions (set in rtp.conf)
Definition at line 88 of file res_rtp_asterisk.c.
int strictrtp [static] |
Definition at line 101 of file res_rtp_asterisk.c.
1.5.6