#include "asterisk/frame.h"
#include "asterisk/io.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include <netinet/in.h>
Go to the source code of this file.
Data Structures | |
struct | ast_rtp_protocol |
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) |
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, 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(), 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 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, 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 1524 of file rtp.c. References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_rtp_get_peer(), ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, option_debug, ast_rtp_protocol::set_rtp_peer, and ast_channel::tech_pvt. 01525 { 01526 struct ast_frame *f; 01527 struct ast_channel *who, *cs[3]; 01528 struct ast_rtp *p0, *p1; /* Audio RTP Channels */ 01529 struct ast_rtp *vp0, *vp1; /* Video RTP channels */ 01530 struct ast_rtp_protocol *pr0, *pr1; 01531 struct sockaddr_in ac0, ac1; 01532 struct sockaddr_in vac0, vac1; 01533 struct sockaddr_in t0, t1; 01534 struct sockaddr_in vt0, vt1; 01535 char iabuf[INET_ADDRSTRLEN]; 01536 01537 void *pvt0, *pvt1; 01538 int codec0,codec1, oldcodec0, oldcodec1; 01539 01540 memset(&vt0, 0, sizeof(vt0)); 01541 memset(&vt1, 0, sizeof(vt1)); 01542 memset(&vac0, 0, sizeof(vac0)); 01543 memset(&vac1, 0, sizeof(vac1)); 01544 01545 /* if need DTMF, cant native bridge */ 01546 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01547 return AST_BRIDGE_FAILED_NOWARN; 01548 01549 /* Lock channels */ 01550 ast_mutex_lock(&c0->lock); 01551 while(ast_mutex_trylock(&c1->lock)) { 01552 ast_mutex_unlock(&c0->lock); 01553 usleep(1); 01554 ast_mutex_lock(&c0->lock); 01555 } 01556 01557 /* Find channel driver interfaces */ 01558 pr0 = get_proto(c0); 01559 pr1 = get_proto(c1); 01560 if (!pr0) { 01561 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01562 ast_mutex_unlock(&c0->lock); 01563 ast_mutex_unlock(&c1->lock); 01564 return AST_BRIDGE_FAILED; 01565 } 01566 if (!pr1) { 01567 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01568 ast_mutex_unlock(&c0->lock); 01569 ast_mutex_unlock(&c1->lock); 01570 return AST_BRIDGE_FAILED; 01571 } 01572 01573 /* Get channel specific interface structures */ 01574 pvt0 = c0->tech_pvt; 01575 pvt1 = c1->tech_pvt; 01576 01577 /* Get audio and video interface (if native bridge is possible) */ 01578 p0 = pr0->get_rtp_info(c0); 01579 if (pr0->get_vrtp_info) 01580 vp0 = pr0->get_vrtp_info(c0); 01581 else 01582 vp0 = NULL; 01583 p1 = pr1->get_rtp_info(c1); 01584 if (pr1->get_vrtp_info) 01585 vp1 = pr1->get_vrtp_info(c1); 01586 else 01587 vp1 = NULL; 01588 01589 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01590 if (!p0 || !p1) { 01591 /* Somebody doesn't want to play... */ 01592 ast_mutex_unlock(&c0->lock); 01593 ast_mutex_unlock(&c1->lock); 01594 return AST_BRIDGE_FAILED_NOWARN; 01595 } 01596 /* Get codecs from both sides */ 01597 if (pr0->get_codec) 01598 codec0 = pr0->get_codec(c0); 01599 else 01600 codec0 = 0; 01601 if (pr1->get_codec) 01602 codec1 = pr1->get_codec(c1); 01603 else 01604 codec1 = 0; 01605 if (pr0->get_codec && pr1->get_codec) { 01606 /* Hey, we can't do reinvite if both parties speak different codecs */ 01607 if (!(codec0 & codec1)) { 01608 if (option_debug) 01609 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 01610 ast_mutex_unlock(&c0->lock); 01611 ast_mutex_unlock(&c1->lock); 01612 return AST_BRIDGE_FAILED_NOWARN; 01613 } 01614 } 01615 01616 /* Ok, we should be able to redirect the media. Start with one channel */ 01617 if (pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 01618 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01619 else { 01620 /* Store RTP peer */ 01621 ast_rtp_get_peer(p1, &ac1); 01622 if (vp1) 01623 ast_rtp_get_peer(vp1, &vac1); 01624 } 01625 /* Then test the other channel */ 01626 if (pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 01627 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01628 else { 01629 /* Store RTP peer */ 01630 ast_rtp_get_peer(p0, &ac0); 01631 if (vp0) 01632 ast_rtp_get_peer(vp0, &vac0); 01633 } 01634 ast_mutex_unlock(&c0->lock); 01635 ast_mutex_unlock(&c1->lock); 01636 /* External RTP Bridge up, now loop and see if something happes that force us to take the 01637 media back to Asterisk */ 01638 cs[0] = c0; 01639 cs[1] = c1; 01640 cs[2] = NULL; 01641 oldcodec0 = codec0; 01642 oldcodec1 = codec1; 01643 for (;;) { 01644 /* Check if something changed... */ 01645 if ((c0->tech_pvt != pvt0) || 01646 (c1->tech_pvt != pvt1) || 01647 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01648 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01649 if (c0->tech_pvt == pvt0) { 01650 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01651 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01652 } 01653 if (c1->tech_pvt == pvt1) { 01654 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01655 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01656 } 01657 return AST_BRIDGE_RETRY; 01658 } 01659 /* Now check if they have changed address */ 01660 ast_rtp_get_peer(p1, &t1); 01661 ast_rtp_get_peer(p0, &t0); 01662 if (pr0->get_codec) 01663 codec0 = pr0->get_codec(c0); 01664 if (pr1->get_codec) 01665 codec1 = pr1->get_codec(c1); 01666 if (vp1) 01667 ast_rtp_get_peer(vp1, &vt1); 01668 if (vp0) 01669 ast_rtp_get_peer(vp0, &vt0); 01670 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) { 01671 if (option_debug > 1) { 01672 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01673 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1); 01674 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 01675 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1); 01676 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01677 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 01678 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01679 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 01680 } 01681 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))) 01682 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01683 memcpy(&ac1, &t1, sizeof(ac1)); 01684 memcpy(&vac1, &vt1, sizeof(vac1)); 01685 oldcodec1 = codec1; 01686 } 01687 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01688 if (option_debug) { 01689 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01690 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0); 01691 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01692 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 01693 } 01694 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))) 01695 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01696 memcpy(&ac0, &t0, sizeof(ac0)); 01697 memcpy(&vac0, &vt0, sizeof(vac0)); 01698 oldcodec0 = codec0; 01699 } 01700 who = ast_waitfor_n(cs, 2, &timeoutms); 01701 if (!who) { 01702 if (!timeoutms) 01703 return AST_BRIDGE_RETRY; 01704 if (option_debug) 01705 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01706 /* check for hangup / whentohangup */ 01707 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01708 break; 01709 continue; 01710 } 01711 f = ast_read(who); 01712 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01713 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01714 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01715 *fo = f; 01716 *rc = who; 01717 if (option_debug) 01718 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01719 if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) { 01720 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01721 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01722 } 01723 if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) { 01724 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01725 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01726 } 01727 return AST_BRIDGE_COMPLETE; 01728 } else if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 01729 if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD) || 01730 (f->subclass == AST_CONTROL_VIDUPDATE)) { 01731 ast_indicate(who == c0 ? c1 : c0, f->subclass); 01732 ast_frfree(f); 01733 } else { 01734 *fo = f; 01735 *rc = who; 01736 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 01737 return AST_BRIDGE_COMPLETE; 01738 } 01739 } else { 01740 if ((f->frametype == AST_FRAME_DTMF) || 01741 (f->frametype == AST_FRAME_VOICE) || 01742 (f->frametype == AST_FRAME_VIDEO)) { 01743 /* Forward voice or DTMF frames if they happen upon us */ 01744 if (who == c0) { 01745 ast_write(c1, f); 01746 } else if (who == c1) { 01747 ast_write(c0, f); 01748 } 01749 } 01750 ast_frfree(f); 01751 } 01752 /* Swap priority not that it's a big deal at this point */ 01753 cs[2] = cs[0]; 01754 cs[0] = cs[1]; 01755 cs[1] = cs[2]; 01756 01757 } 01758 return AST_BRIDGE_FAILED; 01759 }
|
|
Definition at line 1092 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(), mgcp_hangup(), skinny_hangup(), start_rtp(), and unalloc_sub(). 01093 { 01094 if (rtp->smoother) 01095 ast_smoother_free(rtp->smoother); 01096 if (rtp->ioid) 01097 ast_io_remove(rtp->io, rtp->ioid); 01098 if (rtp->s > -1) 01099 close(rtp->s); 01100 if (rtp->rtcp) { 01101 close(rtp->rtcp->s); 01102 free(rtp->rtcp); 01103 } 01104 free(rtp); 01105 }
|
|
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, rtpPayloadType::isAstFormat, and MAX_RTP_PT. 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 if ((them->sin_family != AF_INET) || 01047 (them->sin_port != rtp->them.sin_port) || 01048 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 01049 them->sin_family = AF_INET; 01050 them->sin_port = rtp->them.sin_port; 01051 them->sin_addr = rtp->them.sin_addr; 01052 return 1; 01053 } 01054 return 0; 01055 }
|
|
Definition at line 1057 of file rtp.c. References ast_rtp::us. Referenced by add_sdp(), external_rtp_create(), and oh323_set_rtp_peer().
|
|
Definition at line 1887 of file rtp.c. References ast_cli_register(), ast_rtp_reload(), cli_debug, cli_debug_ip, and cli_no_debug. 01888 { 01889 ast_cli_register(&cli_debug); 01890 ast_cli_register(&cli_debug_ip); 01891 ast_cli_register(&cli_no_debug); 01892 ast_rtp_reload(); 01893 }
|
|
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(), 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(), 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. 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(), io, and sched. 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_log(), ast_rtcp_new(), free, LOG_ERROR, malloc, ast_rtp::rtcp, rtp_socket(), rtpend, rtpstart, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, 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(). 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(), LOG_WARNING, and ast_rtp::rtp_offered_from_local. Referenced by transmit_invite(), 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 1490 of file rtp.c. References ast_log(), LOG_WARNING, ast_rtp_protocol::next, protos, and ast_rtp_protocol::type. Referenced by load_module(), and unload_module(). 01491 { 01492 struct ast_rtp_protocol *cur; 01493 cur = protos; 01494 while(cur) { 01495 if (cur->type == proto->type) { 01496 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01497 return -1; 01498 } 01499 cur = cur->next; 01500 } 01501 proto->next = protos; 01502 protos = proto; 01503 return 0; 01504 }
|
|
Definition at line 1470 of file rtp.c. References ast_rtp_protocol::next, and protos. Referenced by unload_module(). 01471 { 01472 struct ast_rtp_protocol *cur, *prev; 01473 01474 cur = protos; 01475 prev = NULL; 01476 while(cur) { 01477 if (cur == proto) { 01478 if (prev) 01479 prev->next = proto->next; 01480 else 01481 protos = proto->next; 01482 return; 01483 } 01484 prev = cur; 01485 cur = cur->next; 01486 } 01487 }
|
|
Definition at line 708 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT. 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, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and static_RTP_PT. 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, 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(). 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 1831 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, option_verbose, rtpend, rtpstart, s, and VERBOSE_PREFIX_2. Referenced by ast_module_reload(), and ast_rtp_init(). 01832 { 01833 struct ast_config *cfg; 01834 char *s; 01835 01836 rtpstart = 5000; 01837 rtpend = 31000; 01838 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 01839 cfg = ast_config_load("rtp.conf"); 01840 if (cfg) { 01841 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01842 rtpstart = atoi(s); 01843 if (rtpstart < 1024) 01844 rtpstart = 1024; 01845 if (rtpstart > 65535) 01846 rtpstart = 65535; 01847 } 01848 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01849 rtpend = atoi(s); 01850 if (rtpend < 1024) 01851 rtpend = 1024; 01852 if (rtpend > 65535) 01853 rtpend = 65535; 01854 } 01855 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 01856 #ifdef SO_NO_CHECK 01857 if (ast_false(s)) 01858 nochecksums = 1; 01859 else 01860 nochecksums = 0; 01861 #else 01862 if (ast_false(s)) 01863 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 01864 #endif 01865 } 01866 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 01867 dtmftimeout = atoi(s); 01868 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 01869 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 01870 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 01871 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 01872 }; 01873 } 01874 ast_config_destroy(cfg); 01875 } 01876 if (rtpstart >= rtpend) { 01877 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 01878 rtpstart = 5000; 01879 rtpend = 31000; 01880 } 01881 if (option_verbose > 1) 01882 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01883 01884 }
|
|
Definition at line 1072 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. 01073 { 01074 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 01075 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 01076 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 01077 rtp->lastts = 0; 01078 rtp->lastdigitts = 0; 01079 rtp->lastrxts = 0; 01080 rtp->lastividtimestamp = 0; 01081 rtp->lastovidtimestamp = 0; 01082 rtp->lasteventseqn = 0; 01083 rtp->lasteventendseqn = 0; 01084 rtp->lasttxformat = 0; 01085 rtp->lastrxformat = 0; 01086 rtp->dtmfcount = 0; 01087 rtp->dtmfduration = 0; 01088 rtp->seqno = 0; 01089 rtp->rxseqno = 0; 01090 }
|
|
Definition at line 1208 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(). 01209 { 01210 unsigned int *rtpheader; 01211 int hdrlen = 12; 01212 int res; 01213 int payload; 01214 char data[256]; 01215 char iabuf[INET_ADDRSTRLEN]; 01216 level = 127 - (level & 0x7f); 01217 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 01218 01219 /* If we have no peer, return immediately */ 01220 if (!rtp->them.sin_addr.s_addr) 01221 return 0; 01222 01223 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 01224 01225 /* Get a pointer to the header */ 01226 rtpheader = (unsigned int *)data; 01227 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 01228 rtpheader[1] = htonl(rtp->lastts); 01229 rtpheader[2] = htonl(rtp->ssrc); 01230 data[12] = level; 01231 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01232 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 01233 if (res <0) 01234 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)); 01235 if(rtp_debug_test_addr(&rtp->them)) 01236 ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n" 01237 , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 01238 01239 } 01240 return 0; 01241 }
|
|
Definition at line 1126 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(). 01127 { 01128 unsigned int *rtpheader; 01129 int hdrlen = 12; 01130 int res; 01131 int x; 01132 int payload; 01133 char data[256]; 01134 char iabuf[INET_ADDRSTRLEN]; 01135 01136 if ((digit <= '9') && (digit >= '0')) 01137 digit -= '0'; 01138 else if (digit == '*') 01139 digit = 10; 01140 else if (digit == '#') 01141 digit = 11; 01142 else if ((digit >= 'A') && (digit <= 'D')) 01143 digit = digit - 'A' + 12; 01144 else if ((digit >= 'a') && (digit <= 'd')) 01145 digit = digit - 'a' + 12; 01146 else { 01147 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 01148 return -1; 01149 } 01150 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 01151 01152 /* If we have no peer, return immediately */ 01153 if (!rtp->them.sin_addr.s_addr) 01154 return 0; 01155 01156 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 01157 01158 /* Get a pointer to the header */ 01159 rtpheader = (unsigned int *)data; 01160 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 01161 rtpheader[1] = htonl(rtp->lastdigitts); 01162 rtpheader[2] = htonl(rtp->ssrc); 01163 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 01164 for (x = 0; x < 6; x++) { 01165 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01166 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 01167 if (res < 0) 01168 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 01169 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), 01170 ntohs(rtp->them.sin_port), strerror(errno)); 01171 if (rtp_debug_test_addr(&rtp->them)) 01172 ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n", 01173 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), 01174 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 01175 } 01176 /* Sequence number of last two end packets does not get incremented */ 01177 if (x < 3) 01178 rtp->seqno++; 01179 /* Clear marker bit and set seqno */ 01180 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 01181 /* For the last three packets, set the duration and the end bit */ 01182 if (x == 2) { 01183 #if 0 01184 /* No, this is wrong... Do not increment lastdigitts, that's not according 01185 to the RFC, as best we can determine */ 01186 rtp->lastdigitts++; /* or else the SPA3000 will click instead of beeping... */ 01187 rtpheader[1] = htonl(rtp->lastdigitts); 01188 #endif 01189 /* Make duration 800 (100ms) */ 01190 rtpheader[3] |= htonl((800)); 01191 /* Set the End bit */ 01192 rtpheader[3] |= htonl((1 << 23)); 01193 } 01194 } 01195 /* Increment the digit timestamp by 120ms, to ensure that digits 01196 sent sequentially with no intervening non-digit packets do not 01197 get sent with the same timestamp, and that sequential digits 01198 have some 'dead air' in between them 01199 */ 01200 rtp->lastdigitts += 960; 01201 /* Increment the sequence number to reflect the last packet 01202 that was sent 01203 */ 01204 rtp->seqno++; 01205 return 0; 01206 }
|
|
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, ast_rtp::current_RTP_PT, MAX_RTP_PT, and static_RTP_PT. 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 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, MAX_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 1062 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(). 01063 { 01064 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 01065 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 01066 if (rtp->rtcp) { 01067 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 01068 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 01069 } 01070 }
|
|
Definition at line 1324 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, 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(). 01325 { 01326 struct ast_frame *f; 01327 int codec; 01328 int hdrlen = 12; 01329 int subclass; 01330 01331 01332 /* If we have no peer, return immediately */ 01333 if (!rtp->them.sin_addr.s_addr) 01334 return 0; 01335 01336 /* If there is no data length, return immediately */ 01337 if (!_f->datalen) 01338 return 0; 01339 01340 /* Make sure we have enough space for RTP header */ 01341 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 01342 ast_log(LOG_WARNING, "RTP can only send voice\n"); 01343 return -1; 01344 } 01345 01346 subclass = _f->subclass; 01347 if (_f->frametype == AST_FRAME_VIDEO) 01348 subclass &= ~0x1; 01349 01350 codec = ast_rtp_lookup_code(rtp, 1, subclass); 01351 if (codec < 0) { 01352 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 01353 return -1; 01354 } 01355 01356 if (rtp->lasttxformat != subclass) { 01357 /* New format, reset the smoother */ 01358 if (option_debug) 01359 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01360 rtp->lasttxformat = subclass; 01361 if (rtp->smoother) 01362 ast_smoother_free(rtp->smoother); 01363 rtp->smoother = NULL; 01364 } 01365 01366 01367 switch(subclass) { 01368 case AST_FORMAT_SLINEAR: 01369 if (!rtp->smoother) { 01370 rtp->smoother = ast_smoother_new(320); 01371 } 01372 if (!rtp->smoother) { 01373 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01374 return -1; 01375 } 01376 ast_smoother_feed_be(rtp->smoother, _f); 01377 01378 while((f = ast_smoother_read(rtp->smoother))) 01379 ast_rtp_raw_write(rtp, f, codec); 01380 break; 01381 case AST_FORMAT_ULAW: 01382 case AST_FORMAT_ALAW: 01383 if (!rtp->smoother) { 01384 rtp->smoother = ast_smoother_new(160); 01385 } 01386 if (!rtp->smoother) { 01387 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01388 return -1; 01389 } 01390 ast_smoother_feed(rtp->smoother, _f); 01391 01392 while((f = ast_smoother_read(rtp->smoother))) 01393 ast_rtp_raw_write(rtp, f, codec); 01394 break; 01395 case AST_FORMAT_ADPCM: 01396 case AST_FORMAT_G726: 01397 if (!rtp->smoother) { 01398 rtp->smoother = ast_smoother_new(80); 01399 } 01400 if (!rtp->smoother) { 01401 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01402 return -1; 01403 } 01404 ast_smoother_feed(rtp->smoother, _f); 01405 01406 while((f = ast_smoother_read(rtp->smoother))) 01407 ast_rtp_raw_write(rtp, f, codec); 01408 break; 01409 case AST_FORMAT_G729A: 01410 if (!rtp->smoother) { 01411 rtp->smoother = ast_smoother_new(20); 01412 if (rtp->smoother) 01413 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729); 01414 } 01415 if (!rtp->smoother) { 01416 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n"); 01417 return -1; 01418 } 01419 ast_smoother_feed(rtp->smoother, _f); 01420 01421 while((f = ast_smoother_read(rtp->smoother))) 01422 ast_rtp_raw_write(rtp, f, codec); 01423 break; 01424 case AST_FORMAT_GSM: 01425 if (!rtp->smoother) { 01426 rtp->smoother = ast_smoother_new(33); 01427 } 01428 if (!rtp->smoother) { 01429 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n"); 01430 return -1; 01431 } 01432 ast_smoother_feed(rtp->smoother, _f); 01433 while((f = ast_smoother_read(rtp->smoother))) 01434 ast_rtp_raw_write(rtp, f, codec); 01435 break; 01436 case AST_FORMAT_ILBC: 01437 if (!rtp->smoother) { 01438 rtp->smoother = ast_smoother_new(50); 01439 } 01440 if (!rtp->smoother) { 01441 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n"); 01442 return -1; 01443 } 01444 ast_smoother_feed(rtp->smoother, _f); 01445 while((f = ast_smoother_read(rtp->smoother))) 01446 ast_rtp_raw_write(rtp, f, codec); 01447 break; 01448 default: 01449 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass)); 01450 /* fall through to... */ 01451 case AST_FORMAT_H261: 01452 case AST_FORMAT_H263: 01453 case AST_FORMAT_H263_PLUS: 01454 case AST_FORMAT_G723_1: 01455 case AST_FORMAT_LPC10: 01456 case AST_FORMAT_SPEEX: 01457 /* Don't buffer outgoing frames; send them one-per-packet: */ 01458 if (_f->offset < hdrlen) { 01459 f = ast_frdup(_f); 01460 } else { 01461 f = _f; 01462 } 01463 ast_rtp_raw_write(rtp, f, codec); 01464 } 01465 01466 return 0; 01467 }
|