#include "asterisk/frame.h"
#include "asterisk/io.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include <netinet/in.h>
Include dependency graph for rtp.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
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 |
Typedefs | |
| typedef int(* | ast_rtp_callback )(struct ast_rtp *rtp, struct ast_frame *f, void *data) |
Functions | |
| int | ast_rtcp_fd (struct ast_rtp *rtp) |
| ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
| int | 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) |
| void | 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, int isAstFormat, int code) |
| char * | ast_rtp_lookup_mime_multiple (char *buf, int size, const int capability, const int isAstFormat) |
| char * | ast_rtp_lookup_mime_subtype (int isAstFormat, int code) |
| rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
| ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
| Initializate a RTP session. | |
| 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. | |
| 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) |
| 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) |
RTP is defined in RFC 3550.
Definition in file rtp.h.
|
|
DTMF (Cisco Proprietary) Definition at line 46 of file rtp.h. Referenced by ast_rtp_read(). |
|
|
'Comfort Noise' (RFC3389) Definition at line 44 of file rtp.h. Referenced by ast_rtp_read(), and ast_rtp_sendcng(). |
|
|
DTMF (RFC2833) Definition at line 42 of file rtp.h. Referenced by add_noncodec_to_sdp(), add_sdp(), ast_rtp_read(), ast_rtp_senddigit(), check_user_full(), create_addr(), create_addr_from_peer(), oh323_alloc(), oh323_request(), process_sdp(), and sip_alloc(). |
|
|
Maximum RTP-specific code Definition at line 48 of file rtp.h. Referenced by add_sdp(), and ast_rtp_lookup_mime_multiple(). |
|
|
|
|
|
Definition at line 158 of file rtp.c. References ast_rtp::rtcp, and ast_rtcp::s. Referenced by sip_new().
|
|
|
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, rtpdebug, 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 != EAGAIN)
00390 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00391 if (errno == EBADF)
00392 CRASH;
00393 return &null_frame;
00394 }
00395
00396 if (res < hdrlen) {
00397 ast_log(LOG_WARNING, "RTP Read too short\n");
00398 return &null_frame;
00399 }
00400
00401 if (rtp->nat) {
00402 /* Send to whoever sent to us */
00403 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00404 (rtp->rtcp->them.sin_port != sin.sin_port)) {
00405 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00406 if (option_debug || rtpdebug)
00407 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));
00408 }
00409 }
00410 if (option_debug)
00411 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00412 return &null_frame;
00413 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 1518 of file rtp.c. References 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::name, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt. 01519 {
01520 struct ast_frame *f;
01521 struct ast_channel *who, *cs[3];
01522 struct ast_rtp *p0, *p1; /* Audio RTP Channels */
01523 struct ast_rtp *vp0, *vp1; /* Video RTP channels */
01524 struct ast_rtp_protocol *pr0, *pr1;
01525 struct sockaddr_in ac0, ac1;
01526 struct sockaddr_in vac0, vac1;
01527 struct sockaddr_in t0, t1;
01528 struct sockaddr_in vt0, vt1;
01529 char iabuf[INET_ADDRSTRLEN];
01530
01531 void *pvt0, *pvt1;
01532 int codec0,codec1, oldcodec0, oldcodec1;
01533
01534 memset(&vt0, 0, sizeof(vt0));
01535 memset(&vt1, 0, sizeof(vt1));
01536 memset(&vac0, 0, sizeof(vac0));
01537 memset(&vac1, 0, sizeof(vac1));
01538
01539 /* if need DTMF, cant native bridge */
01540 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
01541 return AST_BRIDGE_FAILED_NOWARN;
01542
01543 /* Lock channels */
01544 ast_mutex_lock(&c0->lock);
01545 while(ast_mutex_trylock(&c1->lock)) {
01546 ast_mutex_unlock(&c0->lock);
01547 usleep(1);
01548 ast_mutex_lock(&c0->lock);
01549 }
01550
01551 /* Find channel driver interfaces */
01552 pr0 = get_proto(c0);
01553 pr1 = get_proto(c1);
01554 if (!pr0) {
01555 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
01556 ast_mutex_unlock(&c0->lock);
01557 ast_mutex_unlock(&c1->lock);
01558 return AST_BRIDGE_FAILED;
01559 }
01560 if (!pr1) {
01561 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
01562 ast_mutex_unlock(&c0->lock);
01563 ast_mutex_unlock(&c1->lock);
01564 return AST_BRIDGE_FAILED;
01565 }
01566
01567 /* Get channel specific interface structures */
01568 pvt0 = c0->tech_pvt;
01569 pvt1 = c1->tech_pvt;
01570
01571 /* Get audio and video interface (if native bridge is possible) */
01572 p0 = pr0->get_rtp_info(c0);
01573 if (pr0->get_vrtp_info)
01574 vp0 = pr0->get_vrtp_info(c0);
01575 else
01576 vp0 = NULL;
01577 p1 = pr1->get_rtp_info(c1);
01578 if (pr1->get_vrtp_info)
01579 vp1 = pr1->get_vrtp_info(c1);
01580 else
01581 vp1 = NULL;
01582
01583 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01584 if (!p0 || !p1) {
01585 /* Somebody doesn't want to play... */
01586 ast_mutex_unlock(&c0->lock);
01587 ast_mutex_unlock(&c1->lock);
01588 return AST_BRIDGE_FAILED_NOWARN;
01589 }
01590 /* Get codecs from both sides */
01591 if (pr0->get_codec)
01592 codec0 = pr0->get_codec(c0);
01593 else
01594 codec0 = 0;
01595 if (pr1->get_codec)
01596 codec1 = pr1->get_codec(c1);
01597 else
01598 codec1 = 0;
01599 if (pr0->get_codec && pr1->get_codec) {
01600 /* Hey, we can't do reinvite if both parties speak different codecs */
01601 if (!(codec0 & codec1)) {
01602 if (option_debug)
01603 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
01604 ast_mutex_unlock(&c0->lock);
01605 ast_mutex_unlock(&c1->lock);
01606 return AST_BRIDGE_FAILED_NOWARN;
01607 }
01608 }
01609
01610 /* Ok, we should be able to redirect the media. Start with one channel */
01611 if (pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
01612 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
01613 else {
01614 /* Store RTP peer */
01615 ast_rtp_get_peer(p1, &ac1);
01616 if (vp1)
01617 ast_rtp_get_peer(vp1, &vac1);
01618 }
01619 /* Then test the other channel */
01620 if (pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
01621 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
01622 else {
01623 /* Store RTP peer */
01624 ast_rtp_get_peer(p0, &ac0);
01625 if (vp0)
01626 ast_rtp_get_peer(vp0, &vac0);
01627 }
01628 ast_mutex_unlock(&c0->lock);
01629 ast_mutex_unlock(&c1->lock);
01630 /* External RTP Bridge up, now loop and see if something happes that force us to take the
01631 media back to Asterisk */
01632 cs[0] = c0;
01633 cs[1] = c1;
01634 cs[2] = NULL;
01635 oldcodec0 = codec0;
01636 oldcodec1 = codec1;
01637 for (;;) {
01638 /* Check if something changed... */
01639 if ((c0->tech_pvt != pvt0) ||
01640 (c1->tech_pvt != pvt1) ||
01641 (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
01642 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
01643 if (c0->tech_pvt == pvt0) {
01644 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
01645 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
01646 }
01647 if (c1->tech_pvt == pvt1) {
01648 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
01649 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
01650 }
01651 return AST_BRIDGE_RETRY;
01652 }
01653 /* Now check if they have changed address */
01654 ast_rtp_get_peer(p1, &t1);
01655 ast_rtp_get_peer(p0, &t0);
01656 if (pr0->get_codec)
01657 codec0 = pr0->get_codec(c0);
01658 if (pr1->get_codec)
01659 codec1 = pr1->get_codec(c1);
01660 if (vp1)
01661 ast_rtp_get_peer(vp1, &vt1);
01662 if (vp0)
01663 ast_rtp_get_peer(vp0, &vt0);
01664 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) {
01665 if (option_debug > 1) {
01666 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
01667 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1);
01668 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
01669 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1);
01670 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01671 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
01672 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01673 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
01674 }
01675 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)))
01676 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
01677 memcpy(&ac1, &t1, sizeof(ac1));
01678 memcpy(&vac1, &vt1, sizeof(vac1));
01679 oldcodec1 = codec1;
01680 }
01681 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) {
01682 if (option_debug) {
01683 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
01684 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0);
01685 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01686 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
01687 }
01688 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)))
01689 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
01690 memcpy(&ac0, &t0, sizeof(ac0));
01691 memcpy(&vac0, &vt0, sizeof(vac0));
01692 oldcodec0 = codec0;
01693 }
01694 who = ast_waitfor_n(cs, 2, &timeoutms);
01695 if (!who) {
01696 if (!timeoutms)
01697 return AST_BRIDGE_RETRY;
01698 if (option_debug)
01699 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
01700 /* check for hangup / whentohangup */
01701 if (ast_check_hangup(c0) || ast_check_hangup(c1))
01702 break;
01703 continue;
01704 }
01705 f = ast_read(who);
01706 if (!f || ((f->frametype == AST_FRAME_DTMF) &&
01707 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
01708 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
01709 *fo = f;
01710 *rc = who;
01711 if (option_debug)
01712 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
01713 if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) {
01714 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
01715 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
01716 }
01717 if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) {
01718 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
01719 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
01720 }
01721 return AST_BRIDGE_COMPLETE;
01722 } else if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
01723 if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD) ||
01724 (f->subclass == AST_CONTROL_VIDUPDATE)) {
01725 ast_indicate(who == c0 ? c1 : c0, f->subclass);
01726 ast_frfree(f);
01727 } else {
01728 *fo = f;
01729 *rc = who;
01730 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
01731 return AST_BRIDGE_COMPLETE;
01732 }
01733 } else {
01734 if ((f->frametype == AST_FRAME_DTMF) ||
01735 (f->frametype == AST_FRAME_VOICE) ||
01736 (f->frametype == AST_FRAME_VIDEO)) {
01737 /* Forward voice or DTMF frames if they happen upon us */
01738 if (who == c0) {
01739 ast_write(c1, f);
01740 } else if (who == c1) {
01741 ast_write(c0, f);
01742 }
01743 }
01744 ast_frfree(f);
01745 }
01746 /* Swap priority not that it's a big deal at this point */
01747 cs[2] = cs[0];
01748 cs[0] = cs[1];
01749 cs[1] = cs[2];
01750
01751 }
01752 return AST_BRIDGE_FAILED;
01753 }
|
|
|
Definition at line 1086 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(). 01087 {
01088 if (rtp->smoother)
01089 ast_smoother_free(rtp->smoother);
01090 if (rtp->ioid)
01091 ast_io_remove(rtp->io, rtp->ioid);
01092 if (rtp->s > -1)
01093 close(rtp->s);
01094 if (rtp->rtcp) {
01095 close(rtp->rtcp->s);
01096 free(rtp->rtcp);
01097 }
01098 free(rtp);
01099 }
|
|
|
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 }
|
|
||||||||||||||||
|
Definition at line 771 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, and rtpPayloadType::isAstFormat. Referenced by process_sdp(). 00772 {
00773 int pt;
00774
00775 *astFormats = *nonAstFormats = 0;
00776 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00777 if (rtp->current_RTP_PT[pt].isAstFormat) {
00778 *astFormats |= rtp->current_RTP_PT[pt].code;
00779 } else {
00780 *nonAstFormats |= rtp->current_RTP_PT[pt].code;
00781 }
00782 }
00783 }
|
|
||||||||||||
|
Definition at line 1044 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(). 01045 {
01046 them->sin_family = AF_INET;
01047 them->sin_port = rtp->them.sin_port;
01048 them->sin_addr = rtp->them.sin_addr;
01049 }
|
|
||||||||||||
|
Definition at line 1051 of file rtp.c. References ast_rtp::us. Referenced by add_sdp(), external_rtp_create(), handle_message(), and oh323_set_rtp_peer().
|
|
|
Definition at line 1881 of file rtp.c. References ast_cli_register(), and ast_rtp_reload(). Referenced by main(). 01882 {
01883 ast_cli_register(&cli_debug);
01884 ast_cli_register(&cli_debug_ip);
01885 ast_cli_register(&cli_no_debug);
01886 ast_rtp_reload();
01887 }
|
|
||||||||||||||||
|
Definition at line 811 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, 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(). 00811 {
00812
00813 int pt;
00814
00815 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
00816 code == rtp->rtp_lookup_code_cache_code) {
00817
00818 /* Use our cached mapping, to avoid the overhead of the loop below */
00819 return rtp->rtp_lookup_code_cache_result;
00820 }
00821
00822 /* Check the dynamic list first */
00823 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00824 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
00825 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00826 rtp->rtp_lookup_code_cache_code = code;
00827 rtp->rtp_lookup_code_cache_result = pt;
00828 return pt;
00829 }
00830 }
00831
00832 /* Then the static list */
00833 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00834 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
00835 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00836 rtp->rtp_lookup_code_cache_code = code;
00837 rtp->rtp_lookup_code_cache_result = pt;
00838 return pt;
00839 }
00840 }
00841 return -1;
00842 }
|
|
||||||||||||||||||||
|
Definition at line 856 of file rtp.c. References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, and name. Referenced by process_sdp(). 00857 {
00858 int format;
00859 unsigned len;
00860 char *end = buf;
00861 char *start = buf;
00862
00863 if (!buf || !size)
00864 return NULL;
00865
00866 snprintf(end, size, "0x%x (", capability);
00867
00868 len = strlen(end);
00869 end += len;
00870 size -= len;
00871 start = end;
00872
00873 for (format = 1; format < AST_RTP_MAX; format <<= 1) {
00874 if (capability & format) {
00875 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format);
00876 snprintf(end, size, "%s|", name);
00877 len = strlen(end);
00878 end += len;
00879 size -= len;
00880 }
00881 }
00882
00883 if (start == end)
00884 snprintf(start, size, "nothing)");
00885 else if (size > 1)
00886 *(end -1) = ')';
00887
00888 return buf;
00889 }
|
|
||||||||||||
|
Definition at line 844 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(). 00844 {
00845
00846 int i;
00847
00848 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00849 if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
00850 return mimeTypes[i].subtype;
00851 }
00852 }
00853 return "";
00854 }
|
|
||||||||||||
|
Definition at line 792 of file rtp.c. References rtpPayloadType::code, and rtpPayloadType::isAstFormat. Referenced by ast_rtp_read(), and setup_rtp_connection(). 00793 {
00794 struct rtpPayloadType result;
00795
00796 result.isAstFormat = result.code = 0;
00797 if (pt < 0 || pt > MAX_RTP_PT)
00798 return result; /* bogus payload type */
00799
00800 /* Start with the negotiated codecs */
00801 if (!rtp->rtp_offered_from_local)
00802 result = rtp->current_RTP_PT[pt];
00803
00804 /* If it doesn't exist, check our static RTP type list, just in case */
00805 if (!result.code)
00806 result = static_RTP_PT[pt];
00807 return result;
00808 }
|
|
||||||||||||||||||||
|
Initializate a RTP session.
Definition at line 1016 of file rtp.c. References ast_rtp_new_with_bindaddr(). Referenced by start_rtp(). 01017 {
01018 struct in_addr ia;
01019
01020 memset(&ia, 0, sizeof(ia));
01021 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01022 }
|
|
||||||||||||||||||||||||
|
Initializate a RTP session using an in_addr structure. This fuction gets called by ast_rtp_new().
Definition at line 929 of file rtp.c. References ast_io_add(), AST_IO_IN, ast_log(), ast_rtcp_new(), ast_rtp_pt_default(), free, LOG_ERROR, malloc, rtp_socket(), rtpend, rtpread(), and rtpstart. Referenced by ast_rtp_new(), oh323_alloc(), sip_alloc(), and start_rtp(). 00930 {
00931 struct ast_rtp *rtp;
00932 int x;
00933 int first;
00934 int startplace;
00935 rtp = malloc(sizeof(struct ast_rtp));
00936 if (!rtp)
00937 return NULL;
00938 memset(rtp, 0, sizeof(struct ast_rtp));
00939 rtp->them.sin_family = AF_INET;
00940 rtp->us.sin_family = AF_INET;
00941 rtp->s = rtp_socket();
00942 rtp->ssrc = rand();
00943 rtp->seqno = rand() & 0xffff;
00944 if (rtp->s < 0) {
00945 free(rtp);
00946 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
00947 return NULL;
00948 }
00949 if (sched && rtcpenable) {
00950 rtp->sched = sched;
00951 rtp->rtcp = ast_rtcp_new();
00952 }
00953
00954 /* Select a random port number in the range of possible RTP */
00955 x = (rand() % (rtpend-rtpstart)) + rtpstart;
00956 x = x & ~1;
00957 /* Save it for future references. */
00958 startplace = x;
00959 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
00960 for (;;) {
00961 /* Must be an even port number by RTP spec */
00962 rtp->us.sin_port = htons(x);
00963 rtp->us.sin_addr = addr;
00964 /* If there's rtcp, initialize it as well. */
00965 if (rtp->rtcp)
00966 rtp->rtcp->us.sin_port = htons(x + 1);
00967 /* Try to bind it/them. */
00968 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
00969 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
00970 break;
00971 if (!first) {
00972 /* Primary bind succeeded! Gotta recreate it */
00973 close(rtp->s);
00974 rtp->s = rtp_socket();
00975 }
00976 if (errno != EADDRINUSE) {
00977 /* We got an error that wasn't expected, abort! */
00978 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
00979 close(rtp->s);
00980 if (rtp->rtcp) {
00981 close(rtp->rtcp->s);
00982 free(rtp->rtcp);
00983 }
00984 free(rtp);
00985 return NULL;
00986 }
00987 /* The port was used, increment it (by two). */
00988 x += 2;
00989 /* Did we go over the limit ? */
00990 if (x > rtpend)
00991 /* then, start from the begingig. */
00992 x = (rtpstart + 1) & ~1;
00993 /* Check if we reached the place were we started. */
00994 if (x == startplace) {
00995 /* If so, there's no ports available. */
00996 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
00997 close(rtp->s);
00998 if (rtp->rtcp) {
00999 close(rtp->rtcp->s);
01000 free(rtp->rtcp);
01001 }
01002 free(rtp);
01003 return NULL;
01004 }
01005 }
01006 if (io && sched && callbackmode) {
01007 /* Operate this one in a callback mode */
01008 rtp->sched = sched;
01009 rtp->io = io;
01010 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
01011 }
01012 ast_rtp_pt_default(rtp);
01013 return rtp;
01014 }
|
|
||||||||||||
|
Definition at line 785 of file rtp.c. References ast_log(), and LOG_WARNING. Referenced by transmit_connect_with_sdp(), transmit_invite(), transmit_modify_with_sdp(), transmit_reinvite_with_sdp(), and transmit_response_with_sdp(). 00785 {
00786 if (rtp)
00787 rtp->rtp_offered_from_local = local;
00788 else
00789 ast_log(LOG_WARNING, "rtp structure is null\n");
00790 }
|
|
|
Definition at line 1484 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(). 01485 {
01486 struct ast_rtp_protocol *cur;
01487 cur = protos;
01488 while(cur) {
01489 if (cur->type == proto->type) {
01490 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01491 return -1;
01492 }
01493 cur = cur->next;
01494 }
01495 proto->next = protos;
01496 protos = proto;
01497 return 0;
01498 }
|
|
|
Definition at line 1464 of file rtp.c. References ast_rtp_protocol::next. Referenced by unload_module(). 01465 {
01466 struct ast_rtp_protocol *cur, *prev;
01467
01468 cur = protos;
01469 prev = NULL;
01470 while(cur) {
01471 if (cur == proto) {
01472 if (prev)
01473 prev->next = proto->next;
01474 else
01475 protos = proto->next;
01476 return;
01477 }
01478 prev = cur;
01479 cur = cur->next;
01480 }
01481 }
|
|
|
Definition at line 708 of file rtp.c. Referenced by process_sdp(). 00709 {
00710 int i;
00711 if (!rtp)
00712 return;
00713
00714 for (i = 0; i < MAX_RTP_PT; ++i) {
00715 rtp->current_RTP_PT[i].isAstFormat = 0;
00716 rtp->current_RTP_PT[i].code = 0;
00717 }
00718
00719 rtp->rtp_lookup_code_cache_isAstFormat = 0;
00720 rtp->rtp_lookup_code_cache_code = 0;
00721 rtp->rtp_lookup_code_cache_result = 0;
00722 }
|
|
|
Definition at line 724 of file rtp.c. References rtpPayloadType::code, and rtpPayloadType::isAstFormat. Referenced by ast_rtp_new_with_bindaddr(). 00725 {
00726 int i;
00727
00728 /* Initialize to default payload types */
00729 for (i = 0; i < MAX_RTP_PT; ++i) {
00730 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
00731 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
00732 }
00733
00734 rtp->rtp_lookup_code_cache_isAstFormat = 0;
00735 rtp->rtp_lookup_code_cache_code = 0;
00736 rtp->rtp_lookup_code_cache_result = 0;
00737 }
|
|
|
Definition at line 426 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, dtmftimeout, 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(), rtpdebug, 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(). 00427 {
00428 int res;
00429 struct sockaddr_in sin;
00430 socklen_t len;
00431 unsigned int seqno;
00432 int version;
00433 int payloadtype;
00434 int hdrlen = 12;
00435 int padding;
00436 int mark;
00437 int ext;
00438 int x;
00439 char iabuf[INET_ADDRSTRLEN];
00440 unsigned int ssrc;
00441 unsigned int timestamp;
00442 unsigned int *rtpheader;
00443 struct ast_frame *f;
00444 static struct ast_frame null_frame = { AST_FRAME_NULL, };
00445 struct rtpPayloadType rtpPT;
00446
00447 len = sizeof(sin);
00448
00449 /* Cache where the header will go */
00450 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
00451 0, (struct sockaddr *)&sin, &len);
00452
00453
00454 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
00455 if (res < 0) {
00456 if (errno != EAGAIN)
00457 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00458 if (errno == EBADF)
00459 CRASH;
00460 return &null_frame;
00461 }
00462 if (res < hdrlen) {
00463 ast_log(LOG_WARNING, "RTP Read too short\n");
00464 return &null_frame;
00465 }
00466
00467 /* Ignore if the other side hasn't been given an address
00468 yet. */
00469 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
00470 return &null_frame;
00471
00472 if (rtp->nat) {
00473 /* Send to whoever sent to us */
00474 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00475 (rtp->them.sin_port != sin.sin_port)) {
00476 memcpy(&rtp->them, &sin, sizeof(rtp->them));
00477 rtp->rxseqno = 0;
00478 ast_set_flag(rtp, FLAG_NAT_ACTIVE);
00479 if (option_debug || rtpdebug)
00480 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));
00481 }
00482 }
00483
00484 /* Get fields */
00485 seqno = ntohl(rtpheader[0]);
00486
00487 /* Check RTP version */
00488 version = (seqno & 0xC0000000) >> 30;
00489 if (version != 2)
00490 return &null_frame;
00491
00492 payloadtype = (seqno & 0x7f0000) >> 16;
00493 padding = seqno & (1 << 29);
00494 mark = seqno & (1 << 23);
00495 ext = seqno & (1 << 28);
00496 seqno &= 0xffff;
00497 timestamp = ntohl(rtpheader[1]);
00498 ssrc = ntohl(rtpheader[2]);
00499
00500 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
00501 if (option_debug || rtpdebug)
00502 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n");
00503 mark = 1;
00504 }
00505
00506 rtp->rxssrc = ssrc;
00507
00508 if (padding) {
00509 /* Remove padding bytes */
00510 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
00511 }
00512
00513 if (ext) {
00514 /* RTP Extension present */
00515 hdrlen += 4;
00516 hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2;
00517 }
00518
00519 if (res < hdrlen) {
00520 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
00521 return &null_frame;
00522 }
00523
00524 if(rtp_debug_test_addr(&sin))
00525 ast_verbose("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len %d)\n"
00526 , ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
00527
00528 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
00529 if (!rtpPT.isAstFormat) {
00530 /* This is special in-band data that's not one of our codecs */
00531 if (rtpPT.code == AST_RTP_DTMF) {
00532 /* It's special -- rfc2833 process it */
00533 if(rtp_debug_test_addr(&sin)) {
00534 unsigned char *data;
00535 unsigned int event;
00536 unsigned int event_end;
00537 unsigned int duration;
00538 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
00539 event = ntohl(*((unsigned int *)(data)));
00540 event >>= 24;
00541 event_end = ntohl(*((unsigned int *)(data)));
00542 event_end <<= 8;
00543 event_end >>= 24;
00544 duration = ntohl(*((unsigned int *)(data)));
00545 duration &= 0xFFFF;
00546 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);
00547 }
00548 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
00549 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno);
00550 rtp->lasteventseqn = seqno;
00551 } else
00552 f = NULL;
00553 if (f)
00554 return f;
00555 else
00556 return &null_frame;
00557 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
00558 /* It's really special -- process it the Cisco way */
00559 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
00560 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
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_CN) {
00569 /* Comfort Noise */
00570 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00571 if (f)
00572 return f;
00573 else
00574 return &null_frame;
00575 } else {
00576 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
00577 return &null_frame;
00578 }
00579 }
00580 rtp->f.subclass = rtpPT.code;
00581 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO)
00582 rtp->f.frametype = AST_FRAME_VOICE;
00583 else
00584 rtp->f.frametype = AST_FRAME_VIDEO;
00585 rtp->lastrxformat = rtp->f.subclass;
00586
00587 if (!rtp->lastrxts)
00588 rtp->lastrxts = timestamp;
00589
00590 if (rtp->rxseqno) {
00591 for (x=rtp->rxseqno + 1; x < seqno; x++) {
00592 /* Queue empty frames */
00593 rtp->f.mallocd = 0;
00594 rtp->f.datalen = 0;
00595 rtp->f.data = NULL;
00596 rtp->f.offset = 0;
00597 rtp->f.samples = 0;
00598 rtp->f.src = "RTPMissedFrame";
00599 }
00600 }
00601 rtp->rxseqno = seqno;
00602
00603 if (rtp->dtmfcount) {
00604 #if 0
00605 printf("dtmfcount was %d\n", rtp->dtmfcount);
00606 #endif
00607 rtp->dtmfcount -= (timestamp - rtp->lastrxts);
00608 if (rtp->dtmfcount < 0)
00609 rtp->dtmfcount = 0;
00610 #if 0
00611 if (dtmftimeout != rtp->dtmfcount)
00612 printf("dtmfcount is %d\n", rtp->dtmfcount);
00613 #endif
00614 }
00615 rtp->lastrxts = timestamp;
00616
00617 /* Send any pending DTMF */
00618 if (rtp->resp && !rtp->dtmfcount) {
00619 if (option_debug)
00620 ast_log(LOG_DEBUG, "Sending pending DTMF\n");
00621 return send_dtmf(rtp);
00622 }
00623 rtp->f.mallocd = 0;
00624 rtp->f.datalen = res - hdrlen;
00625 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
00626 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
00627 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
00628 rtp->f.samples = ast_codec_get_samples(&rtp->f);
00629 if (rtp->f.subclass == AST_FORMAT_SLINEAR)
00630 ast_frame_byteswap_be(&rtp->f);
00631 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
00632 } else {
00633 /* Video -- samples is # of samples vs. 90000 */
00634 if (!rtp->lastividtimestamp)
00635 rtp->lastividtimestamp = timestamp;
00636 rtp->f.samples = timestamp - rtp->lastividtimestamp;
00637 rtp->lastividtimestamp = timestamp;
00638 rtp->f.delivery.tv_sec = 0;
00639 rtp->f.delivery.tv_usec = 0;
00640 if (mark)
00641 rtp->f.subclass |= 0x1;
00642
00643 }
00644 rtp->f.src = "RTP";
00645 return &rtp->f;
00646 }
|
|
|
Definition at line 1825 of file rtp.c. References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), cfg, DEFAULT_DTMF_TIMEOUT, dtmftimeout, LOG_WARNING, option_verbose, rtpend, rtpstart, s, and VERBOSE_PREFIX_2. Referenced by ast_module_reload(), ast_rtp_init(), and main(). 01826 {
01827 struct ast_config *cfg;
01828 char *s;
01829
01830 rtpstart = 5000;
01831 rtpend = 31000;
01832 dtmftimeout = DEFAULT_DTMF_TIMEOUT;
01833 cfg = ast_config_load("rtp.conf");
01834 if (cfg) {
01835 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
01836 rtpstart = atoi(s);
01837 if (rtpstart < 1024)
01838 rtpstart = 1024;
01839 if (rtpstart > 65535)
01840 rtpstart = 65535;
01841 }
01842 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
01843 rtpend = atoi(s);
01844 if (rtpend < 1024)
01845 rtpend = 1024;
01846 if (rtpend > 65535)
01847 rtpend = 65535;
01848 }
01849 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
01850 #ifdef SO_NO_CHECK
01851 if (ast_false(s))
01852 nochecksums = 1;
01853 else
01854 nochecksums = 0;
01855 #else
01856 if (ast_false(s))
01857 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
01858 #endif
01859 }
01860 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
01861 dtmftimeout = atoi(s);
01862 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
01863 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
01864 dtmftimeout, DEFAULT_DTMF_TIMEOUT);
01865 dtmftimeout = DEFAULT_DTMF_TIMEOUT;
01866 };
01867 }
01868 ast_config_destroy(cfg);
01869 }
01870 if (rtpstart >= rtpend) {
01871 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
01872 rtpstart = 5000;
01873 rtpend = 31000;
01874 }
01875 if (option_verbose > 1)
01876 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
01877
01878 }
|
|
|
Definition at line 1066 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. 01067 {
01068 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
01069 memset(&rtp->txcore, 0, sizeof(rtp->txcore));
01070 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
01071 rtp->lastts = 0;
01072 rtp->lastdigitts = 0;
01073 rtp->lastrxts = 0;
01074 rtp->lastividtimestamp = 0;
01075 rtp->lastovidtimestamp = 0;
01076 rtp->lasteventseqn = 0;
01077 rtp->lasteventendseqn = 0;
01078 rtp->lasttxformat = 0;
01079 rtp->lastrxformat = 0;
01080 rtp->dtmfcount = 0;
01081 rtp->dtmfduration = 0;
01082 rtp->seqno = 0;
01083 rtp->rxseqno = 0;
01084 }
|
|
||||||||||||
|
Definition at line 1202 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(). 01203 {
01204 unsigned int *rtpheader;
01205 int hdrlen = 12;
01206 int res;
01207 int payload;
01208 char data[256];
01209 char iabuf[INET_ADDRSTRLEN];
01210 level = 127 - (level & 0x7f);
01211 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
01212
01213 /* If we have no peer, return immediately */
01214 if (!rtp->them.sin_addr.s_addr)
01215 return 0;
01216
01217 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
01218
01219 /* Get a pointer to the header */
01220 rtpheader = (unsigned int *)data;
01221 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
01222 rtpheader[1] = htonl(rtp->lastts);
01223 rtpheader[2] = htonl(rtp->ssrc);
01224 data[12] = level;
01225 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01226 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
01227 if (res <0)
01228 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));
01229 if(rtp_debug_test_addr(&rtp->them))
01230 ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n"
01231 , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);
01232
01233 }
01234 return 0;
01235 }
|
|
||||||||||||
|
Definition at line 1120 of file rtp.c. References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), LOG_ERROR, LOG_WARNING, and rtp_debug_test_addr(). Referenced by oh323_digit(), and sip_senddigit(). 01121 {
01122 unsigned int *rtpheader;
01123 int hdrlen = 12;
01124 int res;
01125 int x;
01126 int payload;
01127 char data[256];
01128 char iabuf[INET_ADDRSTRLEN];
01129
01130 if ((digit <= '9') && (digit >= '0'))
01131 digit -= '0';
01132 else if (digit == '*')
01133 digit = 10;
01134 else if (digit == '#')
01135 digit = 11;
01136 else if ((digit >= 'A') && (digit <= 'D'))
01137 digit = digit - 'A' + 12;
01138 else if ((digit >= 'a') && (digit <= 'd'))
01139 digit = digit - 'a' + 12;
01140 else {
01141 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
01142 return -1;
01143 }
01144 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
01145
01146 /* If we have no peer, return immediately */
01147 if (!rtp->them.sin_addr.s_addr)
01148 return 0;
01149
01150 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
01151
01152 /* Get a pointer to the header */
01153 rtpheader = (unsigned int *)data;
01154 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
01155 rtpheader[1] = htonl(rtp->lastdigitts);
01156 rtpheader[2] = htonl(rtp->ssrc);
01157 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
01158 for (x = 0; x < 6; x++) {
01159 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01160 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
01161 if (res < 0)
01162 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
01163 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
01164 ntohs(rtp->them.sin_port), strerror(errno));
01165 if (rtp_debug_test_addr(&rtp->them))
01166 ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n",
01167 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
01168 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
01169 }
01170 /* Sequence number of last two end packets does not get incremented */
01171 if (x < 3)
01172 rtp->seqno++;
01173 /* Clear marker bit and set seqno */
01174 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
01175 /* For the last three packets, set the duration and the end bit */
01176 if (x == 2) {
01177 #if 0
01178 /* No, this is wrong... Do not increment lastdigitts, that's not according
01179 to the RFC, as best we can determine */
01180 rtp->lastdigitts++; /* or else the SPA3000 will click instead of beeping... */
01181 rtpheader[1] = htonl(rtp->lastdigitts);
01182 #endif
01183 /* Make duration 800 (100ms) */
01184 rtpheader[3] |= htonl((800));
01185 /* Set the End bit */
01186 rtpheader[3] |= htonl((1 << 23));
01187 }
01188 }
01189 /* Increment the digit timestamp by 120ms, to ensure that digits
01190 sent sequentially with no intervening non-digit packets do not
01191 get sent with the same timestamp, and that sequential digits
01192 have some 'dead air' in between them
01193 */
01194 rtp->lastdigitts += 960;
01195 /* Increment the sequence number to reflect the last packet
01196 that was sent
01197 */
01198 rtp->seqno++;
01199 return 0;
01200 }
|
|
||||||||||||
|
Definition at line 170 of file rtp.c. References ast_rtp::callback. Referenced by start_rtp(). 00171 {
00172 rtp->callback = callback;
00173 }
|
|
||||||||||||
|
Definition at line 165 of file rtp.c. References ast_rtp::data. Referenced by start_rtp(). 00166 {
00167 rtp->data = data;
00168 }
|
|
||||||||||||
|
Definition at line 742 of file rtp.c. References rtpPayloadType::code. Referenced by process_sdp(). 00742 {
00743 if (pt < 0 || pt > MAX_RTP_PT)
00744 return; /* bogus payload type */
00745
00746 if (static_RTP_PT[pt].code != 0) {
00747 rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
00748 }
00749 }
|
|
||||||||||||
|
Definition at line 1033 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(). 01034 {
01035 rtp->them.sin_port = them->sin_port;
01036 rtp->them.sin_addr = them->sin_addr;
01037 if (rtp->rtcp) {
01038 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
01039 rtp->rtcp->them.sin_addr = them->sin_addr;
01040 }
01041 rtp->rxseqno = 0;
01042 }
|
|
||||||||||||||||||||
|
Definition at line 753 of file rtp.c. References ast_rtp::current_RTP_PT, mimeTypes, subtype, and type. Referenced by process_sdp(), and set_dtmf_payload(). 00754 {
00755 int i;
00756
00757 if (pt < 0 || pt > MAX_RTP_PT)
00758 return; /* bogus payload type */
00759
00760 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00761 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
00762 strcasecmp(mimeType, mimeTypes[i].type) == 0) {
00763 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
00764 return;
00765 }
00766 }
00767 }
|
|
||||||||||||
|
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().
|
|
||||||||||||
|
Definition at line 1024 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::s. Referenced by oh323_alloc(), and sip_alloc(). 01025 {
01026 int res;
01027
01028 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
01029 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01030 return res;
01031 }
|
|
|
Definition at line 1056 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(). 01057 {
01058 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01059 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01060 if (rtp->rtcp) {
01061 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01062 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01063 }
01064 }
|
|
||||||||||||
|
Definition at line 1318 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_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, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_frame::subclass, and ast_rtp::them. Referenced by mgcp_write(), oh323_write(), sip_write(), and skinny_write(). 01319 {
01320 struct ast_frame *f;
01321 int codec;
01322 int hdrlen = 12;
01323 int subclass;
01324
01325
01326 /* If we have no peer, return immediately */
01327 if (!rtp->them.sin_addr.s_addr)
01328 return 0;
01329
01330 /* If there is no data length, return immediately */
01331 if (!_f->datalen)
01332 return 0;
01333
01334 /* Make sure we have enough space for RTP header */
01335 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
01336 ast_log(LOG_WARNING, "RTP can only send voice\n");
01337 return -1;
01338 }
01339
01340 subclass = _f->subclass;
01341 if (_f->frametype == AST_FRAME_VIDEO)
01342 subclass &= ~0x1;
01343
01344 codec = ast_rtp_lookup_code(rtp, 1, subclass);
01345 if (codec < 0) {
01346 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
01347 return -1;
01348 }
01349
01350 if (rtp->lasttxformat != subclass) {
01351 /* New format, reset the smoother */
01352 if (option_debug)
01353 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01354 rtp->lasttxformat = subclass;
01355 if (rtp->smoother)
01356 ast_smoother_free(rtp->smoother);
01357 rtp->smoother = NULL;
01358 }
01359
01360
01361 switch(subclass) {
01362 case AST_FORMAT_SLINEAR:
01363 if (!rtp->smoother) {
01364 rtp->smoother = ast_smoother_new(320);
01365 }
01366 if (!rtp->smoother) {
01367 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01368 return -1;
01369 }
01370 ast_smoother_feed_be(rtp->smoother, _f);
01371
01372 while((f = ast_smoother_read(rtp->smoother)))
01373 ast_rtp_raw_write(rtp, f, codec);
01374 break;
01375 case AST_FORMAT_ULAW:
01376 case AST_FORMAT_ALAW:
01377 if (!rtp->smoother) {
01378 rtp->smoother = ast_smoother_new(160);
01379 }
01380 if (!rtp->smoother) {
01381 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01382 return -1;
01383 }
01384 ast_smoother_feed(rtp->smoother, _f);
01385
01386 while((f = ast_smoother_read(rtp->smoother)))
01387 ast_rtp_raw_write(rtp, f, codec);
01388 break;
01389 case AST_FORMAT_ADPCM:
01390 case AST_FORMAT_G726:
01391 if (!rtp->smoother) {
01392 rtp->smoother = ast_smoother_new(80);
01393 }
01394 if (!rtp->smoother) {
01395 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01396 return -1;
01397 }
01398 ast_smoother_feed(rtp->smoother, _f);
01399
01400 while((f = ast_smoother_read(rtp->smoother)))
01401 ast_rtp_raw_write(rtp, f, codec);
01402 break;
01403 case AST_FORMAT_G729A:
01404 if (!rtp->smoother) {
01405 rtp->smoother = ast_smoother_new(20);
01406 if (rtp->smoother)
01407 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729);
01408 }
01409 if (!rtp->smoother) {
01410 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
01411 return -1;
01412 }
01413 ast_smoother_feed(rtp->smoother, _f);
01414
01415 while((f = ast_smoother_read(rtp->smoother)))
01416 ast_rtp_raw_write(rtp, f, codec);
01417 break;
01418 case AST_FORMAT_GSM:
01419 if (!rtp->smoother) {
01420 rtp->smoother = ast_smoother_new(33);
01421 }
01422 if (!rtp->smoother) {
01423 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
01424 return -1;
01425 }
01426 ast_smoother_feed(rtp->smoother, _f);
01427 while((f = ast_smoother_read(rtp->smoother)))
01428 ast_rtp_raw_write(rtp, f, codec);
01429 break;
01430 case AST_FORMAT_ILBC:
01431 if (!rtp->smoother) {
01432 rtp->smoother = ast_smoother_new(50);
01433 }
01434 if (!rtp->smoother) {
01435 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
01436 return -1;
01437 }
01438 ast_smoother_feed(rtp->smoother, _f);
01439 while((f = ast_smoother_read(rtp->smoother)))
01440 ast_rtp_raw_write(rtp, f, codec);
01441 break;
01442 default:
01443 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
01444 /* fall through to... */
01445 case AST_FORMAT_H261:
01446 case AST_FORMAT_H263:
01447 case AST_FORMAT_H263_PLUS:
01448 case AST_FORMAT_G723_1:
01449 case AST_FORMAT_LPC10:
01450 case AST_FORMAT_SPEEX:
01451 /* Don't buffer outgoing frames; send them one-per-packet: */
01452 if (_f->offset < hdrlen) {
01453 f = ast_frdup(_f);
01454 } else {
01455 f = _f;
01456 }
01457 ast_rtp_raw_write(rtp, f, codec);
01458 }
01459
01460 return 0;
01461 }
|
1.4.2