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