#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk.h"
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"
Include dependency graph for rtp.c:

Go to the source code of this file.
Data Structures | |
| struct | ast_rtcp |
| Structure defining an RTCP session. More... | |
| struct | ast_rtp |
| struct | rtpPayloadType |
Defines | |
| #define | DEFAULT_DTMF_TIMEOUT 3000 |
| #define | FLAG_3389_WARNING (1 << 0) |
| #define | FLAG_NAT_ACTIVE (3 << 1) |
| #define | FLAG_NAT_INACTIVE (0 << 1) |
| #define | FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
| #define | MAX_RTP_PT 256 |
| #define | MAX_TIMESTAMP_SKEW 640 |
| #define | RTP_MTU 1200 |
Functions | |
| int | ast_rtcp_fd (struct ast_rtp *rtp) |
| static struct ast_rtcp * | ast_rtcp_new (void) |
| Initialize a new RTCP session. | |
| ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
| enum ast_bridge_result | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
| void | ast_rtp_destroy (struct ast_rtp *rtp) |
| int | ast_rtp_fd (struct ast_rtp *rtp) |
| void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
| int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
| void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
| void | ast_rtp_init (void) |
| int | ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code) |
| char * | ast_rtp_lookup_mime_multiple (char *buf, int size, const int capability, const int isAstFormat) |
| char * | ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code) |
| 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 addr) |
| Initializate a RTP session using an in_addr structure. | |
| void | ast_rtp_offered_from_local (struct ast_rtp *rtp, int local) |
| int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
| void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
| void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
| void | ast_rtp_pt_default (struct ast_rtp *rtp) |
| static int | ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec) |
| ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
| void | ast_rtp_reload (void) |
| void | ast_rtp_reset (struct ast_rtp *rtp) |
| int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
| int | ast_rtp_senddigit (struct ast_rtp *rtp, char digit) |
| void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
| void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
| void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
| void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
| void | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype) |
| void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
| int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
| void | ast_rtp_stop (struct ast_rtp *rtp) |
| int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f) |
| static void | calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark) |
| static unsigned int | calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery) |
| static struct ast_rtp_protocol * | get_proto (struct ast_channel *chan) |
| static struct ast_frame * | process_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len) |
| static struct ast_frame * | process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno) |
| Process RTP DTMF and events according to RFC 2833. | |
| static struct ast_frame * | process_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len) |
| Process Comfort Noise RTP. | |
| static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
| static int | rtp_do_debug (int fd, int argc, char *argv[]) |
| static int | rtp_do_debug_ip (int fd, int argc, char *argv[]) |
| static int | rtp_no_debug (int fd, int argc, char *argv[]) |
| static int | rtp_socket (void) |
| static int | rtpread (int *id, int fd, short events, void *cbdata) |
| static struct ast_frame * | send_dtmf (struct ast_rtp *rtp) |
Variables | |
| static struct ast_cli_entry | cli_debug |
| static struct ast_cli_entry | cli_debug_ip |
| static struct ast_cli_entry | cli_no_debug |
| static char | debug_usage [] |
| static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
| struct { | |
| rtpPayloadType payloadType | |
| char * subtype | |
| char * type | |
| } | mimeTypes [] |
| static char | no_debug_usage [] |
| static struct ast_rtp_protocol * | protos = NULL |
| static int | rtpdebug = 0 |
| static struct sockaddr_in | rtpdebugaddr |
| static int | rtpend = 0 |
| static int | rtpstart = 0 |
| static struct rtpPayloadType | static_RTP_PT [MAX_RTP_PT] |
RTP is deffined in RFC 3550.
Definition in file rtp.c.
| #define DEFAULT_DTMF_TIMEOUT 3000 |
| #define FLAG_3389_WARNING (1 << 0) |
| #define FLAG_NAT_ACTIVE (3 << 1) |
Definition at line 82 of file rtp.c.
Referenced by ast_rtp_bridge(), ast_rtp_raw_write(), and ast_rtp_read().
| #define FLAG_NAT_INACTIVE (0 << 1) |
| #define FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
| #define MAX_RTP_PT 256 |
Definition at line 79 of file rtp.c.
Referenced by ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_default(), ast_rtp_set_m_type(), and ast_rtp_set_rtpmap_type().
| #define MAX_TIMESTAMP_SKEW 640 |
Definition at line 57 of file rtp.c.
Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp().
| int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 158 of file rtp.c.
References ast_rtp::rtcp, and ast_rtcp::s.
Referenced by sip_new().
| static struct ast_rtcp* ast_rtcp_new | ( | void | ) | [static] |
Initialize a new RTCP session.
Definition at line 923 of file rtp.c.
References ast_log(), free, LOG_WARNING, malloc, rtp_socket(), ast_rtcp::s, and ast_rtcp::us.
Referenced by ast_rtp_new_with_bindaddr().
00924 { 00925 struct ast_rtcp *rtcp; 00926 rtcp = malloc(sizeof(struct ast_rtcp)); 00927 if (!rtcp) 00928 return NULL; 00929 memset(rtcp, 0, sizeof(struct ast_rtcp)); 00930 rtcp->s = rtp_socket(); 00931 rtcp->us.sin_family = AF_INET; 00932 if (rtcp->s < 0) { 00933 free(rtcp); 00934 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00935 return NULL; 00936 } 00937 return rtcp; 00938 }
Definition at line 370 of file rtp.c.
References AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, ast_rtcp::s, and ast_rtcp::them.
Referenced by sip_rtp_read().
00371 { 00372 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00373 socklen_t len; 00374 int hdrlen = 8; 00375 int res; 00376 struct sockaddr_in sin; 00377 unsigned int rtcpdata[1024]; 00378 char iabuf[INET_ADDRSTRLEN]; 00379 00380 if (!rtp || !rtp->rtcp) 00381 return &null_frame; 00382 00383 len = sizeof(sin); 00384 00385 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata), 00386 0, (struct sockaddr *)&sin, &len); 00387 00388 if (res < 0) { 00389 if (errno == EBADF) 00390 CRASH; 00391 if (errno != EAGAIN) { 00392 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up now.\n", strerror(errno)); 00393 return NULL; 00394 } 00395 return &null_frame; 00396 } 00397 00398 if (res < hdrlen) { 00399 ast_log(LOG_WARNING, "RTP Read too short\n"); 00400 return &null_frame; 00401 } 00402 00403 if (rtp->nat) { 00404 /* Send to whoever sent to us */ 00405 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00406 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00407 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00408 if (option_debug || rtpdebug) 00409 ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00410 } 00411 } 00412 if (option_debug) 00413 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00414 return &null_frame; 00415 }
| enum ast_bridge_result ast_rtp_bridge | ( | struct ast_channel * | c0, | |
| struct ast_channel * | c1, | |||
| int | flags, | |||
| struct ast_frame ** | fo, | |||
| struct ast_channel ** | rc, | |||
| int | timeoutms | |||
| ) |
Definition at line 1539 of file rtp.c.
References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, 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.
01540 { 01541 struct ast_frame *f; 01542 struct ast_channel *who, *cs[3]; 01543 struct ast_rtp *p0, *p1; /* Audio RTP Channels */ 01544 struct ast_rtp *vp0, *vp1; /* Video RTP channels */ 01545 struct ast_rtp_protocol *pr0, *pr1; 01546 struct sockaddr_in ac0, ac1; 01547 struct sockaddr_in vac0, vac1; 01548 struct sockaddr_in t0, t1; 01549 struct sockaddr_in vt0, vt1; 01550 char iabuf[INET_ADDRSTRLEN]; 01551 01552 void *pvt0, *pvt1; 01553 int codec0,codec1, oldcodec0, oldcodec1; 01554 01555 memset(&vt0, 0, sizeof(vt0)); 01556 memset(&vt1, 0, sizeof(vt1)); 01557 memset(&vac0, 0, sizeof(vac0)); 01558 memset(&vac1, 0, sizeof(vac1)); 01559 01560 /* if need DTMF, cant native bridge */ 01561 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01562 return AST_BRIDGE_FAILED_NOWARN; 01563 01564 /* Lock channels */ 01565 ast_mutex_lock(&c0->lock); 01566 while(ast_mutex_trylock(&c1->lock)) { 01567 ast_mutex_unlock(&c0->lock); 01568 usleep(1); 01569 ast_mutex_lock(&c0->lock); 01570 } 01571 01572 /* Find channel driver interfaces */ 01573 pr0 = get_proto(c0); 01574 pr1 = get_proto(c1); 01575 if (!pr0) { 01576 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01577 ast_mutex_unlock(&c0->lock); 01578 ast_mutex_unlock(&c1->lock); 01579 return AST_BRIDGE_FAILED; 01580 } 01581 if (!pr1) { 01582 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01583 ast_mutex_unlock(&c0->lock); 01584 ast_mutex_unlock(&c1->lock); 01585 return AST_BRIDGE_FAILED; 01586 } 01587 01588 /* Get channel specific interface structures */ 01589 pvt0 = c0->tech_pvt; 01590 pvt1 = c1->tech_pvt; 01591 01592 /* Get audio and video interface (if native bridge is possible) */ 01593 p0 = pr0->get_rtp_info(c0); 01594 if (pr0->get_vrtp_info) 01595 vp0 = pr0->get_vrtp_info(c0); 01596 else 01597 vp0 = NULL; 01598 p1 = pr1->get_rtp_info(c1); 01599 if (pr1->get_vrtp_info) 01600 vp1 = pr1->get_vrtp_info(c1); 01601 else 01602 vp1 = NULL; 01603 01604 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01605 if (!p0 || !p1) { 01606 /* Somebody doesn't want to play... */ 01607 ast_mutex_unlock(&c0->lock); 01608 ast_mutex_unlock(&c1->lock); 01609 return AST_BRIDGE_FAILED_NOWARN; 01610 } 01611 /* Get codecs from both sides */ 01612 if (pr0->get_codec) 01613 codec0 = pr0->get_codec(c0); 01614 else 01615 codec0 = 0; 01616 if (pr1->get_codec) 01617 codec1 = pr1->get_codec(c1); 01618 else 01619 codec1 = 0; 01620 if (pr0->get_codec && pr1->get_codec) { 01621 /* Hey, we can't do reinvite if both parties speak different codecs */ 01622 if (!(codec0 & codec1)) { 01623 if (option_debug) 01624 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 01625 ast_mutex_unlock(&c0->lock); 01626 ast_mutex_unlock(&c1->lock); 01627 return AST_BRIDGE_FAILED_NOWARN; 01628 } 01629 } 01630 01631 /* Ok, we should be able to redirect the media. Start with one channel */ 01632 if (pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 01633 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01634 else { 01635 /* Store RTP peer */ 01636 ast_rtp_get_peer(p1, &ac1); 01637 if (vp1) 01638 ast_rtp_get_peer(vp1, &vac1); 01639 } 01640 /* Then test the other channel */ 01641 if (pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 01642 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01643 else { 01644 /* Store RTP peer */ 01645 ast_rtp_get_peer(p0, &ac0); 01646 if (vp0) 01647 ast_rtp_get_peer(vp0, &vac0); 01648 } 01649 ast_mutex_unlock(&c0->lock); 01650 ast_mutex_unlock(&c1->lock); 01651 /* External RTP Bridge up, now loop and see if something happes that force us to take the 01652 media back to Asterisk */ 01653 cs[0] = c0; 01654 cs[1] = c1; 01655 cs[2] = NULL; 01656 oldcodec0 = codec0; 01657 oldcodec1 = codec1; 01658 for (;;) { 01659 /* Check if something changed... */ 01660 if ((c0->tech_pvt != pvt0) || 01661 (c1->tech_pvt != pvt1) || 01662 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01663 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01664 if (c0->tech_pvt == pvt0) { 01665 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01666 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01667 } 01668 if (c1->tech_pvt == pvt1) { 01669 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01670 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01671 } 01672 return AST_BRIDGE_RETRY; 01673 } 01674 /* Now check if they have changed address */ 01675 ast_rtp_get_peer(p1, &t1); 01676 ast_rtp_get_peer(p0, &t0); 01677 if (pr0->get_codec) 01678 codec0 = pr0->get_codec(c0); 01679 if (pr1->get_codec) 01680 codec1 = pr1->get_codec(c1); 01681 if (vp1) 01682 ast_rtp_get_peer(vp1, &vt1); 01683 if (vp0) 01684 ast_rtp_get_peer(vp0, &vt0); 01685 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) { 01686 if (option_debug > 1) { 01687 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01688 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1); 01689 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 01690 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1); 01691 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01692 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 01693 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01694 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 01695 } 01696 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 01697 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01698 memcpy(&ac1, &t1, sizeof(ac1)); 01699 memcpy(&vac1, &vt1, sizeof(vac1)); 01700 oldcodec1 = codec1; 01701 } 01702 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01703 if (option_debug) { 01704 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01705 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0); 01706 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01707 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 01708 } 01709 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 01710 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01711 memcpy(&ac0, &t0, sizeof(ac0)); 01712 memcpy(&vac0, &vt0, sizeof(vac0)); 01713 oldcodec0 = codec0; 01714 } 01715 who = ast_waitfor_n(cs, 2, &timeoutms); 01716 if (!who) { 01717 if (!timeoutms) { 01718 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01719 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01720 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01721 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01722 return AST_BRIDGE_RETRY; 01723 } 01724 if (option_debug) 01725 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01726 /* check for hangup / whentohangup */ 01727 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01728 break; 01729 continue; 01730 } 01731 f = ast_read(who); 01732 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01733 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01734 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01735 *fo = f; 01736 *rc = who; 01737 if (option_debug) 01738 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01739 if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) { 01740 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01741 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01742 } 01743 if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) { 01744 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01745 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01746 } 01747 return AST_BRIDGE_COMPLETE; 01748 } else if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 01749 if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD) || 01750 (f->subclass == AST_CONTROL_VIDUPDATE)) { 01751 ast_indicate(who == c0 ? c1 : c0, f->subclass); 01752 ast_frfree(f); 01753 } else { 01754 *fo = f; 01755 *rc = who; 01756 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 01757 return AST_BRIDGE_COMPLETE; 01758 } 01759 } else { 01760 if ((f->frametype == AST_FRAME_DTMF) || 01761 (f->frametype == AST_FRAME_VOICE) || 01762 (f->frametype == AST_FRAME_VIDEO)) { 01763 /* Forward voice or DTMF frames if they happen upon us */ 01764 if (who == c0) { 01765 ast_write(c1, f); 01766 } else if (who == c1) { 01767 ast_write(c0, f); 01768 } 01769 } 01770 ast_frfree(f); 01771 } 01772 /* Swap priority not that it's a big deal at this point */ 01773 cs[2] = cs[0]; 01774 cs[0] = cs[1]; 01775 cs[1] = cs[2]; 01776 01777 } 01778 01779 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01780 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01781 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01782 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01783 01784 return AST_BRIDGE_FAILED; 01785 }
| void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 1105 of file rtp.c.
References ast_io_remove(), ast_smoother_free(), free, ast_rtp::io, ast_rtp::ioid, ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, and ast_rtp::smoother.
Referenced by __oh323_destroy(), __sip_destroy(), cleanup_connection(), destroy_endpoint(), mgcp_hangup(), skinny_hangup(), start_rtp(), and unalloc_sub().
01106 { 01107 if (rtp->smoother) 01108 ast_smoother_free(rtp->smoother); 01109 if (rtp->ioid) 01110 ast_io_remove(rtp->io, rtp->ioid); 01111 if (rtp->s > -1) 01112 close(rtp->s); 01113 if (rtp->rtcp) { 01114 close(rtp->rtcp->s); 01115 free(rtp->rtcp); 01116 } 01117 free(rtp); 01118 }
| int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 153 of file rtp.c.
References ast_rtp::s.
Referenced by __oh323_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().
00154 { 00155 return rtp->s; 00156 }
| void ast_rtp_get_current_formats | ( | struct ast_rtp * | rtp, | |
| int * | astFormats, | |||
| int * | nonAstFormats | |||
| ) |
Definition at line 782 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by process_sdp().
00783 { 00784 int pt; 00785 00786 *astFormats = *nonAstFormats = 0; 00787 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00788 if (rtp->current_RTP_PT[pt].isAstFormat) { 00789 *astFormats |= rtp->current_RTP_PT[pt].code; 00790 } else { 00791 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 00792 } 00793 } 00794 }
| int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 1057 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), ast_rtp_bridge(), do_monitor(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
01058 { 01059 if ((them->sin_family != AF_INET) || 01060 (them->sin_port != rtp->them.sin_port) || 01061 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 01062 them->sin_family = AF_INET; 01063 them->sin_port = rtp->them.sin_port; 01064 them->sin_addr = rtp->them.sin_addr; 01065 return 1; 01066 } 01067 return 0; 01068 }
| void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | us | |||
| ) |
Definition at line 1070 of file rtp.c.
References ast_rtp::us.
Referenced by add_sdp(), external_rtp_create(), handle_message(), and oh323_set_rtp_peer().
| void ast_rtp_init | ( | void | ) |
Definition at line 1913 of file rtp.c.
References ast_cli_register(), ast_rtp_reload(), cli_debug, cli_debug_ip, and cli_no_debug.
Referenced by main().
01914 { 01915 ast_cli_register(&cli_debug); 01916 ast_cli_register(&cli_debug_ip); 01917 ast_cli_register(&cli_no_debug); 01918 ast_rtp_reload(); 01919 }
| int ast_rtp_lookup_code | ( | struct ast_rtp * | rtp, | |
| const int | isAstFormat, | |||
| const int | code | |||
| ) |
Definition at line 822 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit(), and ast_rtp_write().
00822 { 00823 00824 int pt; 00825 00826 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 00827 code == rtp->rtp_lookup_code_cache_code) { 00828 00829 /* Use our cached mapping, to avoid the overhead of the loop below */ 00830 return rtp->rtp_lookup_code_cache_result; 00831 } 00832 00833 /* Check the dynamic list first */ 00834 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00835 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 00836 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00837 rtp->rtp_lookup_code_cache_code = code; 00838 rtp->rtp_lookup_code_cache_result = pt; 00839 return pt; 00840 } 00841 } 00842 00843 /* Then the static list */ 00844 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00845 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 00846 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00847 rtp->rtp_lookup_code_cache_code = code; 00848 rtp->rtp_lookup_code_cache_result = pt; 00849 return pt; 00850 } 00851 } 00852 return -1; 00853 }
| char* ast_rtp_lookup_mime_multiple | ( | char * | buf, | |
| int | size, | |||
| const int | capability, | |||
| const int | isAstFormat | |||
| ) |
Definition at line 867 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, and name.
Referenced by process_sdp().
00868 { 00869 int format; 00870 unsigned len; 00871 char *end = buf; 00872 char *start = buf; 00873 00874 if (!buf || !size) 00875 return NULL; 00876 00877 snprintf(end, size, "0x%x (", capability); 00878 00879 len = strlen(end); 00880 end += len; 00881 size -= len; 00882 start = end; 00883 00884 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 00885 if (capability & format) { 00886 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format); 00887 snprintf(end, size, "%s|", name); 00888 len = strlen(end); 00889 end += len; 00890 size -= len; 00891 } 00892 } 00893 00894 if (start == end) 00895 snprintf(start, size, "nothing)"); 00896 else if (size > 1) 00897 *(end -1) = ')'; 00898 00899 return buf; 00900 }
| char* ast_rtp_lookup_mime_subtype | ( | const int | isAstFormat, | |
| const int | code | |||
| ) |
Definition at line 855 of file rtp.c.
References rtpPayloadType::code, mimeTypes, and payloadType.
Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().
00855 { 00856 00857 int i; 00858 00859 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00860 if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00861 return mimeTypes[i].subtype; 00862 } 00863 } 00864 return ""; 00865 }
| struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
| int | pt | |||
| ) |
Definition at line 803 of file rtp.c.
References MAX_RTP_PT, result, and static_RTP_PT.
Referenced by ast_rtp_read(), and setup_rtp_connection().
00804 { 00805 struct rtpPayloadType result; 00806 00807 result.isAstFormat = result.code = 0; 00808 if (pt < 0 || pt > MAX_RTP_PT) 00809 return result; /* bogus payload type */ 00810 00811 /* Start with the negotiated codecs */ 00812 if (!rtp->rtp_offered_from_local) 00813 result = rtp->current_RTP_PT[pt]; 00814 00815 /* If it doesn't exist, check our static RTP type list, just in case */ 00816 if (!result.code) 00817 result = static_RTP_PT[pt]; 00818 return result; 00819 }
| struct ast_rtp* ast_rtp_new | ( | struct sched_context * | sched, | |
| struct io_context * | io, | |||
| int | rtcpenable, | |||
| int | callbackmode | |||
| ) |
Initializate a RTP session.
| sched | ||
| io | ||
| rtcpenable | ||
| callbackmode |
Definition at line 1029 of file rtp.c.
References ast_rtp_new_with_bindaddr(), io, and sched.
Referenced by start_rtp().
01030 { 01031 struct in_addr ia; 01032 01033 memset(&ia, 0, sizeof(ia)); 01034 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 01035 }
| struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched, | |
| struct io_context * | io, | |||
| int | rtcpenable, | |||
| int | callbackmode, | |||
| struct in_addr | in | |||
| ) |
Initializate a RTP session using an in_addr structure.
This fuction gets called by ast_rtp_new().
| sched | ||
| io | ||
| rtcpenable | ||
| callbackmode | ||
| in |
Definition at line 940 of file rtp.c.
References ast_io_add(), AST_IO_IN, ast_log(), ast_rtcp_new(), ast_rtp_pt_default(), free, io, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, malloc, ast_rtp::rtcp, rtp_socket(), rtpend, rtpread(), rtpstart, ast_rtp::s, ast_rtcp::s, sched, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtp::us, and ast_rtcp::us.
Referenced by ast_rtp_new(), oh323_alloc(), sip_alloc(), and start_rtp().