#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk.h"
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.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/unaligned.h"

Go to the source code of this file.
Data Structures | |
| struct | ast_rtcp |
| Structure defining an RTCP session. More... | |
| struct | ast_rtp |
| struct | rtpPayloadType |
Defines | |
| #define | DEFAULT_DTMF_TIMEOUT 3000 |
| #define | FLAG_3389_WARNING (1 << 0) |
| #define | FLAG_NAT_ACTIVE (3 << 1) |
| #define | FLAG_NAT_INACTIVE (0 << 1) |
| #define | FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
| #define | MAX_RTP_PT 256 |
| #define | MAX_TIMESTAMP_SKEW 640 |
| #define | RTP_MTU 1200 |
Functions | |
| int | ast_rtcp_fd (struct ast_rtp *rtp) |
| static struct ast_rtcp * | ast_rtcp_new (void) |
| Initialize a new RTCP session. | |
| struct ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
| enum ast_bridge_result | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
| void | ast_rtp_destroy (struct ast_rtp *rtp) |
| int | ast_rtp_fd (struct ast_rtp *rtp) |
| void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
| int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
| void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
| void | ast_rtp_init (void) |
| int | ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code) |
| char * | ast_rtp_lookup_mime_multiple (char *buf, int size, const int capability, const int isAstFormat) |
| char * | ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code) |
| struct rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
| struct ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
| Initializate a RTP session. | |
| struct ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr) |
| Initializate a RTP session using an in_addr structure. | |
| void | ast_rtp_offered_from_local (struct ast_rtp *rtp, int local) |
| int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
| void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
| void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
| void | ast_rtp_pt_default (struct ast_rtp *rtp) |
| static int | ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec) |
| struct ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
| void | ast_rtp_reload (void) |
| void | ast_rtp_reset (struct ast_rtp *rtp) |
| int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
| int | ast_rtp_senddigit (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) |
| void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
| void | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype) |
| void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
| int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
| void | ast_rtp_stop (struct ast_rtp *rtp) |
| int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f) |
| 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_rtp_protocol * | get_proto (struct ast_channel *chan) |
| static struct ast_frame * | process_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len) |
| static struct ast_frame * | process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno) |
| Process RTP DTMF and events according to RFC 2833. | |
| static struct ast_frame * | process_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len) |
| Process Comfort Noise RTP. | |
| static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
| static int | rtp_do_debug (int fd, int argc, char *argv[]) |
| static int | rtp_do_debug_ip (int fd, int argc, char *argv[]) |
| static int | rtp_no_debug (int fd, int argc, char *argv[]) |
| static int | rtp_socket (void) |
| static int | rtpread (int *id, int fd, short events, void *cbdata) |
| static struct ast_frame * | send_dtmf (struct ast_rtp *rtp) |
Variables | |
| static struct ast_cli_entry | cli_debug |
| static struct ast_cli_entry | cli_debug_ip |
| static struct ast_cli_entry | cli_no_debug |
| static char | debug_usage [] |
| static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
| struct { | |
| struct rtpPayloadType payloadType | |
| char * subtype | |
| char * type | |
| } | mimeTypes [] |
| static char | no_debug_usage [] |
| static struct ast_rtp_protocol * | protos = NULL |
| static int | rtpdebug = 0 |
| static struct sockaddr_in | rtpdebugaddr |
| static int | rtpend = 0 |
| static int | rtpstart = 0 |
| static struct rtpPayloadType | static_RTP_PT [MAX_RTP_PT] |
RTP is deffined in RFC 3550.
Definition in file rtp.c.
| #define DEFAULT_DTMF_TIMEOUT 3000 |
| #define FLAG_3389_WARNING (1 << 0) |
| #define FLAG_NAT_ACTIVE (3 << 1) |
Definition at line 82 of file rtp.c.
Referenced by ast_rtp_bridge(), ast_rtp_raw_write(), and ast_rtp_read().
| #define FLAG_NAT_INACTIVE (0 << 1) |
| #define FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
| #define MAX_RTP_PT 256 |
Definition at line 79 of file rtp.c.
Referenced by ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_default(), ast_rtp_set_m_type(), and ast_rtp_set_rtpmap_type().
| #define MAX_TIMESTAMP_SKEW 640 |
Definition at line 57 of file rtp.c.
Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp().
| int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 158 of file rtp.c.
References ast_rtp::rtcp, and ast_rtcp::s.
Referenced by sip_new().
| static struct ast_rtcp* ast_rtcp_new | ( | void | ) | [static, read] |
Initialize a new RTCP session.
Definition at line 923 of file rtp.c.
References ast_log(), free, LOG_WARNING, malloc, rtp_socket(), ast_rtcp::s, and ast_rtcp::us.
Referenced by ast_rtp_new_with_bindaddr().
00924 { 00925 struct ast_rtcp *rtcp; 00926 rtcp = malloc(sizeof(struct ast_rtcp)); 00927 if (!rtcp) 00928 return NULL; 00929 memset(rtcp, 0, sizeof(struct ast_rtcp)); 00930 rtcp->s = rtp_socket(); 00931 rtcp->us.sin_family = AF_INET; 00932 if (rtcp->s < 0) { 00933 free(rtcp); 00934 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00935 return NULL; 00936 } 00937 return rtcp; 00938 }
Definition at line 370 of file rtp.c.
References AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, ast_rtcp::s, and ast_rtcp::them.
Referenced by sip_rtp_read().
00371 { 00372 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00373 socklen_t len; 00374 int hdrlen = 8; 00375 int res; 00376 struct sockaddr_in sin; 00377 unsigned int rtcpdata[1024]; 00378 char iabuf[INET_ADDRSTRLEN]; 00379 00380 if (!rtp || !rtp->rtcp) 00381 return &null_frame; 00382 00383 len = sizeof(sin); 00384 00385 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata), 00386 0, (struct sockaddr *)&sin, &len); 00387 00388 if (res < 0) { 00389 if (errno == EBADF) 00390 CRASH; 00391 if (errno != EAGAIN) { 00392 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up now.\n", strerror(errno)); 00393 return NULL; 00394 } 00395 return &null_frame; 00396 } 00397 00398 if (res < hdrlen) { 00399 ast_log(LOG_WARNING, "RTP Read too short\n"); 00400 return &null_frame; 00401 } 00402 00403 if (rtp->nat) { 00404 /* Send to whoever sent to us */ 00405 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00406 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00407 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00408 if (option_debug || rtpdebug) 00409 ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00410 } 00411 } 00412 if (option_debug) 00413 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00414 return &null_frame; 00415 }
| enum ast_bridge_result ast_rtp_bridge | ( | struct ast_channel * | c0, | |
| struct ast_channel * | c1, | |||
| int | flags, | |||
| struct ast_frame ** | fo, | |||
| struct ast_channel ** | rc, | |||
| int | timeoutms | |||
| ) |
Definition at line 1539 of file rtp.c.
References ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, inaddrcmp(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
01540 { 01541 struct ast_frame *f; 01542 struct ast_channel *who, *cs[3]; 01543 struct ast_rtp *p0, *p1; /* Audio RTP Channels */ 01544 struct ast_rtp *vp0, *vp1; /* Video RTP channels */ 01545 struct ast_rtp_protocol *pr0, *pr1; 01546 struct sockaddr_in ac0, ac1; 01547 struct sockaddr_in vac0, vac1; 01548 struct sockaddr_in t0, t1; 01549 struct sockaddr_in vt0, vt1; 01550 char iabuf[INET_ADDRSTRLEN]; 01551 01552 void *pvt0, *pvt1; 01553 int codec0,codec1, oldcodec0, oldcodec1; 01554 01555 memset(&vt0, 0, sizeof(vt0)); 01556 memset(&vt1, 0, sizeof(vt1)); 01557 memset(&vac0, 0, sizeof(vac0)); 01558 memset(&vac1, 0, sizeof(vac1)); 01559 01560 /* if need DTMF, cant native bridge */ 01561 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01562 return AST_BRIDGE_FAILED_NOWARN; 01563 01564 /* Lock channels */ 01565 ast_mutex_lock(&c0->lock); 01566 while(ast_mutex_trylock(&c1->lock)) { 01567 ast_mutex_unlock(&c0->lock); 01568 usleep(1); 01569 ast_mutex_lock(&c0->lock); 01570 } 01571 01572 /* Find channel driver interfaces */ 01573 pr0 = get_proto(c0); 01574 pr1 = get_proto(c1); 01575 if (!pr0) { 01576 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01577 ast_mutex_unlock(&c0->lock); 01578 ast_mutex_unlock(&c1->lock); 01579 return AST_BRIDGE_FAILED; 01580 } 01581 if (!pr1) { 01582 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01583 ast_mutex_unlock(&c0->lock); 01584 ast_mutex_unlock(&c1->lock); 01585 return AST_BRIDGE_FAILED; 01586 } 01587 01588 /* Get channel specific interface structures */ 01589 pvt0 = c0->tech_pvt; 01590 pvt1 = c1->tech_pvt; 01591 01592 /* Get audio and video interface (if native bridge is possible) */ 01593 p0 = pr0->get_rtp_info(c0); 01594 if (pr0->get_vrtp_info) 01595 vp0 = pr0->get_vrtp_info(c0); 01596 else 01597 vp0 = NULL; 01598 p1 = pr1->get_rtp_info(c1); 01599 if (pr1->get_vrtp_info) 01600 vp1 = pr1->get_vrtp_info(c1); 01601 else 01602 vp1 = NULL; 01603 01604 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01605 if (!p0 || !p1) { 01606 /* Somebody doesn't want to play... */ 01607 ast_mutex_unlock(&c0->lock); 01608 ast_mutex_unlock(&c1->lock); 01609 return AST_BRIDGE_FAILED_NOWARN; 01610 } 01611 /* Get codecs from both sides */ 01612 if (pr0->get_codec) 01613 codec0 = pr0->get_codec(c0); 01614 else 01615 codec0 = 0; 01616 if (pr1->get_codec) 01617 codec1 = pr1->get_codec(c1); 01618 else 01619 codec1 = 0; 01620 if (pr0->get_codec && pr1->get_codec) { 01621 /* Hey, we can't do reinvite if both parties speak different codecs */ 01622 if (!(codec0 & codec1)) { 01623 if (option_debug) 01624 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 01625 ast_mutex_unlock(&c0->lock); 01626 ast_mutex_unlock(&c1->lock); 01627 return AST_BRIDGE_FAILED_NOWARN; 01628 } 01629 } 01630 01631 /* Ok, we should be able to redirect the media. Start with one channel */ 01632 if (pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 01633 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01634 else { 01635 /* Store RTP peer */ 01636 ast_rtp_get_peer(p1, &ac1); 01637 if (vp1) 01638 ast_rtp_get_peer(vp1, &vac1); 01639 } 01640 /* Then test the other channel */ 01641 if (pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 01642 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01643 else { 01644 /* Store RTP peer */ 01645 ast_rtp_get_peer(p0, &ac0); 01646 if (vp0) 01647 ast_rtp_get_peer(vp0, &vac0); 01648 } 01649 ast_mutex_unlock(&c0->lock); 01650 ast_mutex_unlock(&c1->lock); 01651 /* External RTP Bridge up, now loop and see if something happes that force us to take the 01652 media back to Asterisk */ 01653 cs[0] = c0; 01654 cs[1] = c1; 01655 cs[2] = NULL; 01656 oldcodec0 = codec0; 01657 oldcodec1 = codec1; 01658 for (;;) { 01659 /* Check if something changed... */ 01660 if ((c0->tech_pvt != pvt0) || 01661 (c1->tech_pvt != pvt1) || 01662 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01663 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01664 if (c0->tech_pvt == pvt0) { 01665 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01666 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01667 } 01668 if (c1->tech_pvt == pvt1) { 01669 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01670 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01671 } 01672 return AST_BRIDGE_RETRY; 01673 } 01674 /* Now check if they have changed address */ 01675 ast_rtp_get_peer(p1, &t1); 01676 ast_rtp_get_peer(p0, &t0); 01677 if (pr0->get_codec) 01678 codec0 = pr0->get_codec(c0); 01679 if (pr1->get_codec) 01680 codec1 = pr1->get_codec(c1); 01681 if (vp1) 01682 ast_rtp_get_peer(vp1, &vt1); 01683 if (vp0) 01684 ast_rtp_get_peer(vp0, &vt0); 01685 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) { 01686 if (option_debug > 1) { 01687 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01688 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1); 01689 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 01690 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1); 01691 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01692 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 01693 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01694 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 01695 } 01696 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 01697 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01698 memcpy(&ac1, &t1, sizeof(ac1)); 01699 memcpy(&vac1, &vt1, sizeof(vac1)); 01700 oldcodec1 = codec1; 01701 } 01702 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01703 if (option_debug) { 01704 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01705 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0); 01706 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01707 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 01708 } 01709 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 01710 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01711 memcpy(&ac0, &t0, sizeof(ac0)); 01712 memcpy(&vac0, &vt0, sizeof(vac0)); 01713 oldcodec0 = codec0; 01714 } 01715 who = ast_waitfor_n(cs, 2, &timeoutms); 01716 if (!who) { 01717 if (!timeoutms) { 01718 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01719 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01720 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01721 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01722 return AST_BRIDGE_RETRY; 01723 } 01724 if (option_debug) 01725 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01726 /* check for hangup / whentohangup */ 01727 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01728 break; 01729 continue; 01730 } 01731 f = ast_read(who); 01732 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01733 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01734 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01735 *fo = f; 01736 *rc = who; 01737 if (option_debug) 01738 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01739 if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) { 01740 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01741 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01742 } 01743 if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) { 01744 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01745 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01746 } 01747 return AST_BRIDGE_COMPLETE; 01748 } else if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 01749 if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD) || 01750 (f->subclass == AST_CONTROL_VIDUPDATE)) { 01751 ast_indicate(who == c0 ? c1 : c0, f->subclass); 01752 ast_frfree(f); 01753 } else { 01754 *fo = f; 01755 *rc = who; 01756 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 01757 return AST_BRIDGE_COMPLETE; 01758 } 01759 } else { 01760 if ((f->frametype == AST_FRAME_DTMF) || 01761 (f->frametype == AST_FRAME_VOICE) || 01762 (f->frametype == AST_FRAME_VIDEO)) { 01763 /* Forward voice or DTMF frames if they happen upon us */ 01764 if (who == c0) { 01765 ast_write(c1, f); 01766 } else if (who == c1) { 01767 ast_write(c0, f); 01768 } 01769 } 01770 ast_frfree(f); 01771 } 01772 /* Swap priority not that it's a big deal at this point */ 01773 cs[2] = cs[0]; 01774 cs[0] = cs[1]; 01775 cs[1] = cs[2]; 01776 01777 } 01778 01779 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01780 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01781 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01782 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01783 01784 return AST_BRIDGE_FAILED; 01785 }
| void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 1105 of file rtp.c.
References ast_io_remove(), ast_smoother_free(), free, ast_rtp::io, ast_rtp::ioid, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, and ast_rtp::smoother.
Referenced by __oh323_destroy(), __sip_destroy(), cleanup_connection(), destroy_endpoint(), mgcp_hangup(), skinny_hangup(), start_rtp(), and unalloc_sub().
01106 { 01107 if (rtp->smoother) 01108 ast_smoother_free(rtp->smoother); 01109 if (rtp->ioid) 01110 ast_io_remove(rtp->io, rtp->ioid); 01111 if (rtp->s > -1) 01112 close(rtp->s); 01113 if (rtp->rtcp) { 01114 close(rtp->rtcp->s); 01115 free(rtp->rtcp); 01116 } 01117 free(rtp); 01118 }
| int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 153 of file rtp.c.
References ast_rtp::s.
Referenced by __oh323_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().
00154 { 00155 return rtp->s; 00156 }
| void ast_rtp_get_current_formats | ( | struct ast_rtp * | rtp, | |
| int * | astFormats, | |||
| int * | nonAstFormats | |||
| ) |
Definition at line 782 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by process_sdp().
00783 { 00784 int pt; 00785 00786 *astFormats = *nonAstFormats = 0; 00787 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00788 if (rtp->current_RTP_PT[pt].isAstFormat) { 00789 *astFormats |= rtp->current_RTP_PT[pt].code; 00790 } else { 00791 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 00792 } 00793 } 00794 }
| int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 1057 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), ast_rtp_bridge(), do_monitor(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
01058 { 01059 if ((them->sin_family != AF_INET) || 01060 (them->sin_port != rtp->them.sin_port) || 01061 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 01062 them->sin_family = AF_INET; 01063 them->sin_port = rtp->them.sin_port; 01064 them->sin_addr = rtp->them.sin_addr; 01065 return 1; 01066 } 01067 return 0; 01068 }
| void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | us | |||
| ) |
Definition at line 1070 of file rtp.c.
References ast_rtp::us.
Referenced by add_sdp(), external_rtp_create(), handle_message(), and oh323_set_rtp_peer().
| void ast_rtp_init | ( | void | ) |
Definition at line 1913 of file rtp.c.
References ast_cli_register(), and ast_rtp_reload().
Referenced by main().
01914 { 01915 ast_cli_register(&cli_debug); 01916 ast_cli_register(&cli_debug_ip); 01917 ast_cli_register(&cli_no_debug); 01918 ast_rtp_reload(); 01919 }
| int ast_rtp_lookup_code | ( | struct ast_rtp * | rtp, | |
| const int | isAstFormat, | |||
| const int | code | |||
| ) |
Definition at line 822 of file rtp.c.
References 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_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit(), and ast_rtp_write().
00822 { 00823 00824 int pt; 00825 00826 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 00827 code == rtp->rtp_lookup_code_cache_code) { 00828 00829 /* Use our cached mapping, to avoid the overhead of the loop below */ 00830 return rtp->rtp_lookup_code_cache_result; 00831 } 00832 00833 /* Check the dynamic list first */ 00834 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00835 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 00836 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00837 rtp->rtp_lookup_code_cache_code = code; 00838 rtp->rtp_lookup_code_cache_result = pt; 00839 return pt; 00840 } 00841 } 00842 00843 /* Then the static list */ 00844 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00845 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 00846 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00847 rtp->rtp_lookup_code_cache_code = code; 00848 rtp->rtp_lookup_code_cache_result = pt; 00849 return pt; 00850 } 00851 } 00852 return -1; 00853 }
| char* ast_rtp_lookup_mime_multiple | ( | char * | buf, | |
| int | size, | |||
| const int | capability, | |||
| const int | isAstFormat | |||
| ) |
Definition at line 867 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, and name.
Referenced by process_sdp().
00868 { 00869 int format; 00870 unsigned len; 00871 char *end = buf; 00872 char *start = buf; 00873 00874 if (!buf || !size) 00875 return NULL; 00876 00877 snprintf(end, size, "0x%x (", capability); 00878 00879 len = strlen(end); 00880 end += len; 00881 size -= len; 00882 start = end; 00883 00884 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 00885 if (capability & format) { 00886 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format); 00887 snprintf(end, size, "%s|", name); 00888 len = strlen(end); 00889 end += len; 00890 size -= len; 00891 } 00892 } 00893 00894 if (start == end) 00895 snprintf(start, size, "nothing)"); 00896 else if (size > 1) 00897 *(end -1) = ')'; 00898 00899 return buf; 00900 }
| char* ast_rtp_lookup_mime_subtype | ( | const int | isAstFormat, | |
| const int | code | |||
| ) |
Definition at line 855 of file rtp.c.
References 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().
00855 { 00856 00857 int i; 00858 00859 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00860 if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00861 return mimeTypes[i].subtype; 00862 } 00863 } 00864 return ""; 00865 }
| struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
| int | pt | |||
| ) | [read] |
Definition at line 803 of file rtp.c.
References rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by ast_rtp_read(), and setup_rtp_connection().
00804 { 00805 struct rtpPayloadType result; 00806 00807 result.isAstFormat = result.code = 0; 00808 if (pt < 0 || pt > MAX_RTP_PT) 00809 return result; /* bogus payload type */ 00810 00811 /* Start with the negotiated codecs */ 00812 if (!rtp->rtp_offered_from_local) 00813 result = rtp->current_RTP_PT[pt]; 00814 00815 /* If it doesn't exist, check our static RTP type list, just in case */ 00816 if (!result.code) 00817 result = static_RTP_PT[pt]; 00818 return result; 00819 }
| 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 1029 of file rtp.c.
References ast_rtp_new_with_bindaddr().
Referenced by start_rtp().
01030 { 01031 struct in_addr ia; 01032 01033 memset(&ia, 0, sizeof(ia)); 01034 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 01035 }
| 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 940 of file rtp.c.
References ast_io_add(), AST_IO_IN, ast_log(), ast_rtcp_new(), ast_rtp_pt_default(), free, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, malloc, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtcp::us, and ast_rtp::us.
Referenced by ast_rtp_new(), oh323_alloc(), sip_alloc(), and start_rtp().
00941 { 00942 struct ast_rtp *rtp; 00943 int x; 00944 int first; 00945 int startplace; 00946 rtp = malloc(sizeof(struct ast_rtp)); 00947 if (!rtp) 00948 return NULL; 00949 memset(rtp, 0, sizeof(struct ast_rtp)); 00950 rtp->them.sin_family = AF_INET; 00951 rtp->us.sin_family = AF_INET; 00952 rtp->s = rtp_socket(); 00953 rtp->ssrc = rand(); 00954 rtp->seqno = rand() & 0xffff; 00955 if (rtp->s < 0) { 00956 free(rtp); 00957 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 00958 return NULL; 00959 } 00960 if (sched && rtcpenable) { 00961 rtp->sched = sched; 00962 rtp->rtcp = ast_rtcp_new(); 00963 } 00964 00965 /* Select a random port number in the range of possible RTP */ 00966 x = (rand() % (rtpend-rtpstart)) + rtpstart; 00967 x = x & ~1; 00968 /* Save it for future references. */ 00969 startplace = x; 00970 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 00971 for (;;) { 00972 /* Must be an even port number by RTP spec */ 00973 rtp->us.sin_port = htons(x); 00974 rtp->us.sin_addr = addr; 00975 /* If there's rtcp, initialize it as well. */ 00976 if (rtp->rtcp) { 00977 rtp->rtcp->us.sin_addr = addr; 00978 rtp->rtcp->us.sin_port = htons(x + 1); 00979 } 00980 /* Try to bind it/them. */ 00981 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 00982 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 00983 break; 00984 if (!first) { 00985 /* Primary bind succeeded! Gotta recreate it */ 00986 close(rtp->s); 00987 rtp->s = rtp_socket(); 00988 } 00989 if (errno != EADDRINUSE) { 00990 /* We got an error that wasn't expected, abort! */ 00991 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 00992 close(rtp->s); 00993 if (rtp->rtcp) { 00994 close(rtp->rtcp->s); 00995 free(rtp->rtcp); 00996 } 00997 free(rtp); 00998 return NULL; 00999 } 01000 /* The port was used, increment it (by two). */ 01001 x += 2; 01002 /* Did we go over the limit ? */ 01003 if (x > rtpend) 01004 /* then, start from the begingig. */ 01005 x = (rtpstart + 1) & ~1; 01006 /* Check if we reached the place were we started. */ 01007 if (x == startplace) { 01008 /* If so, there's no ports available. */ 01009 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01010 close(rtp->s); 01011 if (rtp->rtcp) { 01012 close(rtp->rtcp->s); 01013 free(rtp->rtcp); 01014 } 01015 free(rtp); 01016 return NULL; 01017 } 01018 } 01019 if (io && sched && callbackmode) { 01020 /* Operate this one in a callback mode */ 01021 rtp->sched = sched; 01022 rtp->io = io; 01023 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01024 } 01025 ast_rtp_pt_default(rtp); 01026 return rtp; 01027 }
| void ast_rtp_offered_from_local | ( | struct ast_rtp * | rtp, | |
| int | local | |||
| ) |
Definition at line 796 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::rtp_offered_from_local.
Referenced by transmit_connect_with_sdp(), transmit_invite(), transmit_modify_with_sdp(), transmit_reinvite_with_sdp(), and transmit_response_with_sdp().
00796 { 00797 if (rtp) 00798 rtp->rtp_offered_from_local = local; 00799 else 00800 ast_log(LOG_WARNING, "rtp structure is null\n"); 00801 }
| int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Definition at line 1505 of file rtp.c.
References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type.
Referenced by load_module(), and unload_module().
01506 { 01507 struct ast_rtp_protocol *cur; 01508 cur = protos; 01509 while(cur) { 01510 if (cur->type == proto->type) { 01511 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01512 return -1; 01513 } 01514 cur = cur->next; 01515 } 01516 proto->next = protos; 01517 protos = proto; 01518 return 0; 01519 }
| void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Definition at line 1485 of file rtp.c.
References ast_rtp_protocol::next.
Referenced by unload_module().
01486 { 01487 struct ast_rtp_protocol *cur, *prev; 01488 01489 cur = protos; 01490 prev = NULL; 01491 while(cur) { 01492 if (cur == proto) { 01493 if (prev) 01494 prev->next = proto->next; 01495 else 01496 protos = proto->next; 01497 return; 01498 } 01499 prev = cur; 01500 cur = cur->next; 01501 } 01502 }
| void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Definition at line 719 of file rtp.c.
References 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 process_sdp().
00720 { 00721 int i; 00722 if (!rtp) 00723 return; 00724 00725 for (i = 0; i < MAX_RTP_PT; ++i) { 00726 rtp->current_RTP_PT[i].isAstFormat = 0; 00727 rtp->current_RTP_PT[i].code = 0; 00728 } 00729 00730 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00731 rtp->rtp_lookup_code_cache_code = 0; 00732 rtp->rtp_lookup_code_cache_result = 0; 00733 }
| void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Definition at line 735 of file rtp.c.
References 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().
00736 { 00737 int i; 00738 00739 /* Initialize to default payload types */ 00740 for (i = 0; i < MAX_RTP_PT; ++i) { 00741 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 00742 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 00743 } 00744 00745 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00746 rtp->rtp_lookup_code_cache_code = 0; 00747 rtp->rtp_lookup_code_cache_result = 0; 00748 }
Definition at line 1256 of file rtp.c.
References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_rtp::lastdigitts, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_DEBUG, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), rtp_debug_test_addr(), ast_rtp::s, ast_frame::samples, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_write().
01257 { 01258 unsigned char *rtpheader; 01259 char iabuf[INET_ADDRSTRLEN]; 01260 int hdrlen = 12; 01261 int res; 01262 unsigned int ms; 01263 int pred; 01264 int mark = 0; 01265 01266 ms = calc_txstamp(rtp, &f->delivery); 01267 /* Default prediction */ 01268 if (f->subclass < AST_FORMAT_MAX_AUDIO) { 01269 pred = rtp->lastts + f->samples; 01270 01271 /* Re-calculate last TS */ 01272 rtp->lastts = rtp->lastts + ms * 8; 01273 if (ast_tvzero(f->delivery)) { 01274 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 01275 and if so, go with our prediction */ 01276 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 01277 rtp->lastts = pred; 01278 else { 01279 if (option_debug > 2) 01280 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 01281 mark = 1; 01282 } 01283 } 01284 } else { 01285 mark = f->subclass & 0x1; 01286 pred = rtp->lastovidtimestamp + f->samples; 01287 /* Re-calculate last TS */ 01288 rtp->lastts = rtp->lastts + ms * 90; 01289 /* If it's close to our prediction, go for it */ 01290 if (ast_tvzero(f->delivery)) { 01291 if (abs(rtp->lastts - pred) < 7200) { 01292 rtp->lastts = pred; 01293 rtp->lastovidtimestamp += f->samples; 01294 } else { 01295 if (option_debug > 2) 01296 ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples); 01297 rtp->lastovidtimestamp = rtp->lastts; 01298 } 01299 } 01300 } 01301 /* If the timestamp for non-digit packets has moved beyond the timestamp 01302 for digits, update the digit timestamp. 01303 */ 01304 if (rtp->lastts > rtp->lastdigitts) 01305 rtp->lastdigitts = rtp->lastts; 01306 01307 /* Get a pointer to the header */ 01308 rtpheader = (unsigned char *)(f->data - hdrlen); 01309 01310 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 01311 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 01312 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 01313 01314 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01315 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 01316 if (res <0) { 01317 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01318 ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 01319 } else if ((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) { 01320 /* Only give this error message once if we are not RTP debugging */ 01321 if (option_debug || rtpdebug) 01322 ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 01323 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 01324 } 01325 } 01326 01327 if(rtp_debug_test_addr(&rtp->them)) 01328 ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n" 01329 , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 01330 } 01331 01332 rtp->seqno++; 01333 01334 return 0; 01335 }
Definition at line 428 of file rtp.c.
References ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_lookup_pt(), ast_set_flag, ast_verbose(), calc_rxstamp(), rtpPayloadType::code, CRASH, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, 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::resp, rtp_debug_test_addr(), ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, send_dtmf(), ast_frame::src, ast_frame::subclass, and ast_rtp::them.
Referenced by mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().
00429 { 00430 int res; 00431 struct sockaddr_in sin; 00432 socklen_t len; 00433 unsigned int seqno; 00434 int version; 00435 int payloadtype; 00436 int hdrlen = 12; 00437 int padding; 00438 int mark; 00439 int ext; 00440 int cc; 00441 int x; 00442 char iabuf[INET_ADDRSTRLEN]; 00443 unsigned int ssrc; 00444 unsigned int timestamp; 00445 unsigned int *rtpheader; 00446 struct ast_frame *f; 00447 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00448 struct rtpPayloadType rtpPT; 00449 00450 len = sizeof(sin); 00451 00452 /* Cache where the header will go */ 00453 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 00454 0, (struct sockaddr *)&sin, &len); 00455 00456 00457 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 00458 if (res < 0) { 00459 if (errno == EBADF) 00460 CRASH; 00461 if (errno != EAGAIN) { 00462 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up now.\n", strerror(errno)); 00463 return NULL; 00464 } 00465 return &null_frame; 00466 } 00467 if (res < hdrlen) { 00468 ast_log(LOG_WARNING, "RTP Read too short\n"); 00469 return &null_frame; 00470 } 00471 00472 /* Ignore if the other side hasn't been given an address 00473 yet. */ 00474 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 00475 return &null_frame; 00476 00477 if (rtp->nat) { 00478 /* Send to whoever sent to us */ 00479 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00480 (rtp->them.sin_port != sin.sin_port)) { 00481 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 00482 rtp->rxseqno = 0; 00483 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 00484 if (option_debug || rtpdebug) 00485 ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 00486 } 00487 } 00488 00489 /* Get fields */ 00490 seqno = ntohl(rtpheader[0]); 00491 00492 /* Check RTP version */ 00493 version = (seqno & 0xC0000000) >> 30; 00494 if (version != 2) 00495 return &null_frame; 00496 00497 payloadtype = (seqno & 0x7f0000) >> 16; 00498 padding = seqno & (1 << 29); 00499 mark = seqno & (1 << 23); 00500 ext = seqno & (1 << 28); 00501 cc = (seqno & 0xF000000) >> 24; 00502 seqno &= 0xffff; 00503 timestamp = ntohl(rtpheader[1]); 00504 ssrc = ntohl(rtpheader[2]); 00505 00506 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 00507 if (option_debug || rtpdebug) 00508 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 00509 mark = 1; 00510 } 00511 00512 rtp->rxssrc = ssrc; 00513 00514 if (padding) { 00515 /* Remove padding bytes */ 00516 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 00517 } 00518 00519 if (cc) { 00520 /* CSRC fields present */ 00521 hdrlen += cc*4; 00522 } 00523 00524 if (ext) { 00525 /* RTP Extension present */ 00526 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 00527 hdrlen += 4; 00528 } 00529 00530 if (res < hdrlen) { 00531 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 00532 return &null_frame; 00533 } 00534 00535 if(rtp_debug_test_addr(&sin)) 00536 ast_verbose("Got RTP packet from %s:%u (type %d, seq %u, ts %u, len %d)\n" 00537 , ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 00538 00539 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 00540 if (!rtpPT.isAstFormat) { 00541 /* This is special in-band data that's not one of our codecs */ 00542 if (rtpPT.code == AST_RTP_DTMF) { 00543 /* It's special -- rfc2833 process it */ 00544 if(rtp_debug_test_addr(&sin)) { 00545 unsigned char *data; 00546 unsigned int event; 00547 unsigned int event_end; 00548 unsigned int duration; 00549 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 00550 event = ntohl(*((unsigned int *)(data))); 00551 event >>= 24; 00552 event_end = ntohl(*((unsigned int *)(data))); 00553 event_end <<= 8; 00554 event_end >>= 24; 00555 duration = ntohl(*((unsigned int *)(data))); 00556 duration &= 0xFFFF; 00557 ast_verbose("Got rfc2833 RTP packet from %s:%d (type %d, seq %d, ts %d, len %d, mark %d, event %08x, end %d, duration %d) \n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration); 00558 } 00559 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) { 00560 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno); 00561 rtp->lasteventseqn = seqno; 00562 } else 00563 f = NULL; 00564 if (f) 00565 return f; 00566 else 00567 return &null_frame; 00568 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 00569 /* It's really special -- process it the Cisco way */ 00570 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) { 00571 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00572 rtp->lasteventseqn = seqno; 00573 } else 00574 f = NULL; 00575 if (f) 00576 return f; 00577 else 00578 return &null_frame; 00579 } else if (rtpPT.code == AST_RTP_CN) { 00580 /* Comfort Noise */ 00581 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00582 if (f) 00583 return f; 00584 else 00585 return &null_frame; 00586 } else { 00587 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype); 00588 return &null_frame; 00589 } 00590 } 00591 rtp->f.subclass = rtpPT.code; 00592 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) 00593 rtp->f.frametype = AST_FRAME_VOICE; 00594 else 00595 rtp->f.frametype = AST_FRAME_VIDEO; 00596 rtp->lastrxformat = rtp->f.subclass; 00597 00598 if (!rtp->lastrxts) 00599 rtp->lastrxts = timestamp; 00600 00601 if (rtp->rxseqno) { 00602 for (x=rtp->rxseqno + 1; x < seqno; x++) { 00603 /* Queue empty frames */ 00604 rtp->f.mallocd = 0; 00605 rtp->f.datalen = 0; 00606 rtp->f.data = NULL; 00607 rtp->f.offset = 0; 00608 rtp->f.samples = 0; 00609 rtp->f.src = "RTPMissedFrame"; 00610 } 00611 } 00612 rtp->rxseqno = seqno; 00613 00614 if (rtp->dtmfcount) { 00615 #if 0 00616 printf("dtmfcount was %d\n", rtp->dtmfcount); 00617 #endif 00618 rtp->dtmfcount -= (timestamp - rtp->lastrxts); 00619 if (rtp->dtmfcount < 0) 00620 rtp->dtmfcount = 0; 00621 #if 0 00622 if (dtmftimeout != rtp->dtmfcount) 00623 printf("dtmfcount is %d\n", rtp->dtmfcount); 00624 #endif 00625 } 00626 rtp->lastrxts = timestamp; 00627 00628 /* Send any pending DTMF */ 00629 if (rtp->resp && !rtp->dtmfcount) { 00630 if (option_debug) 00631 ast_log(LOG_DEBUG, "Sending pending DTMF\n"); 00632 return send_dtmf(rtp); 00633 } 00634 rtp->f.mallocd = 0; 00635 rtp->f.datalen = res - hdrlen; 00636 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 00637 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 00638 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 00639 rtp->f.samples = ast_codec_get_samples(&rtp->f); 00640 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 00641 ast_frame_byteswap_be(&rtp->f); 00642 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 00643 } else { 00644 /* Video -- samples is # of samples vs. 90000 */ 00645 if (!rtp->lastividtimestamp) 00646 rtp->lastividtimestamp = timestamp; 00647 rtp->f.samples = timestamp - rtp->lastividtimestamp; 00648 rtp->lastividtimestamp = timestamp; 00649 rtp->f.delivery.tv_sec = 0; 00650 rtp->f.delivery.tv_usec = 0; 00651 if (mark) 00652 rtp->f.subclass |= 0x1; 00653 00654 } 00655 rtp->f.src = "RTP"; 00656 return &rtp->f; 00657 }
| void ast_rtp_reload | ( | void | ) |
Definition at line 1857 of file rtp.c.
References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), cfg, DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, s, and VERBOSE_PREFIX_2.
Referenced by ast_module_reload(), ast_rtp_init(), and main().
01858 { 01859 struct ast_config *cfg; 01860 char *s; 01861 01862 rtpstart = 5000; 01863 rtpend = 31000; 01864 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 01865 cfg = ast_config_load("rtp.conf"); 01866 if (cfg) { 01867 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01868 rtpstart = atoi(s); 01869 if (rtpstart < 1024) 01870 rtpstart = 1024; 01871 if (rtpstart > 65535) 01872 rtpstart = 65535; 01873 } 01874 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01875 rtpend = atoi(s); 01876 if (rtpend < 1024) 01877 rtpend = 1024; 01878 if (rtpend > 65535) 01879 rtpend = 65535; 01880 } 01881 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 01882 #ifdef SO_NO_CHECK 01883 if (ast_false(s)) 01884 nochecksums = 1; 01885 else 01886 nochecksums = 0; 01887 #else 01888 if (ast_false(s)) 01889 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 01890 #endif 01891 } 01892 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 01893 dtmftimeout = atoi(s); 01894 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 01895 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 01896 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 01897 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 01898 }; 01899 } 01900 ast_config_destroy(cfg); 01901 } 01902 if (rtpstart >= rtpend) { 01903 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 01904 rtpstart = 5000; 01905 rtpend = 31000; 01906 } 01907 if (option_verbose > 1) 01908 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01909 01910 }
| void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 1085 of file rtp.c.
References ast_rtp::dtmfcount, ast_rtp::dtmfduration, ast_rtp::dtmfmute, ast_rtp::lastdigitts, ast_rtp::lasteventendseqn, 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.
01086 { 01087 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 01088 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 01089 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 01090 rtp->lastts = 0; 01091 rtp->lastdigitts = 0; 01092 rtp->lastrxts = 0; 01093 rtp->lastividtimestamp = 0; 01094 rtp->lastovidtimestamp = 0; 01095 rtp->lasteventseqn = 0; 01096 rtp->lasteventendseqn = 0; 01097 rtp->lasttxformat = 0; 01098 rtp->lastrxformat = 0; 01099 rtp->dtmfcount = 0; 01100 rtp->dtmfduration = 0; 01101 rtp->seqno = 0; 01102 rtp->rxseqno = 0; 01103 }
| int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
| int | level | |||
| ) |
Definition at line 1221 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, 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().
01222 { 01223 unsigned int *rtpheader; 01224 int hdrlen = 12; 01225 int res; 01226 int payload; 01227 char data[256]; 01228 char iabuf[INET_ADDRSTRLEN]; 01229 level = 127 - (level & 0x7f); 01230 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 01231 01232 /* If we have no peer, return immediately */ 01233 if (!rtp->them.sin_addr.s_addr) 01234 return 0; 01235 01236 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 01237 01238 /* Get a pointer to the header */ 01239 rtpheader = (unsigned int *)data; 01240 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 01241 rtpheader[1] = htonl(rtp->lastts); 01242 rtpheader[2] = htonl(rtp->ssrc); 01243 data[12] = level; 01244 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01245 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 01246 if (res <0) 01247 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 01248 if(rtp_debug_test_addr(&rtp->them)) 01249 ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n" 01250 , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 01251 01252 } 01253 return 0; 01254 }
| int ast_rtp_senddigit | ( | struct ast_rtp * | rtp, | |
| char | digit | |||
| ) |
Definition at line 1139 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by oh323_digit(), and sip_senddigit().
01140 { 01141 unsigned int *rtpheader; 01142 int hdrlen = 12; 01143 int res; 01144 int x; 01145 int payload; 01146 char data[256]; 01147 char iabuf[INET_ADDRSTRLEN]; 01148 01149 if ((digit <= '9') && (digit >= '0')) 01150 digit -= '0'; 01151 else if (digit == '*') 01152 digit = 10; 01153 else if (digit == '#') 01154 digit = 11; 01155 else if ((digit >= 'A') && (digit <= 'D')) 01156 digit = digit - 'A' + 12; 01157 else if ((digit >= 'a') && (digit <= 'd')) 01158 digit = digit - 'a' + 12; 01159 else { 01160 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 01161 return -1; 01162 } 01163 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 01164 01165 /* If we have no peer, return immediately */ 01166 if (!rtp->them.sin_addr.s_addr) 01167 return 0; 01168 01169 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 01170 01171 /* Get a pointer to the header */ 01172 rtpheader = (unsigned int *)data; 01173 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 01174 rtpheader[1] = htonl(rtp->lastdigitts); 01175 rtpheader[2] = htonl(rtp->ssrc); 01176 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 01177 for (x = 0; x < 6; x++) { 01178 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01179 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 01180 if (res < 0) 01181 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 01182 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), 01183 ntohs(rtp->them.sin_port), strerror(errno)); 01184 if (rtp_debug_test_addr(&rtp->them)) 01185 ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n", 01186 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), 01187 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 01188 } 01189 /* Sequence number of last two end packets does not get incremented */ 01190 if (x < 3) 01191 rtp->seqno++; 01192 /* Clear marker bit and set seqno */ 01193 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 01194 /* For the last three packets, set the duration and the end bit */ 01195 if (x == 2) { 01196 #if 0 01197 /* No, this is wrong... Do not increment lastdigitts, that's not according 01198 to the RFC, as best we can determine */ 01199 rtp->lastdigitts++; /* or else the SPA3000 will click instead of beeping... */ 01200 rtpheader[1] = htonl(rtp->lastdigitts); 01201 #endif 01202 /* Make duration 800 (100ms) */ 01203 rtpheader[3] |= htonl((800)); 01204 /* Set the End bit */ 01205 rtpheader[3] |= htonl((1 << 23)); 01206 } 01207 } 01208 /* Increment the digit timestamp by 120ms, to ensure that digits 01209 sent sequentially with no intervening non-digit packets do not 01210 get sent with the same timestamp, and that sequential digits 01211 have some 'dead air' in between them 01212 */ 01213 rtp->lastdigitts += 960; 01214 /* Increment the sequence number to reflect the last packet 01215 that was sent 01216 */ 01217 rtp->seqno++; 01218 return 0; 01219 }
| void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
| ast_rtp_callback | callback | |||
| ) |
Definition at line 170 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00171 { 00172 rtp->callback = callback; 00173 }
| void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
| void * | data | |||
| ) |
Definition at line 165 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00166 { 00167 rtp->data = data; 00168 }
| void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
| int | pt | |||
| ) |
Definition at line 753 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, and MAX_RTP_PT.
Referenced by process_sdp().
00753 { 00754 if (pt < 0 || pt > MAX_RTP_PT) 00755 return; /* bogus payload type */ 00756 00757 if (static_RTP_PT[pt].code != 0) { 00758 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 00759 } 00760 }
| void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 1046 of file rtp.c.
References ast_rtp::rtcp, ast_rtp::rxseqno, ast_rtcp::them, and ast_rtp::them.
Referenced by handle_message(), process_sdp(), and setup_rtp_connection().
01047 { 01048 rtp->them.sin_port = them->sin_port; 01049 rtp->them.sin_addr = them->sin_addr; 01050 if (rtp->rtcp) { 01051 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 01052 rtp->rtcp->them.sin_addr = them->sin_addr; 01053 } 01054 rtp->rxseqno = 0; 01055 }
| void ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
| int | pt, | |||
| char * | mimeType, | |||
| char * | mimeSubtype | |||
| ) |
Definition at line 764 of file rtp.c.
References ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, subtype, and type.
Referenced by process_sdp(), and set_dtmf_payload().
00765 { 00766 int i; 00767 00768 if (pt < 0 || pt > MAX_RTP_PT) 00769 return; /* bogus payload type */ 00770 00771 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00772 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 00773 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 00774 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 00775 return; 00776 } 00777 } 00778 }
| void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
| int | nat | |||
| ) |
Definition at line 175 of file rtp.c.
References ast_rtp::nat.
Referenced by check_user_full(), create_addr(), create_addr_from_peer(), oh323_request(), oh323_rtp_read(), sip_alloc(), and start_rtp().
| int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
| int | tos | |||
| ) |
Definition at line 1037 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by oh323_alloc(), and sip_alloc().
01038 { 01039 int res; 01040 01041 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 01042 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 01043 return res; 01044 }
| void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 1075 of file rtp.c.
References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them.
Referenced by handle_request_bye(), handle_request_cancel(), handle_response(), and process_sdp().
01076 { 01077 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 01078 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 01079 if (rtp->rtcp) { 01080 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 01081 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 01082 } 01083 }
Definition at line 1337 of file rtp.c.
References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_H263_PLUS, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, 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_G729, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_frame::datalen, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
Referenced by mgcp_write(), oh323_write(), sip_write(), and skinny_write().
01338 { 01339 struct ast_frame *f; 01340 int codec; 01341 int hdrlen = 12; 01342 int subclass; 01343 01344 01345 /* If we have no peer, return immediately */ 01346 if (!rtp->them.sin_addr.s_addr) 01347 return 0; 01348 01349 /* If there is no data length, return immediately */ 01350 if (!_f->datalen) 01351 return 0; 01352 01353 /* Make sure we have enough space for RTP header */ 01354 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 01355 ast_log(LOG_WARNING, "RTP can only send voice\n"); 01356 return -1; 01357 } 01358 01359 subclass = _f->subclass; 01360 if (_f->frametype == AST_FRAME_VIDEO) 01361 subclass &= ~0x1; 01362 01363 codec = ast_rtp_lookup_code(rtp, 1, subclass); 01364 if (codec < 0) { 01365 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 01366 return -1; 01367 } 01368 01369 if (rtp->lasttxformat != subclass) { 01370 /* New format, reset the smoother */ 01371 if (option_debug) 01372 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01373 rtp->lasttxformat = subclass; 01374 if (rtp->smoother) 01375 ast_smoother_free(rtp->smoother); 01376 rtp->smoother = NULL; 01377 } 01378 01379 01380 switch(subclass) { 01381 case AST_FORMAT_SLINEAR: 01382 if (!rtp->smoother) { 01383 rtp->smoother = ast_smoother_new(320); 01384 } 01385 if (!rtp->smoother) { 01386 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01387 return -1; 01388 } 01389 ast_smoother_feed_be(rtp->smoother, _f); 01390 01391 while((f = ast_smoother_read(rtp->smoother))) 01392 ast_rtp_raw_write(rtp, f, codec); 01393 break; 01394 case AST_FORMAT_ULAW: 01395 case AST_FORMAT_ALAW: 01396 if (!rtp->smoother) { 01397 rtp->smoother = ast_smoother_new(160); 01398 } 01399 if (!rtp->smoother) { 01400 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01401 return -1; 01402 } 01403 ast_smoother_feed(rtp->smoother, _f); 01404 01405 while((f = ast_smoother_read(rtp->smoother))) 01406 ast_rtp_raw_write(rtp, f, codec); 01407 break; 01408 case AST_FORMAT_ADPCM: 01409 case AST_FORMAT_G726: 01410 if (!rtp->smoother) { 01411 rtp->smoother = ast_smoother_new(80); 01412 } 01413 if (!rtp->smoother) { 01414 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01415 return -1; 01416 } 01417 ast_smoother_feed(rtp->smoother, _f); 01418 01419 while((f = ast_smoother_read(rtp->smoother))) 01420 ast_rtp_raw_write(rtp, f, codec); 01421 break; 01422 case AST_FORMAT_G729A: 01423 if (!rtp->smoother) { 01424 rtp->smoother = ast_smoother_new(20); 01425 if (rtp->smoother) 01426 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729); 01427 } 01428 if (!rtp->smoother) { 01429 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n"); 01430 return -1; 01431 } 01432 ast_smoother_feed(rtp->smoother, _f); 01433 01434 while((f = ast_smoother_read(rtp->smoother))) 01435 ast_rtp_raw_write(rtp, f, codec); 01436 break; 01437 case AST_FORMAT_GSM: 01438 if (!rtp->smoother) { 01439 rtp->smoother = ast_smoother_new(33); 01440 } 01441 if (!rtp->smoother) { 01442 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n"); 01443 return -1; 01444 } 01445 ast_smoother_feed(rtp->smoother, _f); 01446 while((f = ast_smoother_read(rtp->smoother))) 01447 ast_rtp_raw_write(rtp, f, codec); 01448 break; 01449 case AST_FORMAT_ILBC: 01450 if (!rtp->smoother) { 01451 rtp->smoother = ast_smoother_new(50); 01452 } 01453 if (!rtp->smoother) { 01454 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n"); 01455 return -1; 01456 } 01457 ast_smoother_feed(rtp->smoother, _f); 01458 while((f = ast_smoother_read(rtp->smoother))) 01459 ast_rtp_raw_write(rtp, f, codec); 01460 break; 01461 default: 01462 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass)); 01463 /* fall through to... */ 01464 case AST_FORMAT_H261: 01465 case AST_FORMAT_H263: 01466 case AST_FORMAT_H263_PLUS: 01467 case AST_FORMAT_G723_1: 01468 case AST_FORMAT_LPC10: 01469 case AST_FORMAT_SPEEX: 01470 /* Don't buffer outgoing frames; send them one-per-packet: */ 01471 if (_f->offset < hdrlen) { 01472 f = ast_frdup(_f); 01473 } else { 01474 f = _f; 01475 } 01476 ast_rtp_raw_write(rtp, f, codec); 01477 if (f != _f) 01478 ast_frfree(f); 01479 } 01480 01481 return 0; 01482 }
| static void calc_rxstamp | ( | struct timeval * | tv, | |
| struct ast_rtp * | rtp, | |||
| unsigned int | timestamp, | |||
| int | mark | |||
| ) | [static] |
Definition at line 417 of file rtp.c.
References ast_tvadd(), ast_tvsub(), and ast_rtp::rxcore.
Referenced by ast_rtp_read(), and schedule_delivery().
00418 { 00419 struct timeval ts = ast_samp2tv( timestamp, 8000); 00420 if (ast_tvzero(rtp->rxcore) || mark) { 00421 rtp->rxcore = ast_tvsub(ast_tvnow(), ts); 00422 /* Round to 20ms for nice, pretty timestamps */ 00423 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 20000; 00424 } 00425 *tv = ast_tvadd(rtp->rxcore, ts); 00426 }
| static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
| struct timeval * | delivery | |||
| ) | [static] |
Definition at line 1120 of file rtp.c.
References ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
01121 { 01122 struct timeval t; 01123 long ms; 01124 if (ast_tvzero(rtp->txcore)) { 01125 rtp->txcore = ast_tvnow(); 01126 /* Round to 20ms for nice, pretty timestamps */ 01127 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 01128 } 01129 /* Use previous txcore if available */ 01130 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 01131 ms = ast_tvdiff_ms(t, rtp->txcore); 01132 if (ms < 0) 01133 ms = 0; 01134 /* Use what we just got for next time */ 01135 rtp->txcore = t; 01136 return (unsigned int) ms; 01137 }
| static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 1522 of file rtp.c.
References ast_rtp_protocol::next, ast_channel::type, and ast_rtp_protocol::type.
Referenced by ast_rtp_bridge().
01523 { 01524 struct ast_rtp_protocol *cur; 01525 01526 cur = protos; 01527 while(cur) { 01528 if (cur->type == chan->type) { 01529 return cur; 01530 } 01531 cur = cur->next; 01532 } 01533 return NULL; 01534 }
| static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
| unsigned char * | data, | |||
| int | len | |||
| ) | [static, read] |
Definition at line 224 of file rtp.c.
References ast_rtp::dtmfcount, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00225 { 00226 unsigned int event; 00227 char resp = 0; 00228 struct ast_frame *f = NULL; 00229 event = ntohl(*((unsigned int *)(data))); 00230 event &= 0x001F; 00231 #if 0 00232 printf("Cisco Digit: %08x (len = %d)\n", event, len); 00233 #endif 00234 if (event < 10) { 00235 resp = '0' + event; 00236 } else if (event < 11) { 00237 resp = '*'; 00238 } else if (event < 12) { 00239 resp = '#'; 00240 } else if (event < 16) { 00241 resp = 'A' + (event - 12); 00242 } else if (event < 17) { 00243 resp = 'X'; 00244 } 00245 if (rtp->resp && (rtp->resp != resp)) { 00246 f = send_dtmf(rtp); 00247 } 00248 rtp->resp = resp; 00249 rtp->dtmfcount = dtmftimeout; 00250 return f; 00251 }
| static struct ast_frame* process_rfc2833 | ( | struct ast_rtp * | rtp, | |
| unsigned char * | data, | |||
| int | len, | |||
| unsigned int | seqno | |||
| ) | [static, read] |
Process RTP DTMF and events according to RFC 2833.
RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
| rtp | ||
| data | ||
| len | ||
| seqno |
Definition at line 264 of file rtp.c.
References ast_log(), ast_rtp::dtmfcount, ast_rtp::dtmfduration, ast_rtp::lasteventendseqn, LOG_DEBUG, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00265 { 00266 unsigned int event; 00267 unsigned int event_end; 00268 unsigned int duration; 00269 char resp = 0; 00270 struct ast_frame *f = NULL; 00271 event = ntohl(*((unsigned int *)(data))); 00272 event >>= 24; 00273 event_end = ntohl(*((unsigned int *)(data))); 00274 event_end <<= 8; 00275 event_end >>= 24; 00276 duration = ntohl(*((unsigned int *)(data))); 00277 duration &= 0xFFFF; 00278 if (rtpdebug) 00279 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00280 if (event < 10) { 00281 resp = '0' + event; 00282 } else if (event < 11) { 00283 resp = '*'; 00284 } else if (event < 12) { 00285 resp = '#'; 00286 } else if (event < 16) { 00287 resp = 'A' + (event - 12); 00288 } else if (event < 17) { /* Event 16: Hook flash */ 00289 resp = 'X'; 00290 } 00291 if (rtp->resp && (rtp->resp != resp)) { 00292 f = send_dtmf(rtp); 00293 } else if(event_end & 0x80) { 00294 if (rtp->resp) { 00295 if(rtp->lasteventendseqn != seqno) { 00296 f = send_dtmf(rtp); 00297 rtp->lasteventendseqn = seqno; 00298 } 00299 rtp->resp = 0; 00300 } 00301 resp = 0; 00302 duration = 0; 00303 } else if (rtp->resp && rtp->dtmfduration && (duration < rtp->dtmfduration)) { 00304 f = send_dtmf(rtp); 00305 } 00306 if (!(event_end & 0x80)) 00307 rtp->resp = resp; 00308 rtp->dtmfcount = dtmftimeout; 00309 rtp->dtmfduration = duration; 00310 return f; 00311 }
| static struct ast_frame* process_rfc3389 | ( | struct ast_rtp * | rtp, | |
| unsigned char * | data, | |||
| int | len | |||
| ) | [static, read] |
Process Comfort Noise RTP.
This is incomplete at the moment.
Definition at line 319 of file rtp.c.
References AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, FLAG_3389_WARNING, ast_frame::frametype, ast_rtp::lastrxformat, LOG_DEBUG, LOG_NOTICE, ast_frame::offset, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read().
00320 { 00321 struct ast_frame *f = NULL; 00322 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00323 totally help us out becuase we don't have an engine to keep it going and we are not 00324 guaranteed to have it every 20ms or anything */ 00325 if (rtpdebug) 00326 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00327 00328 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00329 char iabuf[INET_ADDRSTRLEN]; 00330 00331 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00332 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr)); 00333 ast_set_flag(rtp, FLAG_3389_WARNING); 00334 } 00335 00336 /* Must have at least one byte */ 00337 if (!len) 00338 return NULL; 00339 if (len < 24) { 00340 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00341 rtp->f.datalen = len - 1; 00342 rtp->f.offset = AST_FRIENDLY_OFFSET; 00343 memcpy(rtp->f.data, data + 1, len - 1); 00344 } else { 00345 rtp->f.data = NULL; 00346 rtp->f.offset = 0; 00347 rtp->f.datalen = 0; 00348 } 00349 rtp->f.frametype = AST_FRAME_CNG; 00350 rtp->f.subclass = data[0] & 0x7f; 00351 rtp->f.datalen = len - 1; 00352 rtp->f.samples = 0; 00353 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00354 f = &rtp->f; 00355 return f; 00356 }
| static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 211 of file rtp.c.
References rtpdebugaddr.
Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), and ast_rtp_senddigit().
00212 { 00213 if (rtpdebug == 0) 00214 return 0; 00215 if (rtpdebugaddr.sin_addr.s_addr) { 00216 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00217 && (rtpdebugaddr.sin_port != addr->sin_port)) 00218 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00219 return 0; 00220 } 00221 return 1; 00222 }
| static int rtp_do_debug | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1818 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtp_do_debug_ip(), and rtpdebugaddr.
01819 { 01820 if(argc != 2) { 01821 if(argc != 4) 01822 return RESULT_SHOWUSAGE; 01823 return rtp_do_debug_ip(fd, argc, argv); 01824 } 01825 rtpdebug = 1; 01826 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 01827 ast_cli(fd, "RTP Debugging Enabled\n"); 01828 return RESULT_SUCCESS; 01829 }
| static int rtp_do_debug_ip | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1787 of file rtp.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtpdebugaddr.
Referenced by rtp_do_debug().
01788 { 01789 struct hostent *hp; 01790 struct ast_hostent ahp; 01791 char iabuf[INET_ADDRSTRLEN]; 01792 int port = 0; 01793 char *p, *arg; 01794 01795 if (argc != 4) 01796 return RESULT_SHOWUSAGE; 01797 arg = argv[3]; 01798 p = strstr(arg, ":"); 01799 if (p) { 01800 *p = '\0'; 01801 p++; 01802 port = atoi(p); 01803 } 01804 hp = ast_gethostbyname(arg, &ahp); 01805 if (hp == NULL) 01806 return RESULT_SHOWUSAGE; 01807 rtpdebugaddr.sin_family = AF_INET; 01808 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 01809 rtpdebugaddr.sin_port = htons(port); 01810 if (port == 0) 01811 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr)); 01812 else 01813 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr), port); 01814 rtpdebug = 1; 01815 return RESULT_SUCCESS; 01816 }
| static int rtp_no_debug | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1831 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01832 { 01833 if(argc !=3) 01834 return RESULT_SHOWUSAGE; 01835 rtpdebug = 0; 01836 ast_cli(fd,"RTP Debugging Disabled\n"); 01837 return RESULT_SUCCESS; 01838 }
| static int rtp_socket | ( | void | ) | [static] |
Definition at line 902 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
00903 { 00904 int s; 00905 long flags; 00906 s = socket(AF_INET, SOCK_DGRAM, 0); 00907 if (s > -1) { 00908 flags = fcntl(s, F_GETFL); 00909 fcntl(s, F_SETFL, flags | O_NONBLOCK); 00910 #ifdef SO_NO_CHECK 00911 if (nochecksums) 00912 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00913 #endif 00914 } 00915 return s; 00916 }
| static int rtpread | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 358 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and ast_rtp::data.
Referenced by ast_rtp_new_with_bindaddr().
00359 { 00360 struct ast_rtp *rtp = cbdata; 00361 struct ast_frame *f; 00362 f = ast_rtp_read(rtp); 00363 if (f) { 00364 if (rtp->callback) 00365 rtp->callback(rtp, f, rtp->data); 00366 } 00367 return 1; 00368 }
Definition at line 180 of file rtp.c.
References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), ast_frame::datalen, ast_rtp::dtmfduration, ast_rtp::dtmfmute, ast_rtp::f, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, option_debug, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read(), process_cisco_dtmf(), and process_rfc2833().
00181 { 00182 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00183 char iabuf[INET_ADDRSTRLEN]; 00184 00185 if (ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00186 if (option_debug) 00187 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr)); 00188 rtp->resp = 0; 00189 rtp->dtmfduration = 0; 00190 return &null_frame; 00191 } 00192 if (option_debug) 00193 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr)); 00194 if (rtp->resp == 'X') { 00195 rtp->f.frametype = AST_FRAME_CONTROL; 00196 rtp->f.subclass = AST_CONTROL_FLASH; 00197 } else { 00198 rtp->f.frametype = AST_FRAME_DTMF; 00199 rtp->f.subclass = rtp->resp; 00200 } 00201 rtp->f.datalen = 0; 00202 rtp->f.samples = 0; 00203 rtp->f.mallocd = 0; 00204 rtp->f.src = "RTP"; 00205 rtp->resp = 0; 00206 rtp->dtmfduration = 0; 00207 return &rtp->f; 00208 00209 }
struct ast_cli_entry cli_debug [static] |
Initial value:
{{ "rtp", "debug", NULL } , rtp_do_debug, "Enable RTP debugging", debug_usage }
struct ast_cli_entry cli_debug_ip [static] |
Initial value:
{{ "rtp", "debug", "ip", NULL } , rtp_do_debug, "Enable RTP debugging on IP", debug_usage }
struct ast_cli_entry cli_no_debug [static] |
Initial value:
{{ "rtp", "no", "debug", NULL } , rtp_no_debug, "Disable RTP debugging", no_debug_usage }
char debug_usage[] [static] |
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
struct { ... } mimeTypes[] [static] |
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
char no_debug_usage[] [static] |
| struct rtpPayloadType payloadType |
struct ast_rtp_protocol* protos = NULL [static] |
struct sockaddr_in rtpdebugaddr [static] |
Definition at line 68 of file rtp.c.
Referenced by rtp_debug_test_addr(), rtp_do_debug(), and rtp_do_debug_ip().
struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static] |
| char* subtype |
| char* type |
Definition at line 663 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_filename(), check_header(), do_chanreads(), find_subscription_type(), load_module(), misdn_cfg_get(), misdn_cfg_get_config_string(), schedule_delivery(), subscription_type2str(), vpb_new(), and yyparse().
1.5.6