#include <netinet/in.h>
#include "asterisk/frame.h"
#include "asterisk/io.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/linkedlists.h"
Go to the source code of this file.
Data Structures | |
struct | ast_rtp_protocol |
struct | ast_rtp_quality |
Defines | |
#define | AST_RTP_CISCO_DTMF (1 << 2) |
#define | AST_RTP_CN (1 << 1) |
#define | AST_RTP_DTMF (1 << 0) |
#define | AST_RTP_MAX AST_RTP_CISCO_DTMF |
#define | FLAG_3389_WARNING (1 << 0) |
#define | MAX_RTP_PT 256 |
Typedefs | |
typedef int(* | ast_rtp_callback )(struct ast_rtp *rtp, struct ast_frame *f, void *data) |
Enumerations | |
enum | ast_rtp_get_result { AST_RTP_GET_FAILED = 0, AST_RTP_TRY_PARTIAL, AST_RTP_TRY_NATIVE } |
enum | ast_rtp_options { AST_RTP_OPT_G726_NONSTANDARD = (1 << 0) } |
Functions | |
int | ast_rtcp_fd (struct ast_rtp *rtp) |
struct ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
int | ast_rtcp_send_h261fur (void *data) |
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP. | |
size_t | ast_rtp_alloc_size (void) |
Get the amount of space required to hold an RTP session. | |
int | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk. | |
void | ast_rtp_change_source (struct ast_rtp *instance) |
Indicate a new source of audio has dropped in and the ssrc should change. | |
int | ast_rtp_codec_getformat (int pt) |
struct ast_codec_pref * | ast_rtp_codec_getpref (struct ast_rtp *rtp) |
int | ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs) |
void | ast_rtp_destroy (struct ast_rtp *rtp) |
int | ast_rtp_early_bridge (struct ast_channel *dest, struct ast_channel *src) |
If possible, create an early bridge directly between the devices without having to send a re-invite later. | |
int | ast_rtp_fd (struct ast_rtp *rtp) |
struct ast_rtp * | ast_rtp_get_bridged (struct ast_rtp *rtp) |
void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs. | |
int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
char * | ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual) |
Return RTCP quality string. | |
int | ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp) |
Get rtp hold timeout. | |
int | ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp) |
Get RTP keepalive interval. | |
int | ast_rtp_get_rtptimeout (struct ast_rtp *rtp) |
Get rtp timeout. | |
void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
int | ast_rtp_getnat (struct ast_rtp *rtp) |
void | ast_rtp_init (void) |
Initialize the RTP system in Asterisk. | |
int | ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code) |
Looks up an RTP code out of our *static* outbound list. | |
char * | ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options) |
Build a string of MIME subtype names from a capability list. | |
const char * | ast_rtp_lookup_mime_subtype (int isAstFormat, int code, enum ast_rtp_options options) |
Mapping an Asterisk code into a MIME subtype (string):. | |
struct rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
Mapping between RTP payload format codes and Asterisk codes:. | |
int | ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media) |
struct ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
Initializate a RTP session. | |
void | ast_rtp_new_init (struct ast_rtp *rtp) |
Initialize a new RTP structure. | |
struct ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in) |
Initializate a RTP session using an in_addr structure. | |
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
Register interface to channel driver. | |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
Unregister interface to channel driver. | |
void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
Setting RTP payload types from lines in a SDP description:. | |
void | ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src) |
Copy payload types between RTP structures. | |
void | ast_rtp_pt_default (struct ast_rtp *rtp) |
Set payload types to defaults. | |
struct ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
int | ast_rtp_reload (void) |
void | ast_rtp_reset (struct ast_rtp *rtp) |
int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
generate comfort noice (CNG) | |
int | ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit) |
Send begin frames for DTMF. | |
int | ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit) |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
Activate payload type. | |
void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
void | ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout) |
Set rtp hold timeout. | |
void | ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period) |
set RTP keepalive interval | |
int | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options) |
Initiate payload type to a known MIME media type for a codec. | |
void | ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout) |
Set rtp timeout. | |
void | ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp) |
void | ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf) |
Indicate whether this RTP session is carrying DTMF or not. | |
void | ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate) |
Compensate for devices that send RFC2833 packets all at once. | |
void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
void | ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable) |
Enable STUN capability. | |
int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
void | ast_rtp_stop (struct ast_rtp *rtp) |
void | ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username) |
void | ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt) |
clear payload type | |
void | ast_rtp_update_source (struct ast_rtp *rtp) |
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f) |
RTP is defined in RFC 3550.
Definition in file rtp.h.
#define AST_RTP_CISCO_DTMF (1 << 2) |
#define AST_RTP_CN (1 << 1) |
'Comfort Noise' (RFC3389)
Definition at line 45 of file rtp.h.
Referenced by ast_rtp_read(), and ast_rtp_sendcng().
#define AST_RTP_DTMF (1 << 0) |
DTMF (RFC2833)
Definition at line 43 of file rtp.h.
Referenced by add_noncodec_to_sdp(), add_sdp(), ast_rtp_read(), ast_rtp_senddigit_begin(), bridge_p2p_rtp_write(), check_user_full(), create_addr(), create_addr_from_peer(), oh323_alloc(), oh323_request(), process_sdp(), sip_alloc(), and sip_dtmfmode().
#define AST_RTP_MAX AST_RTP_CISCO_DTMF |
Maximum RTP-specific code
Definition at line 49 of file rtp.h.
Referenced by add_sdp(), and ast_rtp_lookup_mime_multiple().
#define MAX_RTP_PT 256 |
Definition at line 51 of file rtp.h.
Referenced by ast_rtp_codec_getformat(), ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_pt_default(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_rtp_unset_m_type(), and process_sdp().
typedef int(* ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data) |
enum ast_rtp_get_result |
Definition at line 57 of file rtp.h.
00057 { 00058 /*! Failed to find the RTP structure */ 00059 AST_RTP_GET_FAILED = 0, 00060 /*! RTP structure exists but true native bridge can not occur so try partial */ 00061 AST_RTP_TRY_PARTIAL, 00062 /*! RTP structure exists and native bridge can occur */ 00063 AST_RTP_TRY_NATIVE, 00064 };
enum ast_rtp_options |
Definition at line 53 of file rtp.h.
00053 { 00054 AST_RTP_OPT_G726_NONSTANDARD = (1 << 0), 00055 };
int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 518 of file rtp.c.
References ast_rtp::rtcp, and ast_rtcp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), sip_new(), and start_rtp().
Definition at line 827 of file rtp.c.
References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, ast_rtp::f, f, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().
Referenced by oh323_read(), sip_rtp_read(), and skinny_rtp_read().
00828 { 00829 socklen_t len; 00830 int position, i, packetwords; 00831 int res; 00832 struct sockaddr_in sin; 00833 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00834 unsigned int *rtcpheader; 00835 int pt; 00836 struct timeval now; 00837 unsigned int length; 00838 int rc; 00839 double rttsec; 00840 uint64_t rtt = 0; 00841 unsigned int dlsr; 00842 unsigned int lsr; 00843 unsigned int msw; 00844 unsigned int lsw; 00845 unsigned int comp; 00846 struct ast_frame *f = &ast_null_frame; 00847 00848 if (!rtp || !rtp->rtcp) 00849 return &ast_null_frame; 00850 00851 len = sizeof(sin); 00852 00853 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00854 0, (struct sockaddr *)&sin, &len); 00855 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00856 00857 if (res < 0) { 00858 ast_assert(errno != EBADF); 00859 if (errno != EAGAIN) { 00860 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); 00861 return NULL; 00862 } 00863 return &ast_null_frame; 00864 } 00865 00866 packetwords = res / 4; 00867 00868 if (rtp->nat) { 00869 /* Send to whoever sent to us */ 00870 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00871 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00872 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00873 if (option_debug || rtpdebug) 00874 ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00875 } 00876 } 00877 00878 if (option_debug) 00879 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00880 00881 /* Process a compound packet */ 00882 position = 0; 00883 while (position < packetwords) { 00884 i = position; 00885 length = ntohl(rtcpheader[i]); 00886 pt = (length & 0xff0000) >> 16; 00887 rc = (length & 0x1f000000) >> 24; 00888 length &= 0xffff; 00889 00890 if ((i + length) > packetwords) { 00891 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00892 return &ast_null_frame; 00893 } 00894 00895 if (rtcp_debug_test_addr(&sin)) { 00896 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00897 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00898 ast_verbose("Reception reports: %d\n", rc); 00899 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00900 } 00901 00902 i += 2; /* Advance past header and ssrc */ 00903 00904 switch (pt) { 00905 case RTCP_PT_SR: 00906 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00907 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00908 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00909 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/ 00910 00911 if (rtcp_debug_test_addr(&sin)) { 00912 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00913 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00914 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00915 } 00916 i += 5; 00917 if (rc < 1) 00918 break; 00919 /* Intentional fall through */ 00920 case RTCP_PT_RR: 00921 /* Don't handle multiple reception reports (rc > 1) yet */ 00922 /* Calculate RTT per RFC */ 00923 gettimeofday(&now, NULL); 00924 timeval2ntp(now, &msw, &lsw); 00925 if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */ 00926 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00927 lsr = ntohl(rtcpheader[i + 4]); 00928 dlsr = ntohl(rtcpheader[i + 5]); 00929 rtt = comp - lsr - dlsr; 00930 00931 /* Convert end to end delay to usec (keeping the calculation in 64bit space) 00932 sess->ee_delay = (eedelay * 1000) / 65536; */ 00933 if (rtt < 4294) { 00934 rtt = (rtt * 1000000) >> 16; 00935 } else { 00936 rtt = (rtt * 1000) >> 16; 00937 rtt *= 1000; 00938 } 00939 rtt = rtt / 1000.; 00940 rttsec = rtt / 1000.; 00941 00942 if (comp - dlsr >= lsr) { 00943 rtp->rtcp->accumulated_transit += rttsec; 00944 rtp->rtcp->rtt = rttsec; 00945 if (rtp->rtcp->maxrtt<rttsec) 00946 rtp->rtcp->maxrtt = rttsec; 00947 if (rtp->rtcp->minrtt>rttsec) 00948 rtp->rtcp->minrtt = rttsec; 00949 } else if (rtcp_debug_test_addr(&sin)) { 00950 ast_verbose("Internal RTCP NTP clock skew detected: " 00951 "lsr=%u, now=%u, dlsr=%u (%d:%03dms), " 00952 "diff=%d\n", 00953 lsr, comp, dlsr, dlsr / 65536, 00954 (dlsr % 65536) * 1000 / 65536, 00955 dlsr - (comp - lsr)); 00956 } 00957 } 00958 00959 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 00960 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 00961 if (rtcp_debug_test_addr(&sin)) { 00962 ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 00963 ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost); 00964 ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 00965 ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 00966 ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 00967 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 00968 ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 00969 if (rtt) 00970 ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt); 00971 } 00972 break; 00973 case RTCP_PT_FUR: 00974 if (rtcp_debug_test_addr(&sin)) 00975 ast_verbose("Received an RTCP Fast Update Request\n"); 00976 rtp->f.frametype = AST_FRAME_CONTROL; 00977 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 00978 rtp->f.datalen = 0; 00979 rtp->f.samples = 0; 00980 rtp->f.mallocd = 0; 00981 rtp->f.src = "RTP"; 00982 f = &rtp->f; 00983 break; 00984 case RTCP_PT_SDES: 00985 if (rtcp_debug_test_addr(&sin)) 00986 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00987 break; 00988 case RTCP_PT_BYE: 00989 if (rtcp_debug_test_addr(&sin)) 00990 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00991 break; 00992 default: 00993 if (option_debug) 00994 ast_log(LOG_DEBUG, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00995 break; 00996 } 00997 position += (length + 1); 00998 } 00999 01000 return f; 01001 }
int ast_rtcp_send_h261fur | ( | void * | data | ) |
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
Definition at line 2366 of file rtp.c.
References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.
02367 { 02368 struct ast_rtp *rtp = data; 02369 int res; 02370 02371 rtp->rtcp->sendfur = 1; 02372 res = ast_rtcp_write(data); 02373 02374 return res; 02375 }
size_t ast_rtp_alloc_size | ( | void | ) |
Get the amount of space required to hold an RTP session.
Definition at line 398 of file rtp.c.
Referenced by process_sdp().
00399 { 00400 return sizeof(struct ast_rtp); 00401 }
int ast_rtp_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
int | timeoutms | |||
) |
Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
Definition at line 3304 of file rtp.c.
References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
03305 { 03306 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03307 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03308 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03309 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03310 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03311 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03312 int codec0 = 0, codec1 = 0; 03313 void *pvt0 = NULL, *pvt1 = NULL; 03314 03315 /* Lock channels */ 03316 ast_channel_lock(c0); 03317 while(ast_channel_trylock(c1)) { 03318 ast_channel_unlock(c0); 03319 usleep(1); 03320 ast_channel_lock(c0); 03321 } 03322 03323 /* Ensure neither channel got hungup during lock avoidance */ 03324 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03325 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name); 03326 ast_channel_unlock(c0); 03327 ast_channel_unlock(c1); 03328 return AST_BRIDGE_FAILED; 03329 } 03330 03331 /* Find channel driver interfaces */ 03332 if (!(pr0 = get_proto(c0))) { 03333 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03334 ast_channel_unlock(c0); 03335 ast_channel_unlock(c1); 03336 return AST_BRIDGE_FAILED; 03337 } 03338 if (!(pr1 = get_proto(c1))) { 03339 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03340 ast_channel_unlock(c0); 03341 ast_channel_unlock(c1); 03342 return AST_BRIDGE_FAILED; 03343 } 03344 03345 /* Get channel specific interface structures */ 03346 pvt0 = c0->tech_pvt; 03347 pvt1 = c1->tech_pvt; 03348 03349 /* Get audio and video interface (if native bridge is possible) */ 03350 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03351 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03352 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03353 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03354 03355 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03356 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03357 audio_p0_res = AST_RTP_GET_FAILED; 03358 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03359 audio_p1_res = AST_RTP_GET_FAILED; 03360 03361 /* Check if a bridge is possible (partial/native) */ 03362 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03363 /* Somebody doesn't want to play... */ 03364 ast_channel_unlock(c0); 03365 ast_channel_unlock(c1); 03366 return AST_BRIDGE_FAILED_NOWARN; 03367 } 03368 03369 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03370 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03371 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03372 audio_p0_res = AST_RTP_TRY_PARTIAL; 03373 } 03374 03375 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03376 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03377 audio_p1_res = AST_RTP_TRY_PARTIAL; 03378 } 03379 03380 /* If both sides are not using the same method of DTMF transmission 03381 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03382 * -------------------------------------------------- 03383 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03384 * |-----------|------------|-----------------------| 03385 * | Inband | False | True | 03386 * | RFC2833 | True | True | 03387 * | SIP INFO | False | False | 03388 * -------------------------------------------------- 03389 * However, if DTMF from both channels is being monitored by the core, then 03390 * we can still do packet-to-packet bridging, because passing through the 03391 * core will handle DTMF mode translation. 03392 */ 03393 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03394 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03395 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03396 ast_channel_unlock(c0); 03397 ast_channel_unlock(c1); 03398 return AST_BRIDGE_FAILED_NOWARN; 03399 } 03400 audio_p0_res = AST_RTP_TRY_PARTIAL; 03401 audio_p1_res = AST_RTP_TRY_PARTIAL; 03402 } 03403 03404 /* If we need to feed frames into the core don't do a P2P bridge */ 03405 if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) || 03406 (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) { 03407 ast_channel_unlock(c0); 03408 ast_channel_unlock(c1); 03409 return AST_BRIDGE_FAILED_NOWARN; 03410 } 03411 03412 /* Get codecs from both sides */ 03413 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03414 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03415 if (codec0 && codec1 && !(codec0 & codec1)) { 03416 /* Hey, we can't do native bridging if both parties speak different codecs */ 03417 if (option_debug) 03418 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03419 ast_channel_unlock(c0); 03420 ast_channel_unlock(c1); 03421 return AST_BRIDGE_FAILED_NOWARN; 03422 } 03423 03424 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03425 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03426 struct ast_format_list fmt0, fmt1; 03427 03428 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03429 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03430 if (option_debug) 03431 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03432 ast_channel_unlock(c0); 03433 ast_channel_unlock(c1); 03434 return AST_BRIDGE_FAILED_NOWARN; 03435 } 03436 /* They must also be using the same packetization */ 03437 fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat); 03438 fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat); 03439 if (fmt0.cur_ms != fmt1.cur_ms) { 03440 if (option_debug) 03441 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n"); 03442 ast_channel_unlock(c0); 03443 ast_channel_unlock(c1); 03444 return AST_BRIDGE_FAILED_NOWARN; 03445 } 03446 03447 if (option_verbose > 2) 03448 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03449 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03450 } else { 03451 if (option_verbose > 2) 03452 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03453 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03454 } 03455 03456 return res; 03457 }
void ast_rtp_change_source | ( | struct ast_rtp * | instance | ) |
Indicate a new source of audio has dropped in and the ssrc should change.
instance | Instance that the new media source is feeding into |
ast_rtp_instance_change_source(instance);
This indicates that the source of media that is feeding the instance pointed to by instance has changed and that the marker bit should be set and the SSRC updated.
Definition at line 2021 of file rtp.c.
References ast_log(), ast_random(), LOG_DEBUG, ast_rtp::set_marker_bit, and ast_rtp::ssrc.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), and skinny_indicate().
02022 { 02023 unsigned int ssrc = ast_random(); 02024 /* We simply set this bit so that the next packet sent will have the marker bit turned on */ 02025 rtp->set_marker_bit = 1; 02026 ast_log(LOG_DEBUG, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc); 02027 02028 rtp->ssrc = ssrc; 02029 }
int ast_rtp_codec_getformat | ( | int | pt | ) |
Definition at line 2748 of file rtp.c.
References rtpPayloadType::code, and MAX_RTP_PT.
Referenced by process_sdp().
02749 { 02750 if (pt < 0 || pt > MAX_RTP_PT) 02751 return 0; /* bogus payload type */ 02752 02753 if (static_RTP_PT[pt].isAstFormat) 02754 return static_RTP_PT[pt].code; 02755 else 02756 return 0; 02757 }
struct ast_codec_pref* ast_rtp_codec_getpref | ( | struct ast_rtp * | rtp | ) | [read] |
Definition at line 2743 of file rtp.c.
References ast_rtp::pref.
Referenced by add_codec_to_sdp(), and process_sdp().
02744 { 02745 return &rtp->pref; 02746 }
int ast_rtp_codec_setpref | ( | struct ast_rtp * | rtp, | |
struct ast_codec_pref * | prefs | |||
) |
Definition at line 2730 of file rtp.c.
References ast_smoother_free(), ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, and ast_rtp::smoother.
Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().
02731 { 02732 int x; 02733 for (x = 0; x < 32; x++) { /* Ugly way */ 02734 rtp->pref.order[x] = prefs->order[x]; 02735 rtp->pref.framing[x] = prefs->framing[x]; 02736 } 02737 if (rtp->smoother) 02738 ast_smoother_free(rtp->smoother); 02739 rtp->smoother = NULL; 02740 return 0; 02741 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 2149 of file rtp.c.
References ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose(), ast_rtp::bridge_lock, ast_rtcp::expected_prior, free, ast_rtp::io, ast_rtp::ioid, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.
Referenced by __oh323_destroy(), __sip_destroy(), check_user_full(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().
02150 { 02151 if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) { 02152 /*Print some info on the call here */ 02153 ast_verbose(" RTP-stats\n"); 02154 ast_verbose("* Our Receiver:\n"); 02155 ast_verbose(" SSRC: %u\n", rtp->themssrc); 02156 ast_verbose(" Received packets: %u\n", rtp->rxcount); 02157 ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior); 02158 ast_verbose(" Jitter: %.4f\n", rtp->rxjitter); 02159 ast_verbose(" Transit: %.4f\n", rtp->rxtransit); 02160 ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count); 02161 ast_verbose("* Our Sender:\n"); 02162 ast_verbose(" SSRC: %u\n", rtp->ssrc); 02163 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02164 ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost); 02165 ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0); 02166 ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count); 02167 ast_verbose(" RTT: %f\n", rtp->rtcp->rtt); 02168 } 02169 02170 if (rtp->smoother) 02171 ast_smoother_free(rtp->smoother); 02172 if (rtp->ioid) 02173 ast_io_remove(rtp->io, rtp->ioid); 02174 if (rtp->s > -1) 02175 close(rtp->s); 02176 if (rtp->rtcp) { 02177 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02178 close(rtp->rtcp->s); 02179 free(rtp->rtcp); 02180 rtp->rtcp=NULL; 02181 } 02182 02183 ast_mutex_destroy(&rtp->bridge_lock); 02184 02185 free(rtp); 02186 }
int ast_rtp_early_bridge | ( | struct ast_channel * | dest, | |
struct ast_channel * | src | |||
) |
If possible, create an early bridge directly between the devices without having to send a re-invite later.
Definition at line 1491 of file rtp.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01492 { 01493 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01494 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01495 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01496 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01497 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01498 int srccodec, destcodec, nat_active = 0; 01499 01500 /* Lock channels */ 01501 ast_channel_lock(dest); 01502 if (src) { 01503 while(ast_channel_trylock(src)) { 01504 ast_channel_unlock(dest); 01505 usleep(1); 01506 ast_channel_lock(dest); 01507 } 01508 } 01509 01510 /* Find channel driver interfaces */ 01511 destpr = get_proto(dest); 01512 if (src) 01513 srcpr = get_proto(src); 01514 if (!destpr) { 01515 if (option_debug) 01516 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01517 ast_channel_unlock(dest); 01518 if (src) 01519 ast_channel_unlock(src); 01520 return 0; 01521 } 01522 if (!srcpr) { 01523 if (option_debug) 01524 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>"); 01525 ast_channel_unlock(dest); 01526 if (src) 01527 ast_channel_unlock(src); 01528 return 0; 01529 } 01530 01531 /* Get audio and video interface (if native bridge is possible) */ 01532 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01533 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01534 if (srcpr) { 01535 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01536 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01537 } 01538 01539 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01540 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01541 /* Somebody doesn't want to play... */ 01542 ast_channel_unlock(dest); 01543 if (src) 01544 ast_channel_unlock(src); 01545 return 0; 01546 } 01547 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01548 srccodec = srcpr->get_codec(src); 01549 else 01550 srccodec = 0; 01551 if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec) 01552 destcodec = destpr->get_codec(dest); 01553 else 01554 destcodec = 0; 01555 /* Ensure we have at least one matching codec */ 01556 if (!(srccodec & destcodec)) { 01557 ast_channel_unlock(dest); 01558 if (src) 01559 ast_channel_unlock(src); 01560 return 0; 01561 } 01562 /* Consider empty media as non-existant */ 01563 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01564 srcp = NULL; 01565 /* If the client has NAT stuff turned on then just safe NAT is active */ 01566 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01567 nat_active = 1; 01568 /* Bridge media early */ 01569 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active)) 01570 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01571 ast_channel_unlock(dest); 01572 if (src) 01573 ast_channel_unlock(src); 01574 if (option_debug) 01575 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); 01576 return 1; 01577 }
int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 513 of file rtp.c.
References ast_rtp::s.
Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().
00514 { 00515 return rtp->s; 00516 }
Definition at line 2060 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.
Referenced by __sip_destroy(), and ast_rtp_read().
02061 { 02062 struct ast_rtp *bridged = NULL; 02063 02064 ast_mutex_lock(&rtp->bridge_lock); 02065 bridged = rtp->bridged; 02066 ast_mutex_unlock(&rtp->bridge_lock); 02067 02068 return bridged; 02069 }
void ast_rtp_get_current_formats | ( | struct ast_rtp * | rtp, | |
int * | astFormats, | |||
int * | nonAstFormats | |||
) |
Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
Definition at line 1713 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().
01715 { 01716 int pt; 01717 01718 ast_mutex_lock(&rtp->bridge_lock); 01719 01720 *astFormats = *nonAstFormats = 0; 01721 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01722 if (rtp->current_RTP_PT[pt].isAstFormat) { 01723 *astFormats |= rtp->current_RTP_PT[pt].code; 01724 } else { 01725 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01726 } 01727 } 01728 01729 ast_mutex_unlock(&rtp->bridge_lock); 01730 01731 return; 01732 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2042 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), bridge_native_loop(), do_monitor(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
02043 { 02044 if ((them->sin_family != AF_INET) || 02045 (them->sin_port != rtp->them.sin_port) || 02046 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02047 them->sin_family = AF_INET; 02048 them->sin_port = rtp->them.sin_port; 02049 them->sin_addr = rtp->them.sin_addr; 02050 return 1; 02051 } 02052 return 0; 02053 }
char* ast_rtp_get_quality | ( | struct ast_rtp * | rtp, | |
struct ast_rtp_quality * | qual | |||
) |
Return RTCP quality string.
Definition at line 2105 of file rtp.c.
References ast_rtcp::expected_prior, ast_rtp_quality::local_count, ast_rtp_quality::local_jitter, ast_rtp_quality::local_lostpackets, ast_rtp_quality::local_ssrc, ast_rtcp::quality, ast_rtcp::received_prior, ast_rtp_quality::remote_count, ast_rtp_quality::remote_jitter, ast_rtp_quality::remote_lostpackets, ast_rtp_quality::remote_ssrc, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp_quality::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.
Referenced by acf_channel_read(), handle_request_bye(), and sip_hangup().
02106 { 02107 /* 02108 *ssrc our ssrc 02109 *themssrc their ssrc 02110 *lp lost packets 02111 *rxjitter our calculated jitter(rx) 02112 *rxcount no. received packets 02113 *txjitter reported jitter of the other end 02114 *txcount transmitted packets 02115 *rlp remote lost packets 02116 *rtt round trip time 02117 */ 02118 02119 if (qual && rtp) { 02120 qual->local_ssrc = rtp->ssrc; 02121 qual->local_jitter = rtp->rxjitter; 02122 qual->local_count = rtp->rxcount; 02123 qual->remote_ssrc = rtp->themssrc; 02124 qual->remote_count = rtp->txcount; 02125 if (rtp->rtcp) { 02126 qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior; 02127 qual->remote_lostpackets = rtp->rtcp->reported_lost; 02128 qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0; 02129 qual->rtt = rtp->rtcp->rtt; 02130 } 02131 } 02132 if (rtp->rtcp) { 02133 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), 02134 "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", 02135 rtp->ssrc, 02136 rtp->themssrc, 02137 rtp->rtcp->expected_prior - rtp->rtcp->received_prior, 02138 rtp->rxjitter, 02139 rtp->rxcount, 02140 (double)rtp->rtcp->reported_jitter / 65536.0, 02141 rtp->txcount, 02142 rtp->rtcp->reported_lost, 02143 rtp->rtcp->rtt); 02144 return rtp->rtcp->quality; 02145 } else 02146 return "<Unknown> - RTP/RTCP has already been destroyed"; 02147 }
int ast_rtp_get_rtpholdtimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp hold timeout.
Definition at line 568 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by do_monitor().
00569 { 00570 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00571 return 0; 00572 return rtp->rtpholdtimeout; 00573 }
int ast_rtp_get_rtpkeepalive | ( | struct ast_rtp * | rtp | ) |
Get RTP keepalive interval.
Definition at line 576 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by do_monitor().
00577 { 00578 return rtp->rtpkeepalive; 00579 }
int ast_rtp_get_rtptimeout | ( | struct ast_rtp * | rtp | ) |
Get rtp timeout.
Definition at line 560 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by do_monitor().
00561 { 00562 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00563 return 0; 00564 return rtp->rtptimeout; 00565 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 2055 of file rtp.c.
References ast_rtp::us.
Referenced by add_sdp(), external_rtp_create(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), and oh323_set_rtp_peer().
int ast_rtp_getnat | ( | struct ast_rtp * | rtp | ) |
Definition at line 596 of file rtp.c.
References ast_test_flag, and FLAG_NAT_ACTIVE.
Referenced by sip_get_rtp_peer().
00597 { 00598 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00599 }
void ast_rtp_init | ( | void | ) |
Initialize the RTP system in Asterisk.
Definition at line 3842 of file rtp.c.
References ast_cli_register_multiple(), and ast_rtp_reload().
Referenced by main().
03843 { 03844 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03845 ast_rtp_reload(); 03846 }
int ast_rtp_lookup_code | ( | struct ast_rtp * | rtp, | |
int | isAstFormat, | |||
int | code | |||
) |
Looks up an RTP code out of our *static* outbound list.
Definition at line 1756 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by add_codec_to_answer(), add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), and bridge_p2p_rtp_write().
01757 { 01758 int pt = 0; 01759 01760 ast_mutex_lock(&rtp->bridge_lock); 01761 01762 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01763 code == rtp->rtp_lookup_code_cache_code) { 01764 /* Use our cached mapping, to avoid the overhead of the loop below */ 01765 pt = rtp->rtp_lookup_code_cache_result; 01766 ast_mutex_unlock(&rtp->bridge_lock); 01767 return pt; 01768 } 01769 01770 /* Check the dynamic list first */ 01771 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01772 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01773 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01774 rtp->rtp_lookup_code_cache_code = code; 01775 rtp->rtp_lookup_code_cache_result = pt; 01776 ast_mutex_unlock(&rtp->bridge_lock); 01777 return pt; 01778 } 01779 } 01780 01781 /* Then the static list */ 01782 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01783 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01784 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01785 rtp->rtp_lookup_code_cache_code = code; 01786 rtp->rtp_lookup_code_cache_result = pt; 01787 ast_mutex_unlock(&rtp->bridge_lock); 01788 return pt; 01789 } 01790 } 01791 01792 ast_mutex_unlock(&rtp->bridge_lock); 01793 01794 return -1; 01795 }
char* ast_rtp_lookup_mime_multiple | ( | char * | buf, | |
size_t | size, | |||
const int | capability, | |||
const int | isAstFormat, | |||
enum ast_rtp_options | options | |||
) |
Build a string of MIME subtype names from a capability list.
Definition at line 1816 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len, and name.
Referenced by process_sdp().
01818 { 01819 int format; 01820 unsigned len; 01821 char *end = buf; 01822 char *start = buf; 01823 01824 if (!buf || !size) 01825 return NULL; 01826 01827 snprintf(end, size, "0x%x (", capability); 01828 01829 len = strlen(end); 01830 end += len; 01831 size -= len; 01832 start = end; 01833 01834 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01835 if (capability & format) { 01836 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01837 01838 snprintf(end, size, "%s|", name); 01839 len = strlen(end); 01840 end += len; 01841 size -= len; 01842 } 01843 } 01844 01845 if (start == end) 01846 snprintf(start, size, "nothing)"); 01847 else if (size > 1) 01848 *(end -1) = ')'; 01849 01850 return buf; 01851 }
const char* ast_rtp_lookup_mime_subtype | ( | int | isAstFormat, | |
int | code, | |||
enum ast_rtp_options | options | |||
) |
Mapping an Asterisk code into a MIME subtype (string):.
Definition at line 1797 of file rtp.c.
References AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, mimeTypes, and payloadType.
Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().
01799 { 01800 unsigned int i; 01801 01802 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01803 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01804 if (isAstFormat && 01805 (code == AST_FORMAT_G726_AAL2) && 01806 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01807 return "G726-32"; 01808 else 01809 return mimeTypes[i].subtype; 01810 } 01811 } 01812 01813 return ""; 01814 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) | [read] |
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1734 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().
01735 { 01736 struct rtpPayloadType result; 01737 01738 result.isAstFormat = result.code = 0; 01739 01740 if (pt < 0 || pt > MAX_RTP_PT) 01741 return result; /* bogus payload type */ 01742 01743 /* Start with negotiated codecs */ 01744 ast_mutex_lock(&rtp->bridge_lock); 01745 result = rtp->current_RTP_PT[pt]; 01746 ast_mutex_unlock(&rtp->bridge_lock); 01747 01748 /* If it doesn't exist, check our static RTP type list, just in case */ 01749 if (!result.code) 01750 result = static_RTP_PT[pt]; 01751 01752 return result; 01753 }
int ast_rtp_make_compatible | ( | struct ast_channel * | dest, | |
struct ast_channel * | src, | |||
int | media | |||
) |
Definition at line 1579 of file rtp.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, ast_rtp_pt_copy(), AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.
Referenced by wait_for_answer().
01580 { 01581 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01582 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01583 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01584 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01585 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01586 int srccodec, destcodec; 01587 01588 /* Lock channels */ 01589 ast_channel_lock(dest); 01590 while(ast_channel_trylock(src)) { 01591 ast_channel_unlock(dest); 01592 usleep(1); 01593 ast_channel_lock(dest); 01594 } 01595 01596 /* Find channel driver interfaces */ 01597 if (!(destpr = get_proto(dest))) { 01598 if (option_debug) 01599 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01600 ast_channel_unlock(dest); 01601 ast_channel_unlock(src); 01602 return 0; 01603 } 01604 if (!(srcpr = get_proto(src))) { 01605 if (option_debug) 01606 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01607 ast_channel_unlock(dest); 01608 ast_channel_unlock(src); 01609 return 0; 01610 } 01611 01612 /* Get audio and video interface (if native bridge is possible) */ 01613 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01614 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01615 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01616 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01617 01618 /* Ensure we have at least one matching codec */ 01619 if (srcpr->get_codec) 01620 srccodec = srcpr->get_codec(src); 01621 else 01622 srccodec = 0; 01623 if (destpr->get_codec) 01624 destcodec = destpr->get_codec(dest); 01625 else 01626 destcodec = 0; 01627 01628 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01629 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) { 01630 /* Somebody doesn't want to play... */ 01631 ast_channel_unlock(dest); 01632 ast_channel_unlock(src); 01633 return 0; 01634 } 01635 ast_rtp_pt_copy(destp, srcp); 01636 if (vdestp && vsrcp) 01637 ast_rtp_pt_copy(vdestp, vsrcp); 01638 if (media) { 01639 /* Bridge early */ 01640 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01641 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01642 } 01643 ast_channel_unlock(dest); 01644 ast_channel_unlock(src); 01645 if (option_debug) 01646 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01647 return 1; 01648 }
struct ast_rtp* ast_rtp_new | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode | |||
) | [read] |
Initializate a RTP session.
sched | ||
io | ||
rtcpenable | ||
callbackmode |
Definition at line 1998 of file rtp.c.
References ast_rtp_new_with_bindaddr().
01999 { 02000 struct in_addr ia; 02001 02002 memset(&ia, 0, sizeof(ia)); 02003 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02004 }
void ast_rtp_new_init | ( | struct ast_rtp * | rtp | ) |
Initialize a new RTP structure.
Definition at line 1898 of file rtp.c.
References ast_mutex_init(), ast_random(), ast_set_flag, ast_rtp::bridge_lock, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, and ast_rtp::us.
Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().
01899 { 01900 ast_mutex_init(&rtp->bridge_lock); 01901 01902 rtp->them.sin_family = AF_INET; 01903 rtp->us.sin_family = AF_INET; 01904 rtp->ssrc = ast_random(); 01905 rtp->seqno = ast_random() & 0xffff; 01906 ast_set_flag(rtp, FLAG_HAS_DTMF); 01907 01908 return; 01909 }
struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | rtcpenable, | |||
int | callbackmode, | |||
struct in_addr | in | |||
) | [read] |
Initializate a RTP session using an in_addr structure.
This fuction gets called by ast_rtp_new().
sched | ||
io | ||
rtcpenable | ||
callbackmode | ||
in |
Definition at line 1911 of file rtp.c.
References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, errno, FLAG_CALLBACK_MODE, free, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::us, and ast_rtp::us.
Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), sip_alloc(), and start_rtp().
01912 { 01913 struct ast_rtp *rtp; 01914 int x; 01915 int first; 01916 int startplace; 01917 01918 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01919 return NULL; 01920 01921 ast_rtp_new_init(rtp); 01922 01923 rtp->s = rtp_socket(); 01924 if (rtp->s < 0) { 01925 free(rtp); 01926 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01927 return NULL; 01928 } 01929 if (sched && rtcpenable) { 01930 rtp->sched = sched; 01931 rtp->rtcp = ast_rtcp_new(); 01932 } 01933 01934 /* Select a random port number in the range of possible RTP */ 01935 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01936 x = x & ~1; 01937 /* Save it for future references. */ 01938 startplace = x; 01939 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01940 for (;;) { 01941 /* Must be an even port number by RTP spec */ 01942 rtp->us.sin_port = htons(x); 01943 rtp->us.sin_addr = addr; 01944 /* If there's rtcp, initialize it as well. */ 01945 if (rtp->rtcp) { 01946 rtp->rtcp->us.sin_port = htons(x + 1); 01947 rtp->rtcp->us.sin_addr = addr; 01948 } 01949 /* Try to bind it/them. */ 01950 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01951 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01952 break; 01953 if (!first) { 01954 /* Primary bind succeeded! Gotta recreate it */ 01955 close(rtp->s); 01956 rtp->s = rtp_socket(); 01957 } 01958 if (errno != EADDRINUSE) { 01959 /* We got an error that wasn't expected, abort! */ 01960 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01961 close(rtp->s); 01962 if (rtp->rtcp) { 01963 close(rtp->rtcp->s); 01964 free(rtp->rtcp); 01965 } 01966 free(rtp); 01967 return NULL; 01968 } 01969 /* The port was used, increment it (by two). */ 01970 x += 2; 01971 /* Did we go over the limit ? */ 01972 if (x > rtpend) 01973 /* then, start from the begingig. */ 01974 x = (rtpstart + 1) & ~1; 01975 /* Check if we reached the place were we started. */ 01976 if (x == startplace) { 01977 /* If so, there's no ports available. */ 01978 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01979 close(rtp->s); 01980 if (rtp->rtcp) { 01981 close(rtp->rtcp->s); 01982 free(rtp->rtcp); 01983 } 01984 free(rtp); 01985 return NULL; 01986 } 01987 } 01988 rtp->sched = sched; 01989 rtp->io = io; 01990 if (callbackmode) { 01991 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01992 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01993 } 01994 ast_rtp_pt_default(rtp); 01995 return rtp; 01996 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Register interface to channel driver.
Definition at line 2859 of file rtp.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, protos, and ast_rtp_protocol::type.
Referenced by load_module().
02860 { 02861 struct ast_rtp_protocol *cur; 02862 02863 AST_LIST_LOCK(&protos); 02864 AST_LIST_TRAVERSE(&protos, cur, list) { 02865 if (!strcmp(cur->type, proto->type)) { 02866 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02867 AST_LIST_UNLOCK(&protos); 02868 return -1; 02869 } 02870 } 02871 AST_LIST_INSERT_HEAD(&protos, proto, list); 02872 AST_LIST_UNLOCK(&protos); 02873 02874 return 0; 02875 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Unregister interface to channel driver.
Definition at line 2851 of file rtp.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.
Referenced by load_module(), and unload_module().
02852 { 02853 AST_LIST_LOCK(&protos); 02854 AST_LIST_REMOVE(&protos, proto, list); 02855 AST_LIST_UNLOCK(&protos); 02856 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Setting RTP payload types from lines in a SDP description:.
Definition at line 1415 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by gtalk_alloc(), and process_sdp().
01416 { 01417 int i; 01418 01419 if (!rtp) 01420 return; 01421 01422 ast_mutex_lock(&rtp->bridge_lock); 01423 01424 for (i = 0; i < MAX_RTP_PT; ++i) { 01425 rtp->current_RTP_PT[i].isAstFormat = 0; 01426 rtp->current_RTP_PT[i].code = 0; 01427 } 01428 01429 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01430 rtp->rtp_lookup_code_cache_code = 0; 01431 rtp->rtp_lookup_code_cache_result = 0; 01432 01433 ast_mutex_unlock(&rtp->bridge_lock); 01434 }
Copy payload types between RTP structures.
Definition at line 1455 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by ast_rtp_make_compatible(), and process_sdp().
01456 { 01457 unsigned int i; 01458 01459 ast_mutex_lock(&dest->bridge_lock); 01460 ast_mutex_lock(&src->bridge_lock); 01461 01462 for (i=0; i < MAX_RTP_PT; ++i) { 01463 dest->current_RTP_PT[i].isAstFormat = 01464 src->current_RTP_PT[i].isAstFormat; 01465 dest->current_RTP_PT[i].code = 01466 src->current_RTP_PT[i].code; 01467 } 01468 dest->rtp_lookup_code_cache_isAstFormat = 0; 01469 dest->rtp_lookup_code_cache_code = 0; 01470 dest->rtp_lookup_code_cache_result = 0; 01471 01472 ast_mutex_unlock(&src->bridge_lock); 01473 ast_mutex_unlock(&dest->bridge_lock); 01474 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Set payload types to defaults.
Definition at line 1436 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by ast_rtp_new_with_bindaddr().
01437 { 01438 int i; 01439 01440 ast_mutex_lock(&rtp->bridge_lock); 01441 01442 /* Initialize to default payload types */ 01443 for (i = 0; i < MAX_RTP_PT; ++i) { 01444 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01445 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01446 } 01447 01448 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01449 rtp->rtp_lookup_code_cache_code = 0; 01450 rtp->rtp_lookup_code_cache_result = 0; 01451 01452 ast_mutex_unlock(&rtp->bridge_lock); 01453 }
Definition at line 1105 of file rtp.c.
References ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_inet_ntoa(), AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_TAIL, ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, event, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, frames, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, len, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::rtcp, rtp_debug_test_addr(), 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, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtcp::them, ast_rtp::them, ast_rtp::themssrc, and ast_frame::ts.
Referenced by gtalk_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().
01106 { 01107 int res; 01108 struct sockaddr_in sin; 01109 socklen_t len; 01110 unsigned int seqno; 01111 int version; 01112 int payloadtype; 01113 int hdrlen = 12; 01114 int padding; 01115 int mark; 01116 int ext; 01117 int cc; 01118 unsigned int ssrc; 01119 unsigned int timestamp; 01120 unsigned int *rtpheader; 01121 struct rtpPayloadType rtpPT; 01122 struct ast_rtp *bridged = NULL; 01123 AST_LIST_HEAD_NOLOCK(, ast_frame) frames; 01124 01125 /* If time is up, kill it */ 01126 if (rtp->sending_digit) 01127 ast_rtp_senddigit_continuation(rtp); 01128 01129 len = sizeof(sin); 01130 01131 /* Cache where the header will go */ 01132 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01133 0, (struct sockaddr *)&sin, &len); 01134 01135 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01136 if (res < 0) { 01137 ast_assert(errno != EBADF); 01138 if (errno != EAGAIN) { 01139 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno)); 01140 return NULL; 01141 } 01142 return &ast_null_frame; 01143 } 01144 01145 if (res < hdrlen) { 01146 ast_log(LOG_WARNING, "RTP Read too short\n"); 01147 return &ast_null_frame; 01148 } 01149 01150 /* Get fields */ 01151 seqno = ntohl(rtpheader[0]); 01152 01153 /* Check RTP version */ 01154 version = (seqno & 0xC0000000) >> 30; 01155 if (!version) { 01156 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01157 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01158 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01159 } 01160 return &ast_null_frame; 01161 } 01162 01163 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01164 /* If we don't have the other side's address, then ignore this */ 01165 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01166 return &ast_null_frame; 01167 #endif 01168 01169 /* Send to whoever send to us if NAT is turned on */ 01170 if (rtp->nat) { 01171 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01172 (rtp->them.sin_port != sin.sin_port)) { 01173 rtp->them = sin; 01174 if (rtp->rtcp) { 01175 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01176 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01177 } 01178 rtp->rxseqno = 0; 01179 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01180 if (option_debug || rtpdebug) 01181 ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 01182 } 01183 } 01184 01185 /* If we are bridged to another RTP stream, send direct */ 01186 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01187 return &ast_null_frame; 01188 01189 if (version != 2) 01190 return &ast_null_frame; 01191 01192 payloadtype = (seqno & 0x7f0000) >> 16; 01193 padding = seqno & (1 << 29); 01194 mark = seqno & (1 << 23); 01195 ext = seqno & (1 << 28); 01196 cc = (seqno & 0xF000000) >> 24; 01197 seqno &= 0xffff; 01198 timestamp = ntohl(rtpheader[1]); 01199 ssrc = ntohl(rtpheader[2]); 01200 01201 AST_LIST_HEAD_INIT_NOLOCK(&frames); 01202 /* Force a marker bit and change SSRC if the SSRC changes */ 01203 if (rtp->rxssrc && rtp->rxssrc != ssrc) { 01204 struct ast_frame *f, srcupdate; 01205 srcupdate.frametype = AST_FRAME_CONTROL; 01206 srcupdate.subclass = AST_CONTROL_SRCCHANGE; 01207 if (!mark) { 01208 if (option_debug || rtpdebug) 01209 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01210 mark = 1; 01211 } 01212 01213 f = ast_frisolate(&srcupdate); 01214 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01215 } 01216 01217 rtp->rxssrc = ssrc; 01218 01219 if (padding) { 01220 /* Remove padding bytes */ 01221 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01222 } 01223 01224 if (cc) { 01225 /* CSRC fields present */ 01226 hdrlen += cc*4; 01227 } 01228 01229 if (ext) { 01230 /* RTP Extension present */ 01231 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 01232 hdrlen += 4; 01233 } 01234 01235 if (res < hdrlen) { 01236 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01237 return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; 01238 } 01239 01240 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01241 01242 if (rtp->rxcount==1) { 01243 /* This is the first RTP packet successfully received from source */ 01244 rtp->seedrxseqno = seqno; 01245 } 01246 01247 /* Do not schedule RR if RTCP isn't run */ 01248 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01249 /* Schedule transmission of Receiver Report */ 01250 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01251 } 01252 if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */ 01253 rtp->cycles += RTP_SEQ_MOD; 01254 01255 rtp->lastrxseqno = seqno; 01256 01257 if (rtp->themssrc==0) 01258 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01259 01260 if (rtp_debug_test_addr(&sin)) 01261 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01262 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01263 01264 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01265 if (!rtpPT.isAstFormat) { 01266 struct ast_frame *f = NULL; 01267 01268 /* This is special in-band data that's not one of our codecs */ 01269 if (rtpPT.code == AST_RTP_DTMF) { 01270 /* It's special -- rfc2833 process it */ 01271 if (rtp_debug_test_addr(&sin)) { 01272 unsigned char *data; 01273 unsigned int event; 01274 unsigned int event_end; 01275 unsigned int duration; 01276 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01277 event = ntohl(*((unsigned int *)(data))); 01278 event >>= 24; 01279 event_end = ntohl(*((unsigned int *)(data))); 01280 event_end <<= 8; 01281 event_end >>= 24; 01282 duration = ntohl(*((unsigned int *)(data))); 01283 duration &= 0xFFFF; 01284 ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration); 01285 } 01286 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp); 01287 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01288 /* It's really special -- process it the Cisco way */ 01289 if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) { 01290 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01291 rtp->lastevent = seqno; 01292 } 01293 } else if (rtpPT.code == AST_RTP_CN) { 01294 /* Comfort Noise */ 01295 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01296 } else { 01297 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01298 } 01299 if (f) { 01300 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01301 return AST_LIST_FIRST(&frames); 01302 } 01303 return &ast_null_frame; 01304 } 01305 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01306 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01307 01308 if (!rtp->lastrxts) 01309 rtp->lastrxts = timestamp; 01310 01311 rtp->rxseqno = seqno; 01312 01313 /* Record received timestamp as last received now */ 01314 rtp->lastrxts = timestamp; 01315 01316 rtp->f.mallocd = 0; 01317 rtp->f.datalen = res - hdrlen; 01318 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01319 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01320 rtp->f.seqno = seqno; 01321 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01322 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01323 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01324 ast_frame_byteswap_be(&rtp->f); 01325 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01326 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01327 ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); 01328 rtp->f.ts = timestamp / 8; 01329 rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000); 01330 } else { 01331 /* Video -- samples is # of samples vs. 90000 */ 01332 if (!rtp->lastividtimestamp) 01333 rtp->lastividtimestamp = timestamp; 01334 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01335 rtp->lastividtimestamp = timestamp; 01336 rtp->f.delivery.tv_sec = 0; 01337 rtp->f.delivery.tv_usec = 0; 01338 if (mark) 01339 rtp->f.subclass |= 0x1; 01340 01341 } 01342 rtp->f.src = "RTP"; 01343 return &rtp->f; 01344 }
int ast_rtp_reload | ( | void | ) |
Definition at line 3777 of file rtp.c.
References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and VERBOSE_PREFIX_2.
Referenced by ast_rtp_init().
03778 { 03779 struct ast_config *cfg; 03780 const char *s; 03781 03782 rtpstart = 5000; 03783 rtpend = 31000; 03784 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03785 cfg = ast_config_load("rtp.conf"); 03786 if (cfg) { 03787 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03788 rtpstart = atoi(s); 03789 if (rtpstart < 1024) 03790 rtpstart = 1024; 03791 if (rtpstart > 65535) 03792 rtpstart = 65535; 03793 } 03794 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03795 rtpend = atoi(s); 03796 if (rtpend < 1024) 03797 rtpend = 1024; 03798 if (rtpend > 65535) 03799 rtpend = 65535; 03800 } 03801 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03802 rtcpinterval = atoi(s); 03803 if (rtcpinterval == 0) 03804 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03805 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03806 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03807 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03808 rtcpinterval = RTCP_MAX_INTERVALMS; 03809 } 03810 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03811 #ifdef SO_NO_CHECK 03812 if (ast_false(s)) 03813 nochecksums = 1; 03814 else 03815 nochecksums = 0; 03816 #else 03817 if (ast_false(s)) 03818 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03819 #endif 03820 } 03821 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03822 dtmftimeout = atoi(s); 03823 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03824 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03825 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03826 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03827 }; 03828 } 03829 ast_config_destroy(cfg); 03830 } 03831 if (rtpstart >= rtpend) { 03832 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03833 rtpstart = 5000; 03834 rtpend = 31000; 03835 } 03836 if (option_verbose > 1) 03837 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03838 return 0; 03839 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 2085 of file rtp.c.
References ast_rtp::dtmfcount, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.
02086 { 02087 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02088 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02089 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02090 rtp->lastts = 0; 02091 rtp->lastdigitts = 0; 02092 rtp->lastrxts = 0; 02093 rtp->lastividtimestamp = 0; 02094 rtp->lastovidtimestamp = 0; 02095 rtp->lasteventseqn = 0; 02096 rtp->lastevent = 0; 02097 rtp->lasttxformat = 0; 02098 rtp->lastrxformat = 0; 02099 rtp->dtmfcount = 0; 02100 rtp->dtmfsamples = 0; 02101 rtp->seqno = 0; 02102 rtp->rxseqno = 0; 02103 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
generate comfort noice (CNG)
Definition at line 2600 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::data, ast_rtp::dtmfmute, errno, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by do_monitor().
02601 { 02602 unsigned int *rtpheader; 02603 int hdrlen = 12; 02604 int res; 02605 int payload; 02606 char data[256]; 02607 level = 127 - (level & 0x7f); 02608 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02609 02610 /* If we have no peer, return immediately */ 02611 if (!rtp->them.sin_addr.s_addr) 02612 return 0; 02613 02614 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02615 02616 /* Get a pointer to the header */ 02617 rtpheader = (unsigned int *)data; 02618 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02619 rtpheader[1] = htonl(rtp->lastts); 02620 rtpheader[2] = htonl(rtp->ssrc); 02621 data[12] = level; 02622 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02623 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02624 if (res <0) 02625 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 02626 if (rtp_debug_test_addr(&rtp->them)) 02627 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02628 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02629 02630 } 02631 return 0; 02632 }
int ast_rtp_senddigit_begin | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
Send begin frames for DTMF.
Definition at line 2208 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by mgcp_senddigit_begin(), oh323_digit_begin(), and sip_senddigit_begin().
02209 { 02210 unsigned int *rtpheader; 02211 int hdrlen = 12, res = 0, i = 0, payload = 0; 02212 char data[256]; 02213 02214 if ((digit <= '9') && (digit >= '0')) 02215 digit -= '0'; 02216 else if (digit == '*') 02217 digit = 10; 02218 else if (digit == '#') 02219 digit = 11; 02220 else if ((digit >= 'A') && (digit <= 'D')) 02221 digit = digit - 'A' + 12; 02222 else if ((digit >= 'a') && (digit <= 'd')) 02223 digit = digit - 'a' + 12; 02224 else { 02225 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02226 return 0; 02227 } 02228 02229 /* If we have no peer, return immediately */ 02230 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02231 return 0; 02232 02233 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02234 02235 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02236 rtp->send_duration = 160; 02237 02238 /* Get a pointer to the header */ 02239 rtpheader = (unsigned int *)data; 02240 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02241 rtpheader[1] = htonl(rtp->lastdigitts); 02242 rtpheader[2] = htonl(rtp->ssrc); 02243 02244 for (i = 0; i < 2; i++) { 02245 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02246 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02247 if (res < 0) 02248 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02249 ast_inet_ntoa(rtp->them.sin_addr), 02250 ntohs(rtp->them.sin_port), strerror(errno)); 02251 if (rtp_debug_test_addr(&rtp->them)) 02252 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02253 ast_inet_ntoa(rtp->them.sin_addr), 02254 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02255 /* Increment sequence number */ 02256 rtp->seqno++; 02257 /* Increment duration */ 02258 rtp->send_duration += 160; 02259 /* Clear marker bit and set seqno */ 02260 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02261 } 02262 02263 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02264 rtp->sending_digit = 1; 02265 rtp->send_digit = digit; 02266 rtp->send_payload = payload; 02267 02268 return 0; 02269 }
int ast_rtp_senddigit_end | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 586 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00587 { 00588 rtp->callback = callback; 00589 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 581 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00582 { 00583 rtp->data = data; 00584 }
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Activate payload type.
Definition at line 1654 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, ast_rtp::current_RTP_PT, and MAX_RTP_PT.
Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().
01655 { 01656 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01657 return; /* bogus payload type */ 01658 01659 ast_mutex_lock(&rtp->bridge_lock); 01660 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01661 ast_mutex_unlock(&rtp->bridge_lock); 01662 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 2031 of file rtp.c.
References ast_rtp::rtcp, ast_rtp::rxseqno, ast_rtcp::them, and ast_rtp::them.
Referenced by handle_open_receive_channel_ack_message(), process_sdp(), and setup_rtp_connection().
02032 { 02033 rtp->them.sin_port = them->sin_port; 02034 rtp->them.sin_addr = them->sin_addr; 02035 if (rtp->rtcp) { 02036 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02037 rtp->rtcp->them.sin_addr = them->sin_addr; 02038 } 02039 rtp->rxseqno = 0; 02040 }
void ast_rtp_set_rtpholdtimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp hold timeout.
Definition at line 548 of file rtp.c.
References ast_rtp::rtpholdtimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00549 { 00550 rtp->rtpholdtimeout = timeout; 00551 }
void ast_rtp_set_rtpkeepalive | ( | struct ast_rtp * | rtp, | |
int | period | |||
) |
set RTP keepalive interval
Definition at line 554 of file rtp.c.
References ast_rtp::rtpkeepalive.
Referenced by create_addr_from_peer(), and sip_alloc().
00555 { 00556 rtp->rtpkeepalive = period; 00557 }
int ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
int | pt, | |||
char * | mimeType, | |||
char * | mimeSubtype, | |||
enum ast_rtp_options | options | |||
) |
Initiate payload type to a known MIME media type for a codec.
Initiate payload type to a known MIME media type for a codec.
Definition at line 1681 of file rtp.c.
References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, subtype, and type.
Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), process_sdp(), and set_dtmf_payload().
01684 { 01685 unsigned int i; 01686 int found = 0; 01687 01688 if (pt < 0 || pt > MAX_RTP_PT) 01689 return -1; /* bogus payload type */ 01690 01691 ast_mutex_lock(&rtp->bridge_lock); 01692 01693 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01694 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01695 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01696 found = 1; 01697 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01698 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01699 mimeTypes[i].payloadType.isAstFormat && 01700 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01701 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01702 break; 01703 } 01704 } 01705 01706 ast_mutex_unlock(&rtp->bridge_lock); 01707 01708 return (found ? 0 : -1); 01709 }
void ast_rtp_set_rtptimeout | ( | struct ast_rtp * | rtp, | |
int | timeout | |||
) |
Set rtp timeout.
Definition at line 542 of file rtp.c.
References ast_rtp::rtptimeout.
Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().
00543 { 00544 rtp->rtptimeout = timeout; 00545 }
void ast_rtp_set_rtptimers_onhold | ( | struct ast_rtp * | rtp | ) |
Definition at line 535 of file rtp.c.
References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.
Referenced by handle_response_invite().
00536 { 00537 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00538 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00539 }
void ast_rtp_setdtmf | ( | struct ast_rtp * | rtp, | |
int | dtmf | |||
) |
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 601 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_DTMF.
Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), sip_alloc(), and sip_dtmfmode().
00602 { 00603 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00604 }
void ast_rtp_setdtmfcompensate | ( | struct ast_rtp * | rtp, | |
int | compensate | |||
) |
Compensate for devices that send RFC2833 packets all at once.
Definition at line 606 of file rtp.c.
References ast_set2_flag, and FLAG_DTMF_COMPENSATE.
Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), and sip_alloc().
00607 { 00608 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00609 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 591 of file rtp.c.
References ast_rtp::nat.
Referenced by __oh323_rtp_create(), do_setnat(), oh323_rtp_read(), and start_rtp().
void ast_rtp_setstun | ( | struct ast_rtp * | rtp, | |
int | stun_enable | |||
) |
Enable STUN capability.
Definition at line 611 of file rtp.c.
References ast_set2_flag, and FLAG_HAS_STUN.
Referenced by gtalk_new().
00612 { 00613 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00614 }
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 2006 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by __oh323_rtp_create(), and sip_alloc().
02007 { 02008 int res; 02009 02010 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 02011 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 02012 return res; 02013 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 2071 of file rtp.c.
References ast_clear_flag, AST_SCHED_DEL, FLAG_P2P_SENT_MARK, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, ast_rtcp::them, and ast_rtp::them.
Referenced by process_sdp(), setup_rtp_connection(), and stop_media_flows().
02072 { 02073 AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid); 02074 02075 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02076 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02077 if (rtp->rtcp) { 02078 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02079 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02080 } 02081 02082 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02083 }
void ast_rtp_stun_request | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | suggestion, | |||
const char * | username | |||
) |
Definition at line 403 of file rtp.c.
References append_attr_string(), stun_attr::attr, stun_header::ies, stun_header::msglen, stun_header::msgtype, ast_rtp::s, STUN_BINDREQ, stun_req_id(), stun_send(), and STUN_USERNAME.
Referenced by gtalk_update_stun().
00404 { 00405 struct stun_header *req; 00406 unsigned char reqdata[1024]; 00407 int reqlen, reqleft; 00408 struct stun_attr *attr; 00409 00410 req = (struct stun_header *)reqdata; 00411 stun_req_id(req); 00412 reqlen = 0; 00413 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00414 req->msgtype = 0; 00415 req->msglen = 0; 00416 attr = (struct stun_attr *)req->ies; 00417 if (username) 00418 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00419 req->msglen = htons(reqlen); 00420 req->msgtype = htons(STUN_BINDREQ); 00421 stun_send(rtp->s, suggestion, req); 00422 }
void ast_rtp_unset_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
clear payload type
Definition at line 1666 of file rtp.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by process_sdp().
01667 { 01668 if (pt < 0 || pt > MAX_RTP_PT) 01669 return; /* bogus payload type */ 01670 01671 ast_mutex_lock(&rtp->bridge_lock); 01672 rtp->current_RTP_PT[pt].isAstFormat = 0; 01673 rtp->current_RTP_PT[pt].code = 0; 01674 ast_mutex_unlock(&rtp->bridge_lock); 01675 }
void ast_rtp_update_source | ( | struct ast_rtp * | rtp | ) |
Definition at line 2015 of file rtp.c.
References ast_rtp::set_marker_bit.
Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), sip_write(), and skinny_indicate().
02016 { 02017 rtp->set_marker_bit = 1; 02018 return; 02019 }
Definition at line 2759 of file rtp.c.
References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), 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_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_frame::samples, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
Referenced by gtalk_write(), mgcp_write(), oh323_write(), sip_write(), and skinny_write().
02760 { 02761 struct ast_frame *f; 02762 int codec; 02763 int hdrlen = 12; 02764 int subclass; 02765 02766 02767 /* If we have no peer, return immediately */ 02768 if (!rtp->them.sin_addr.s_addr) 02769 return 0; 02770 02771 /* If there is no data length, return immediately */ 02772 if (!_f->datalen) 02773 return 0; 02774 02775 /* Make sure we have enough space for RTP header */ 02776 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 02777 ast_log(LOG_WARNING, "RTP can only send voice and video\n"); 02778 return -1; 02779 } 02780 02781 subclass = _f->subclass; 02782 if (_f->frametype == AST_FRAME_VIDEO) 02783 subclass &= ~0x1; 02784 02785 codec = ast_rtp_lookup_code(rtp, 1, subclass); 02786 if (codec < 0) { 02787 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 02788 return -1; 02789 } 02790 02791 if (rtp->lasttxformat != subclass) { 02792 /* New format, reset the smoother */ 02793 if (option_debug) 02794 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 02795 rtp->lasttxformat = subclass; 02796 if (rtp->smoother) 02797 ast_smoother_free(rtp->smoother); 02798 rtp->smoother = NULL; 02799 } 02800 02801 if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) { 02802 struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass); 02803 if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */ 02804 if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { 02805 ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); 02806 return -1; 02807 } 02808 if (fmt.flags) 02809 ast_smoother_set_flags(rtp->smoother, fmt.flags); 02810 if (option_debug) 02811 ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); 02812 } 02813 } 02814 if (rtp->smoother) { 02815 if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) { 02816 ast_smoother_feed_be(rtp->smoother, _f); 02817 } else { 02818 ast_smoother_feed(rtp->smoother, _f); 02819 } 02820 02821 while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { 02822 if (f->subclass == AST_FORMAT_G722) { 02823 /* G.722 is silllllllllllllly */ 02824 f->samples /= 2; 02825 } 02826 02827 ast_rtp_raw_write(rtp, f, codec); 02828 } 02829 } else { 02830 /* Don't buffer outgoing frames; send them one-per-packet: */ 02831 if (_f->offset < hdrlen) { 02832 f = ast_frdup(_f); 02833 } else { 02834 f = _f; 02835 } 02836 if (f->data) { 02837 if (f->subclass == AST_FORMAT_G722) { 02838 /* G.722 is silllllllllllllly */ 02839 f->samples /= 2; 02840 } 02841 ast_rtp_raw_write(rtp, f, codec); 02842 } 02843 if (f != _f) 02844 ast_frfree(f); 02845 } 02846 02847 return 0; 02848 }