#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 912 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().
00913 { 00914 struct ast_rtcp *rtcp; 00915 rtcp = malloc(sizeof(struct ast_rtcp)); 00916 if (!rtcp) 00917 return NULL; 00918 memset(rtcp, 0, sizeof(struct ast_rtcp)); 00919 rtcp->s = rtp_socket(); 00920 rtcp->us.sin_family = AF_INET; 00921 if (rtcp->s < 0) { 00922 free(rtcp); 00923 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00924 return NULL; 00925 } 00926 return rtcp; 00927 }
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 }
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 1524 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.
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 }
void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
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_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().
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 }
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 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 }
int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
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 }
void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | us | |||
) |
Definition at line 1057 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 1887 of file rtp.c.
References ast_cli_register(), ast_rtp_reload(), cli_debug, cli_debug_ip, and cli_no_debug.
Referenced by main().
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 }
int ast_rtp_lookup_code | ( | struct ast_rtp * | rtp, | |
const int | isAstFormat, | |||
const int | code | |||
) |
Definition at line 811 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().
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 }
char* ast_rtp_lookup_mime_multiple | ( | char * | buf, | |
int | size, | |||
const int | capability, | |||
const int | isAstFormat | |||
) |
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 }
char* ast_rtp_lookup_mime_subtype | ( | const int | isAstFormat, | |
const int | code | |||
) |
Definition at line 844 of file rtp.c.
References rtpPayloadType::code, mimeTypes, and payloadType.
Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().
00844 { 00845 00846 int i; 00847 00848 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00849 if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00850 return mimeTypes[i].subtype; 00851 } 00852 } 00853 return ""; 00854 }
struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Definition at line 792 of file rtp.c.
References MAX_RTP_PT, result, and static_RTP_PT.
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 }
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 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 }
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 929 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().
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 }
void ast_rtp_offered_from_local | ( | struct ast_rtp * | rtp, | |
int | local | |||
) |
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 }
int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
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 }
void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
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 }
void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Definition at line 708 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by process_sdp().
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 }
void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Definition at line 724 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, ast_rtp::rtp_lookup_code_cache_result, and static_RTP_PT.
Referenced by ast_rtp_new_with_bindaddr().
00725 { 00726 int i; 00727 00728 /* Initialize to default payload types */ 00729 for (i = 0; i < MAX_RTP_PT; ++i) { 00730 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 00731 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 00732 } 00733 00734 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00735 rtp->rtp_lookup_code_cache_code = 0; 00736 rtp->rtp_lookup_code_cache_result = 0; 00737 }
Definition at line 1243 of file rtp.c.
References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_rtp::lastdigitts, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_DEBUG, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), rtp_debug_test_addr(), rtpdebug, ast_rtp::s, ast_frame::samples, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_write().
01244 { 01245 unsigned char *rtpheader; 01246 char iabuf[INET_ADDRSTRLEN]; 01247 int hdrlen = 12; 01248 int res; 01249 unsigned int ms; 01250 int pred; 01251 int mark = 0; 01252 01253 ms = calc_txstamp(rtp, &f->delivery); 01254 /* Default prediction */ 01255 if (f->subclass < AST_FORMAT_MAX_AUDIO) { 01256 pred = rtp->lastts + f->samples; 01257 01258 /* Re-calculate last TS */ 01259 rtp->lastts = rtp->lastts + ms * 8; 01260 if (ast_tvzero(f->delivery)) { 01261 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 01262 and if so, go with our prediction */ 01263 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 01264 rtp->lastts = pred; 01265 else { 01266 if (option_debug > 2) 01267 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 01268 mark = 1; 01269 } 01270 } 01271 } else { 01272 mark = f->subclass & 0x1; 01273 pred = rtp->lastovidtimestamp + f->samples; 01274 /* Re-calculate last TS */ 01275 rtp->lastts = rtp->lastts + ms * 90; 01276 /* If it's close to our prediction, go for it */ 01277 if (ast_tvzero(f->delivery)) { 01278 if (abs(rtp->lastts - pred) < 7200) { 01279 rtp->lastts = pred; 01280 rtp->lastovidtimestamp += f->samples; 01281 } else { 01282 if (option_debug > 2) 01283 ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples); 01284 rtp->lastovidtimestamp = rtp->lastts; 01285 } 01286 } 01287 } 01288 /* If the timestamp for non-digit packets has moved beyond the timestamp 01289 for digits, update the digit timestamp. 01290 */ 01291 if (rtp->lastts > rtp->lastdigitts) 01292 rtp->lastdigitts = rtp->lastts; 01293 01294 /* Get a pointer to the header */ 01295 rtpheader = (unsigned char *)(f->data - hdrlen); 01296 01297 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 01298 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 01299 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 01300 01301 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01302 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 01303 if (res <0) { 01304 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 01305 ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 01306 } else if ((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) { 01307 /* Only give this error message once if we are not RTP debugging */ 01308 if (option_debug || rtpdebug) 01309 ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 01310 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 01311 } 01312 } 01313 01314 if(rtp_debug_test_addr(&rtp->them)) 01315 ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n" 01316 , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 01317 } 01318 01319 rtp->seqno++; 01320 01321 return 0; 01322 }
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 }
void ast_rtp_reload | ( | void | ) |
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(), ast_rtp_init(), and main().
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 }
void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
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 }
int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
int | level | |||
) |
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 }
int ast_rtp_senddigit | ( | struct ast_rtp * | rtp, | |
char | digit | |||
) |
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 }
void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
ast_rtp_callback | callback | |||
) |
Definition at line 170 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00171 { 00172 rtp->callback = callback; 00173 }
void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
void * | data | |||
) |
Definition at line 165 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00166 { 00167 rtp->data = data; 00168 }
void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
int | pt | |||
) |
Definition at line 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 }
void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
struct sockaddr_in * | them | |||
) |
Definition at line 1033 of file rtp.c.
References ast_rtp::rtcp, ast_rtp::rxseqno, ast_rtp::them, and ast_rtcp::them.
Referenced by handle_message(), process_sdp(), and setup_rtp_connection().
01034 { 01035 rtp->them.sin_port = them->sin_port; 01036 rtp->them.sin_addr = them->sin_addr; 01037 if (rtp->rtcp) { 01038 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 01039 rtp->rtcp->them.sin_addr = them->sin_addr; 01040 } 01041 rtp->rxseqno = 0; 01042 }
void ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
int | pt, | |||
char * | mimeType, | |||
char * | mimeSubtype | |||
) |
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 }
void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
int | nat | |||
) |
Definition at line 175 of file rtp.c.
References ast_rtp::nat.
Referenced by check_user_full(), create_addr(), create_addr_from_peer(), oh323_request(), oh323_rtp_read(), sip_alloc(), and start_rtp().
int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
int | tos | |||
) |
Definition at line 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 }
void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 1062 of file rtp.c.
References ast_rtp::rtcp, ast_rtp::them, and ast_rtcp::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 }
static void calc_rxstamp | ( | struct timeval * | tv, | |
struct ast_rtp * | rtp, | |||
unsigned int | timestamp, | |||
int | mark | |||
) | [static] |
Definition at line 415 of file rtp.c.
References ast_tvadd(), ast_tvsub(), and ast_rtp::rxcore.
Referenced by ast_rtp_read(), and schedule_delivery().
00416 { 00417 struct timeval ts = ast_samp2tv( timestamp, 8000); 00418 if (ast_tvzero(rtp->rxcore) || mark) { 00419 rtp->rxcore = ast_tvsub(ast_tvnow(), ts); 00420 /* Round to 20ms for nice, pretty timestamps */ 00421 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 20000; 00422 } 00423 *tv = ast_tvadd(rtp->rxcore, ts); 00424 }
static unsigned int calc_txstamp | ( | struct ast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 1107 of file rtp.c.
References ast_rtp::txcore.
Referenced by ast_rtp_raw_write().
01108 { 01109 struct timeval t; 01110 long ms; 01111 if (ast_tvzero(rtp->txcore)) { 01112 rtp->txcore = ast_tvnow(); 01113 /* Round to 20ms for nice, pretty timestamps */ 01114 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 01115 } 01116 /* Use previous txcore if available */ 01117 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 01118 ms = ast_tvdiff_ms(t, rtp->txcore); 01119 if (ms < 0) 01120 ms = 0; 01121 /* Use what we just got for next time */ 01122 rtp->txcore = t; 01123 return (unsigned int) ms; 01124 }
static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1507 of file rtp.c.
References ast_rtp_protocol::next, protos, ast_channel::type, and ast_rtp_protocol::type.
Referenced by ast_rtp_bridge().
01508 { 01509 struct ast_rtp_protocol *cur; 01510 01511 cur = protos; 01512 while(cur) { 01513 if (cur->type == chan->type) { 01514 return cur; 01515 } 01516 cur = cur->next; 01517 } 01518 return NULL; 01519 }
static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 224 of file rtp.c.
References ast_rtp::dtmfcount, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00225 { 00226 unsigned int event; 00227 char resp = 0; 00228 struct ast_frame *f = NULL; 00229 event = ntohl(*((unsigned int *)(data))); 00230 event &= 0x001F; 00231 #if 0 00232 printf("Cisco Digit: %08x (len = %d)\n", event, len); 00233 #endif 00234 if (event < 10) { 00235 resp = '0' + event; 00236 } else if (event < 11) { 00237 resp = '*'; 00238 } else if (event < 12) { 00239 resp = '#'; 00240 } else if (event < 16) { 00241 resp = 'A' + (event - 12); 00242 } else if (event < 17) { 00243 resp = 'X'; 00244 } 00245 if (rtp->resp && (rtp->resp != resp)) { 00246 f = send_dtmf(rtp); 00247 } 00248 rtp->resp = resp; 00249 rtp->dtmfcount = dtmftimeout; 00250 return f; 00251 }
static struct ast_frame* process_rfc2833 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len, | |||
unsigned int | seqno | |||
) | [static] |
Process RTP DTMF and events according to RFC 2833.
RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
rtp | ||
data | ||
len | ||
seqno |
Definition at line 264 of file rtp.c.
References ast_log(), ast_rtp::dtmfcount, ast_rtp::dtmfduration, ast_rtp::lasteventendseqn, LOG_DEBUG, ast_rtp::resp, and send_dtmf().
Referenced by ast_rtp_read().
00265 { 00266 unsigned int event; 00267 unsigned int event_end; 00268 unsigned int duration; 00269 char resp = 0; 00270 struct ast_frame *f = NULL; 00271 event = ntohl(*((unsigned int *)(data))); 00272 event >>= 24; 00273 event_end = ntohl(*((unsigned int *)(data))); 00274 event_end <<= 8; 00275 event_end >>= 24; 00276 duration = ntohl(*((unsigned int *)(data))); 00277 duration &= 0xFFFF; 00278 if (rtpdebug) 00279 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); 00280 if (event < 10) { 00281 resp = '0' + event; 00282 } else if (event < 11) { 00283 resp = '*'; 00284 } else if (event < 12) { 00285 resp = '#'; 00286 } else if (event < 16) { 00287 resp = 'A' + (event - 12); 00288 } else if (event < 17) { /* Event 16: Hook flash */ 00289 resp = 'X'; 00290 } 00291 if (rtp->resp && (rtp->resp != resp)) { 00292 f = send_dtmf(rtp); 00293 } else if(event_end & 0x80) { 00294 if (rtp->resp) { 00295 if(rtp->lasteventendseqn != seqno) { 00296 f = send_dtmf(rtp); 00297 rtp->lasteventendseqn = seqno; 00298 } 00299 rtp->resp = 0; 00300 } 00301 resp = 0; 00302 duration = 0; 00303 } else if (rtp->resp && rtp->dtmfduration && (duration < rtp->dtmfduration)) { 00304 f = send_dtmf(rtp); 00305 } 00306 if (!(event_end & 0x80)) 00307 rtp->resp = resp; 00308 rtp->dtmfcount = dtmftimeout; 00309 rtp->dtmfduration = duration; 00310 return f; 00311 }
static struct ast_frame* process_rfc3389 | ( | struct ast_rtp * | rtp, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Process Comfort Noise RTP.
This is incomplete at the moment.
Definition at line 319 of file rtp.c.
References AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, FLAG_3389_WARNING, ast_frame::frametype, ast_rtp::lastrxformat, LOG_DEBUG, LOG_NOTICE, ast_frame::offset, ast_rtp::rawdata, ast_frame::samples, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read().
00320 { 00321 struct ast_frame *f = NULL; 00322 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't 00323 totally help us out becuase we don't have an engine to keep it going and we are not 00324 guaranteed to have it every 20ms or anything */ 00325 if (rtpdebug) 00326 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len); 00327 00328 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) { 00329 char iabuf[INET_ADDRSTRLEN]; 00330 00331 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n", 00332 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr)); 00333 ast_set_flag(rtp, FLAG_3389_WARNING); 00334 } 00335 00336 /* Must have at least one byte */ 00337 if (!len) 00338 return NULL; 00339 if (len < 24) { 00340 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET; 00341 rtp->f.datalen = len - 1; 00342 rtp->f.offset = AST_FRIENDLY_OFFSET; 00343 memcpy(rtp->f.data, data + 1, len - 1); 00344 } else { 00345 rtp->f.data = NULL; 00346 rtp->f.offset = 0; 00347 rtp->f.datalen = 0; 00348 } 00349 rtp->f.frametype = AST_FRAME_CNG; 00350 rtp->f.subclass = data[0] & 0x7f; 00351 rtp->f.datalen = len - 1; 00352 rtp->f.samples = 0; 00353 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0; 00354 f = &rtp->f; 00355 return f; 00356 }
static int rtp_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 211 of file rtp.c.
Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), and ast_rtp_senddigit().
00212 { 00213 if (rtpdebug == 0) 00214 return 0; 00215 if (rtpdebugaddr.sin_addr.s_addr) { 00216 if (((ntohs(rtpdebugaddr.sin_port) != 0) 00217 && (rtpdebugaddr.sin_port != addr->sin_port)) 00218 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00219 return 0; 00220 } 00221 return 1; 00222 }
static int rtp_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1792 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtp_do_debug_ip(), rtpdebug, and rtpdebugaddr.
01793 { 01794 if(argc != 2) { 01795 if(argc != 4) 01796 return RESULT_SHOWUSAGE; 01797 return rtp_do_debug_ip(fd, argc, argv); 01798 } 01799 rtpdebug = 1; 01800 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr)); 01801 ast_cli(fd, "RTP Debugging Enabled\n"); 01802 return RESULT_SUCCESS; 01803 }
static int rtp_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1761 of file rtp.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, rtpdebug, and rtpdebugaddr.
Referenced by rtp_do_debug().
01762 { 01763 struct hostent *hp; 01764 struct ast_hostent ahp; 01765 char iabuf[INET_ADDRSTRLEN]; 01766 int port = 0; 01767 char *p, *arg; 01768 01769 if (argc != 4) 01770 return RESULT_SHOWUSAGE; 01771 arg = argv[3]; 01772 p = strstr(arg, ":"); 01773 if (p) { 01774 *p = '\0'; 01775 p++; 01776 port = atoi(p); 01777 } 01778 hp = ast_gethostbyname(arg, &ahp); 01779 if (hp == NULL) 01780 return RESULT_SHOWUSAGE; 01781 rtpdebugaddr.sin_family = AF_INET; 01782 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr)); 01783 rtpdebugaddr.sin_port = htons(port); 01784 if (port == 0) 01785 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr)); 01786 else 01787 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr), port); 01788 rtpdebug = 1; 01789 return RESULT_SUCCESS; 01790 }
static int rtp_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1805 of file rtp.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtpdebug.
01806 { 01807 if(argc !=3) 01808 return RESULT_SHOWUSAGE; 01809 rtpdebug = 0; 01810 ast_cli(fd,"RTP Debugging Disabled\n"); 01811 return RESULT_SUCCESS; 01812 }
static int rtp_socket | ( | void | ) | [static] |
Definition at line 891 of file rtp.c.
References s.
Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().
00892 { 00893 int s; 00894 long flags; 00895 s = socket(AF_INET, SOCK_DGRAM, 0); 00896 if (s > -1) { 00897 flags = fcntl(s, F_GETFL); 00898 fcntl(s, F_SETFL, flags | O_NONBLOCK); 00899 #ifdef SO_NO_CHECK 00900 if (nochecksums) 00901 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00902 #endif 00903 } 00904 return s; 00905 }
static int rtpread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 358 of file rtp.c.
References ast_rtp_read(), ast_rtp::callback, and ast_frame::data.
Referenced by ast_rtp_new_with_bindaddr().
00359 { 00360 struct ast_rtp *rtp = cbdata; 00361 struct ast_frame *f; 00362 f = ast_rtp_read(rtp); 00363 if (f) { 00364 if (rtp->callback) 00365 rtp->callback(rtp, f, rtp->data); 00366 } 00367 return 1; 00368 }
Definition at line 180 of file rtp.c.
References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), ast_frame::datalen, ast_rtp::dtmfduration, ast_rtp::dtmfmute, ast_rtp::f, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, option_debug, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.
Referenced by ast_rtp_read(), process_cisco_dtmf(), and process_rfc2833().
00181 { 00182 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00183 char iabuf[INET_ADDRSTRLEN]; 00184 00185 if (ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) { 00186 if (option_debug) 00187 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr)); 00188 rtp->resp = 0; 00189 rtp->dtmfduration = 0; 00190 return &null_frame; 00191 } 00192 if (option_debug) 00193 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr)); 00194 if (rtp->resp == 'X') { 00195 rtp->f.frametype = AST_FRAME_CONTROL; 00196 rtp->f.subclass = AST_CONTROL_FLASH; 00197 } else { 00198 rtp->f.frametype = AST_FRAME_DTMF; 00199 rtp->f.subclass = rtp->resp; 00200 } 00201 rtp->f.datalen = 0; 00202 rtp->f.samples = 0; 00203 rtp->f.mallocd = 0; 00204 rtp->f.src = "RTP"; 00205 rtp->resp = 0; 00206 rtp->dtmfduration = 0; 00207 return &rtp->f; 00208 00209 }
struct ast_cli_entry cli_debug [static] |
Initial value:
{{ "rtp", "debug", NULL } , rtp_do_debug, "Enable RTP debugging", debug_usage }
Definition at line 1825 of file rtp.c.
Referenced by ast_rtp_init(), load_module(), and unload_module().
struct ast_cli_entry cli_debug_ip [static] |
Initial value:
{{ "rtp", "debug", "ip", NULL } , rtp_do_debug, "Enable RTP debugging on IP", debug_usage }
Definition at line 1822 of file rtp.c.
Referenced by ast_rtp_init().
struct ast_cli_entry cli_no_debug [static] |
Initial value:
{{ "rtp", "no", "debug", NULL } , rtp_no_debug, "Disable RTP debugging", no_debug_usage }
Definition at line 1828 of file rtp.c.
Referenced by ast_rtp_init(), load_module(), and unload_module().
char debug_usage[] [static] |
int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static] |
struct { ... } mimeTypes[] [static] |
Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().
char no_debug_usage[] [static] |
struct rtpPayloadType payloadType |
struct ast_rtp_protocol* protos = NULL [static] |
Definition at line 151 of file rtp.c.
Referenced by ast_rtp_proto_register(), ast_rtp_proto_unregister(), and get_proto().
int rtpdebug = 0 [static] |
Definition at line 67 of file rtp.c.
Referenced by ast_rtp_raw_write(), rtp_do_debug(), rtp_do_debug_ip(), and rtp_no_debug().
struct sockaddr_in rtpdebugaddr [static] |
int rtpend = 0 [static] |
Definition at line 66 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr(), and ast_rtp_reload().
int rtpstart = 0 [static] |
Definition at line 65 of file rtp.c.
Referenced by ast_rtp_new_with_bindaddr(), and ast_rtp_reload().
struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static] |
Definition at line 679 of file rtp.c.
Referenced by ast_rtp_lookup_pt(), ast_rtp_pt_default(), and ast_rtp_set_m_type().
char* subtype |
char* type |
Definition at line 652 of file rtp.c.
Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_filename(), check_header(), find_subscription_type(), load_module(), mgcp_new(), misdn_cfg_get(), misdn_cfg_get_config_string(), schedule_delivery(), subscription_type2str(), and yyparse().