[asterisk-commits] file: branch file/rtp_engine r129106 - in /team/file/rtp_engine: channels/ in...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Jul 8 12:34:44 CDT 2008
Author: file
Date: Tue Jul 8 12:34:43 2008
New Revision: 129106
URL: http://svn.digium.com/view/asterisk?view=rev&rev=129106
Log:
Eep! Commit stuff so far. This includes some API changes to the RTP engine stuff plus about half of the changes required for chan_sip, and the basic core of the RTP stack converted over.
Modified:
team/file/rtp_engine/channels/chan_sip.c
team/file/rtp_engine/include/asterisk/rtp_engine.h
team/file/rtp_engine/main/rtp_engine.c
team/file/rtp_engine/res/res_rtp_asterisk.c
Modified: team/file/rtp_engine/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/channels/chan_sip.c?view=diff&rev=129106&r1=129105&r2=129106
==============================================================================
--- team/file/rtp_engine/channels/chan_sip.c (original)
+++ team/file/rtp_engine/channels/chan_sip.c Tue Jul 8 12:34:43 2008
@@ -156,7 +156,7 @@
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
-#include "asterisk/rtp.h"
+#include "asterisk/rtp_engine.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
@@ -1357,9 +1357,9 @@
struct sip_peer *relatedpeer; /*!< If this dialog is related to a peer, which one
Used in peerpoke, mwi subscriptions */
struct sip_registry *registry; /*!< If this is a REGISTER dialog, to which registry */
- struct ast_rtp *rtp; /*!< RTP Session */
- struct ast_rtp *vrtp; /*!< Video RTP session */
- struct ast_rtp *trtp; /*!< Text RTP session */
+ struct ast_rtp_instance *rtp; /*!< RTP Session */
+ struct ast_rtp_instance *vrtp; /*!< Video RTP session */
+ struct ast_rtp_instance *trtp; /*!< Text RTP session */
struct sip_pkt *packets; /*!< Packets scheduled for re-transmission */
struct sip_history_head *history; /*!< History of this SIP dialog */
size_t history_entries; /*!< Number of entires in the history */
@@ -2144,14 +2144,6 @@
static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
-/*----- RTP interface functions */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
-static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static int sip_get_codec(struct ast_channel *chan);
-static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect);
-
/*------ T38 Support --------- */
static int sip_handle_t38_reinvite(struct ast_channel *chan, struct sip_pvt *pvt, int reinvite);
static int transmit_response_with_t38_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
@@ -2195,8 +2187,8 @@
.fixup = sip_fixup, /* called with chan locked */
.send_digit_begin = sip_senddigit_begin, /* called with chan unlocked */
.send_digit_end = sip_senddigit_end,
- .bridge = ast_rtp_bridge, /* XXX chan unlocked ? */
- .early_bridge = ast_rtp_early_bridge,
+// .bridge = ast_rtp_bridge, /* XXX chan unlocked ? */
+// .early_bridge = ast_rtp_early_bridge,
.send_text = sip_sendtext, /* called with chan locked */
.func_channel_read = acf_channel_read,
.queryoption = sip_queryoption,
@@ -2268,18 +2260,6 @@
return cur->x;
return errorvalue;
}
-
-
-/*! \brief Interface structure with callbacks used to connect to RTP module */
-static struct ast_rtp_protocol sip_rtp = {
- .type = "SIP",
- .get_rtp_info = sip_get_rtp_peer,
- .get_vrtp_info = sip_get_vrtp_peer,
- .get_trtp_info = sip_get_trtp_peer,
- .set_rtp_peer = sip_set_rtp_peer,
- .get_codec = sip_get_codec,
-};
-
/*! \brief SIP TCP connection handler */
static void *sip_tcp_worker_fn(void *data)
@@ -4051,11 +4031,11 @@
if (p->rtp) {
ast_debug(1, "Setting NAT on RTP to %s\n", mode);
- ast_rtp_setnat(p->rtp, natflags);
+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, natflags);
}
if (p->vrtp) {
ast_debug(1, "Setting NAT on VRTP to %s\n", mode);
- ast_rtp_setnat(p->vrtp, natflags);
+ ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_NAT, natflags);
}
if (p->udptl) {
ast_debug(1, "Setting NAT on UDPTL to %s\n", mode);
@@ -4063,7 +4043,7 @@
}
if (p->trtp) {
ast_debug(1, "Setting NAT on TRTP to %s\n", mode);
- ast_rtp_setnat(p->trtp, natflags);
+ ast_rtp_instance_set_prop(p->trtp, AST_RTP_PROPERTY_NAT, natflags);
}
}
@@ -4149,11 +4129,11 @@
ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
dialog->capability = peer->capability;
if ((!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) || !(dialog->capability & AST_FORMAT_VIDEO_MASK)) && dialog->vrtp) {
- ast_rtp_destroy(dialog->vrtp);
+ ast_rtp_instance_destroy(dialog->vrtp);
dialog->vrtp = NULL;
}
if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) {
- ast_rtp_destroy(dialog->trtp);
+ ast_rtp_instance_destroy(dialog->trtp);
dialog->trtp = NULL;
}
dialog->prefs = peer->prefs;
@@ -4168,28 +4148,24 @@
do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
if (dialog->rtp) { /* Audio */
- ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
- ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
- ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
- ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
- ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
+ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
+ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+// ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
+// ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
+// ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
/* Set Frame packetization */
- ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
+ ast_rtp_instance_packetization_set(dialog->rtp, &dialog->prefs);
dialog->autoframing = peer->autoframing;
}
if (dialog->vrtp) { /* Video */
- ast_rtp_setdtmf(dialog->vrtp, 0);
- ast_rtp_setdtmfcompensate(dialog->vrtp, 0);
- ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout);
- ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout);
- ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive);
+// ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout);
+// ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout);
+// ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive);
}
if (dialog->trtp) { /* Realtime text */
- ast_rtp_setdtmf(dialog->trtp, 0);
- ast_rtp_setdtmfcompensate(dialog->trtp, 0);
- ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout);
- ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout);
- ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive);
+// ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout);
+// ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout);
+// ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive);
}
ast_string_field_set(dialog, peername, peer->name);
@@ -4535,15 +4511,13 @@
p->notify_headers = NULL;
}
if (p->rtp) {
- ast_rtp_destroy(p->rtp);
+ ast_rtp_instance_destroy(p->rtp);
}
if (p->vrtp) {
- ast_rtp_destroy(p->vrtp);
+ ast_rtp_instance_destroy(p->vrtp);
}
if (p->trtp) {
- while (ast_rtp_get_bridged(p->trtp))
- usleep(1);
- ast_rtp_destroy(p->trtp);
+ ast_rtp_instance_destroy(p->trtp);
}
if (p->udptl)
ast_udptl_destroy(p->udptl);
@@ -4880,7 +4854,7 @@
struct sip_pvt *p = ast->tech_pvt;
int needcancel = FALSE;
int needdestroy = 0;
- struct ast_channel *oldowner = ast;
+// struct ast_channel *oldowner = ast;
if (!p) {
ast_debug(1, "Asked to hangup channel that was not connected\n");
@@ -5004,43 +4978,11 @@
}
if (!p->pendinginvite) {
- struct ast_channel *bridge = ast_bridged_channel(oldowner);
- char *audioqos = "";
- char *videoqos = "";
- char *textqos = "";
-
- if (p->rtp)
- ast_rtp_set_vars(oldowner, p->rtp);
-
- if (bridge) {
- struct sip_pvt *q = bridge->tech_pvt;
-
- if (IS_SIP_TECH(bridge->tech) && q->rtp)
- ast_rtp_set_vars(bridge, q->rtp);
- }
-
- if (p->vrtp)
- videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY);
- if (p->trtp)
- textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY);
+// struct ast_channel *bridge = ast_bridged_channel(oldowner);
+
/* Send a hangup */
transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
- /* Get RTCP quality before end of call */
- if (p->do_history) {
- if (p->rtp)
- append_history(p, "RTCPaudio", "Quality:%s", audioqos);
- if (p->vrtp)
- append_history(p, "RTCPvideo", "Quality:%s", videoqos);
- if (p->trtp)
- append_history(p, "RTCPtext", "Quality:%s", textqos);
- }
- if (p->rtp && oldowner)
- pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos);
- if (p->vrtp && oldowner)
- pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos);
- if (p->trtp && oldowner)
- pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos);
} else {
/* Note we will need a BYE when this all settles out
but we can't send one while we have "INVITE" outstanding. */
@@ -5098,7 +5040,7 @@
change_t38_state(p, T38_ENABLED);
res = transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
} else {
- ast_rtp_new_source(p->rtp);
+ ast_rtp_instance_new_source(p->rtp);
res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE);
}
}
@@ -5133,12 +5075,12 @@
if ((ast->_state != AST_STATE_UP) &&
!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
!ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
- ast_rtp_new_source(p->rtp);
+ ast_rtp_instance_new_source(p->rtp);
transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
}
p->lastrtptx = time(NULL);
- res = ast_rtp_write(p->rtp, frame);
+ res = ast_rtp_instance_write(p->rtp, frame);
}
sip_pvt_unlock(p);
}
@@ -5155,7 +5097,7 @@
ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
}
p->lastrtptx = time(NULL);
- res = ast_rtp_write(p->vrtp, frame);
+ res = ast_rtp_instance_write(p->vrtp, frame);
}
sip_pvt_unlock(p);
}
@@ -5164,7 +5106,7 @@
if (p) {
sip_pvt_lock(p);
if (p->red) {
- red_buffer_t140(p->trtp, frame);
+// red_buffer_t140(p->trtp, frame);
} else {
if (p->trtp) {
/* Activate text early media */
@@ -5175,7 +5117,7 @@
ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
}
p->lastrtptx = time(NULL);
- res = ast_rtp_write(p->trtp, frame);
+// res = ast_rtp_write(p->trtp, frame);
}
}
sip_pvt_unlock(p);
@@ -5238,7 +5180,7 @@
redirect of both channels). Note that a channel can not be masqueraded *into*
a native bridge. So there is no danger that this breaks a native bridge that
should stay up. */
- sip_set_rtp_peer(newchan, NULL, NULL, 0, 0, 0);
+// sip_set_rtp_peer(newchan, NULL, NULL, 0, 0, 0);
ret = 0;
}
ast_debug(3, "SIP Fixup: New owner for dialogue %s: %s (Old parent: %s)\n", p->callid, p->owner->name, oldchan->name);
@@ -5259,7 +5201,7 @@
break;
case SIP_DTMF_RFC2833:
if (p->rtp)
- ast_rtp_senddigit_begin(p->rtp, digit);
+ ast_rtp_instance_dtmf_begin(p->rtp, digit);
break;
default:
break;
@@ -5284,7 +5226,7 @@
break;
case SIP_DTMF_RFC2833:
if (p->rtp)
- ast_rtp_senddigit_end(p->rtp, digit);
+ ast_rtp_instance_dtmf_end(p->rtp, digit);
break;
case SIP_DTMF_INBAND:
res = -1; /* Tell Asterisk to stop inband indications */
@@ -5382,11 +5324,11 @@
res = -1;
break;
case AST_CONTROL_HOLD:
- ast_rtp_new_source(p->rtp);
+ ast_rtp_instance_new_source(p->rtp);
ast_moh_start(ast, data, p->mohinterpret);
break;
case AST_CONTROL_UNHOLD:
- ast_rtp_new_source(p->rtp);
+ ast_rtp_instance_new_source(p->rtp);
ast_moh_stop(ast);
break;
case AST_CONTROL_VIDUPDATE: /* Request a video frame update */
@@ -5419,7 +5361,7 @@
}
break;
case AST_CONTROL_SRCUPDATE:
- ast_rtp_new_source(p->rtp);
+ ast_rtp_instance_new_source(p->rtp);
break;
case -1:
res = -1;
@@ -11794,11 +11736,11 @@
p->jointcapability &= p->peercapability;
p->maxcallbitrate = peer->maxcallbitrate;
if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) || !(p->capability & AST_FORMAT_VIDEO_MASK)) && p->vrtp) {
- ast_rtp_destroy(p->vrtp);
+ ast_rtp_instance_destroy(p->vrtp);
p->vrtp = NULL;
}
if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) || !(p->capability & AST_FORMAT_TEXT_MASK)) && p->trtp) {
- ast_rtp_destroy(p->trtp);
+ ast_rtp_instance_destroy(p->trtp);
p->trtp = NULL;
}
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
@@ -21658,157 +21600,6 @@
}
}
-
-/*! \brief Returns null if we can't reinvite audio (part of RTP interface) */
-static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-{
- struct sip_pvt *p = NULL;
- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
-
- if (!(p = chan->tech_pvt))
- return AST_RTP_GET_FAILED;
-
- sip_pvt_lock(p);
- if (!(p->rtp)) {
- sip_pvt_unlock(p);
- return AST_RTP_GET_FAILED;
- }
-
- *rtp = p->rtp;
-
- if (ast_rtp_getnat(*rtp) && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT))
- res = AST_RTP_TRY_PARTIAL;
- else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
- res = AST_RTP_TRY_NATIVE;
- else if (ast_test_flag(&global_jbconf, AST_JB_FORCED))
- res = AST_RTP_GET_FAILED;
-
- sip_pvt_unlock(p);
-
- return res;
-}
-
-/*! \brief Returns null if we can't reinvite video (part of RTP interface) */
-static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-{
- struct sip_pvt *p = NULL;
- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
-
- if (!(p = chan->tech_pvt))
- return AST_RTP_GET_FAILED;
-
- sip_pvt_lock(p);
- if (!(p->vrtp)) {
- sip_pvt_unlock(p);
- return AST_RTP_GET_FAILED;
- }
-
- *rtp = p->vrtp;
-
- if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
- res = AST_RTP_TRY_NATIVE;
-
- sip_pvt_unlock(p);
-
- return res;
-}
-
-/*! \brief Returns null if we can't reinvite text (part of RTP interface) */
-static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-{
- struct sip_pvt *p = NULL;
- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
-
- if (!(p = chan->tech_pvt))
- return AST_RTP_GET_FAILED;
-
- sip_pvt_lock(p);
- if (!(p->trtp)) {
- sip_pvt_unlock(p);
- return AST_RTP_GET_FAILED;
- }
-
- *rtp = p->trtp;
-
- if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
- res = AST_RTP_TRY_NATIVE;
-
- sip_pvt_unlock(p);
-
- return res;
-}
-
-/*! \brief Set the RTP peer for this call */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
-{
- struct sip_pvt *p;
- int changed = 0;
-
- p = chan->tech_pvt;
- if (!p)
- return -1;
-
- /* Disable early RTP bridge */
- if (chan->_state != AST_STATE_UP && !global_directrtpsetup) /* We are in early state */
- return 0;
-
- sip_pvt_lock(p);
- if (p->alreadygone) {
- /* If we're destroyed, don't bother */
- sip_pvt_unlock(p);
- return 0;
- }
-
- /* if this peer cannot handle reinvites of the media stream to devices
- that are known to be behind a NAT, then stop the process now
- */
- if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) {
- sip_pvt_unlock(p);
- return 0;
- }
-
- if (rtp) {
- changed |= ast_rtp_get_peer(rtp, &p->redirip);
- } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) {
- memset(&p->redirip, 0, sizeof(p->redirip));
- changed = 1;
- }
- if (vrtp) {
- changed |= ast_rtp_get_peer(vrtp, &p->vredirip);
- } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
- memset(&p->vredirip, 0, sizeof(p->vredirip));
- changed = 1;
- }
- if (trtp) {
- changed |= ast_rtp_get_peer(trtp, &p->tredirip);
- } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) {
- memset(&p->tredirip, 0, sizeof(p->tredirip));
- changed = 1;
- }
- if (codecs && (p->redircodecs != codecs)) {
- p->redircodecs = codecs;
- changed = 1;
- }
- if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
- if (chan->_state != AST_STATE_UP) { /* We are in early state */
- if (p->do_history)
- append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
- ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
- } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */
- ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
- transmit_reinvite_with_sdp(p, FALSE, FALSE);
- } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
- ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
- /* We have a pending Invite. Send re-invite when we're done with the invite */
- ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
- }
- }
- /* Reset lastrtprx timer */
- p->lastrtprx = p->lastrtptx = time(NULL);
- sip_pvt_unlock(p);
- return 0;
-}
-
static char *synopsis_dtmfmode = "Change the dtmfmode for a SIP call";
static char *descrip_dtmfmode = " SIPDtmfMode(inband|info|rfc2833): Changes the dtmfmode for a SIP call\n";
static char *app_dtmfmode = "SIPDtmfMode";
@@ -22166,9 +21957,6 @@
/* Register all CLI functions for SIP */
ast_cli_register_multiple(cli_sip, sizeof(cli_sip)/ sizeof(struct ast_cli_entry));
- /* Tell the RTP subdriver that we're here */
- ast_rtp_proto_register(&sip_rtp);
-
/* Tell the UDPTL subdriver that we're here */
ast_udptl_proto_register(&sip_udptl);
@@ -22239,9 +22027,6 @@
/* Unregister CLI commands */
ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry));
- /* Disconnect from the RTP subsystem */
- ast_rtp_proto_unregister(&sip_rtp);
-
/* Disconnect from UDPTL */
ast_udptl_proto_unregister(&sip_udptl);
Modified: team/file/rtp_engine/include/asterisk/rtp_engine.h
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/include/asterisk/rtp_engine.h?view=diff&rev=129106&r1=129105&r2=129106
==============================================================================
--- team/file/rtp_engine/include/asterisk/rtp_engine.h (original)
+++ team/file/rtp_engine/include/asterisk/rtp_engine.h Tue Jul 8 12:34:43 2008
@@ -39,11 +39,18 @@
AST_RTP_PROPERTY_DTMF_COMPENSATE, /*!< Expect unreliable DTMF from remote party */
AST_RTP_PROPERTY_STUN, /*!< Use STUN */
AST_RTP_PROPERTY_RED, /*!< Use RED */
+ AST_RTP_PROPERTY_RTCP, /*!< Use RTCP */
AST_RTP_PROPERTY_MAX, /*!< Maximum number of properties supported */
};
enum ast_rtp_options {
AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
+};
+
+enum ast_rtp_glue_result {
+ AST_RTP_GLUE_RESULT_FORBID = 0,
+ AST_RTP_GLUE_RESULT_DIRECT,
+ AST_RTP_GLUE_RESULT_LOCAL,
};
/* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
@@ -59,6 +66,9 @@
struct ast_rtp_payload_type {
int isAstFormat; /*!< Is this an Asterisk value? */
int code; /*!< Actual internal value */
+};
+
+struct ast_rtp_instance_stats {
};
struct ast_rtp_engine {
@@ -73,7 +83,9 @@
void (*prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value); /*!< Callback for when an RTP property is set */
void (*payload_set)(struct ast_rtp_instance *instance, int payload, int AstFormat, int format); /*!< Callback for when a payload is set */
void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref); /*!< Callback for setting codec packetization preferences */
+ int (*get_stats)(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats); /*!< Callback for retrieving statistics about the session */
struct ast_frame *(*read)(struct ast_rtp_instance *instance); /*!< Callback for reading a frame in */
+ enum ast_bridge_result (*bridge)(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1); /*!< Callback for bridging two RTP instances together */
AST_RWLIST_ENTRY(ast_rtp_engine) entry; /*!< Linked list information */
};
@@ -116,11 +128,12 @@
/*! \brief Create a new RTP instance
*
* \param engine_name Name of the engine to use for the RTP instance
+ * \param glue The glue to use when bridging
*
* \retval non-NULL success
* \retval NULL failure
*/
-struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name);
+struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct ast_rtp_glue *glue);
/*! \brief Destroy an RTP instance
*
Modified: team/file/rtp_engine/main/rtp_engine.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/main/rtp_engine.c?view=diff&rev=129106&r1=129105&r2=129106
==============================================================================
--- team/file/rtp_engine/main/rtp_engine.c (original)
+++ team/file/rtp_engine/main/rtp_engine.c Tue Jul 8 12:34:43 2008
@@ -180,7 +180,7 @@
return current_engine ? 0 : -1;
}
-struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name)
+struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct ast_rtp_glue *glue)
{
struct ast_rtp_instance *instance = NULL;
struct ast_rtp_engine *engine = NULL;
@@ -215,6 +215,7 @@
return NULL;
}
instance->engine = engine;
+ instance->glue = glue;
/* And pass it off to the engine to setup */
if (instance->engine->new(instance)) {
Modified: team/file/rtp_engine/res/res_rtp_asterisk.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/res/res_rtp_asterisk.c?view=diff&rev=129106&r1=129105&r2=129106
==============================================================================
--- team/file/rtp_engine/res/res_rtp_asterisk.c (original)
+++ team/file/rtp_engine/res/res_rtp_asterisk.c Tue Jul 8 12:34:43 2008
@@ -35,7 +35,6 @@
#include <fcntl.h>
#include <math.h>
-#include "asterisk/rtp_engine.h"
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
@@ -48,6 +47,8 @@
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
+#include "asterisk/module.h"
+#include "asterisk/rtp_engine.h"
#define MAX_TIMESTAMP_SKEW 640
@@ -66,6 +67,8 @@
#define RTP_MTU 1200
#define DEFAULT_DTMF_TIMEOUT 3000 /*!< samples */
+
+#define ZFONE_PROFILE_ID 0x505a
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
@@ -87,22 +90,6 @@
STRICT_RTP_LEARN, /*! Accept next packet as source */
STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
};
-
-/* Uncomment this to enable more intense native bridging, but note: this is currently buggy */
-/* #define P2P_INTENSE */
-
-/*!
- * \brief Structure representing a RTP session.
- *
- * RTP session is defined on page 9 of RFC 3550: "An association among a set of participants communicating with RTP. A participant may be involved in multiple RTP sessions at the same time [...]"
- *
- */
-/*! \brief The value of each payload format mapping: */
-struct rtpPayloadType {
- int isAstFormat; /*!< whether the following code is an AST_FORMAT */
- int code;
-};
-
/*! \brief RTP session description */
struct ast_rtp {
@@ -143,14 +130,11 @@
unsigned int dtmfsamples;
/* DTMF Transmission Variables */
unsigned int lastdigitts;
- char sending_digit; /*!< boolean - are we sending digits */
+ unsigned int sending_digit:1; /*!< boolean - are we sending digits */
char send_digit; /*!< digit we are sending */
int send_payload;
int send_duration;
- int nat;
unsigned int flags;
- struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
- struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
struct timeval rxcore;
struct timeval txcore;
double drxcore; /*!< The double representation of the first received packet */
@@ -163,62 +147,14 @@
struct sched_context *sched;
struct io_context *io;
void *data;
- ast_rtp_callback callback;
-#ifdef P2P_INTENSE
- ast_mutex_t bridge_lock;
-#endif
- struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
- int rtp_lookup_code_cache_isAstFormat; /*!< a cache for the result of rtp_lookup_code(): */
- int rtp_lookup_code_cache_code;
- int rtp_lookup_code_cache_result;
struct ast_rtcp *rtcp;
- struct ast_codec_pref pref;
struct ast_rtp *bridged; /*!< Who we are Packet bridged to */
enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
struct sockaddr_in strict_rtp_address; /*!< Remote address information for strict RTP purposes */
- int set_marker_bit:1; /*!< Whether to set the marker bit or not */
- struct rtp_red *red;
+ unsigned int set_marker_bit:1; /*!< Whether to set the marker bit or not */
};
-
-static struct ast_frame *red_t140_to_red(struct rtp_red *red);
-static int red_write(const void *data);
-
-struct rtp_red {
- struct ast_frame t140; /*!< Primary data */
- struct ast_frame t140red; /*!< Redundant t140*/
- unsigned char pt[RED_MAX_GENERATION]; /*!< Payload types for redundancy data */
- unsigned char ts[RED_MAX_GENERATION]; /*!< Time stamps */
- unsigned char len[RED_MAX_GENERATION]; /*!< length of each generation */
- int num_gen; /*!< Number of generations */
- int schedid; /*!< Timer id */
- int ti; /*!< How long to buffer data before send */
- unsigned char t140red_data[64000];
- unsigned char buf_data[64000]; /*!< buffered primary data */
- int hdrlen;
- long int prev_ts;
-};
-
-/* Forward declarations */
-static int ast_rtcp_write(const void *data);
-static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw);
-static int ast_rtcp_write_sr(const void *data);
-static int ast_rtcp_write_rr(const void *data);
-static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp);
-static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp);
-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
-
-#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 FLAG_HAS_DTMF (1 << 3)
-#define FLAG_P2P_SENT_MARK (1 << 4)
-#define FLAG_P2P_NEED_DTMF (1 << 5)
-#define FLAG_CALLBACK_MODE (1 << 6)
-#define FLAG_DTMF_COMPENSATE (1 << 7)
-#define FLAG_HAS_STUN (1 << 8)
/*!
* \brief Structure defining an RTCP session.
@@ -250,10 +186,6 @@
double rtt; /*!< Last reported rtt */
unsigned int reported_jitter; /*!< The contents of their last jitter entry in the RR */
unsigned int reported_lost; /*!< Reported lost packets in their RR */
- char quality[AST_MAX_USER_FIELD];
- char quality_jitter[AST_MAX_USER_FIELD];
- char quality_loss[AST_MAX_USER_FIELD];
- char quality_rtt[AST_MAX_USER_FIELD];
double reported_maxjitter;
double reported_minjitter;
@@ -283,936 +215,572 @@
double normdevrtt;
double stdevrtt;
unsigned int rtt_count;
- int sendfur;
};
-size_t ast_rtp_alloc_size(void)
-{
- return sizeof(struct ast_rtp);
-}
-
-/*! \brief List of current sessions */
-static AST_RWLIST_HEAD_STATIC(protos, ast_rtp_protocol);
-
-static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
-{
- unsigned int sec, usec, frac;
- sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
- usec = tv.tv_usec;
- frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
- *msw = sec;
- *lsw = frac;
-}
-
-int ast_rtp_fd(struct ast_rtp *rtp)
-{
- return rtp->s;
-}
-
-int ast_rtcp_fd(struct ast_rtp *rtp)
-{
- if (rtp->rtcp)
- return rtp->rtcp->s;
- return -1;
-}
-
-unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
-{
- unsigned int interval;
- /*! \todo XXX Do a more reasonable calculation on this one
- * Look in RFC 3550 Section A.7 for an example*/
- interval = rtcpinterval;
- return interval;
-}
-
-/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */
-void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp)
-{
- rtp->rtptimeout = (-1) * rtp->rtptimeout;
- rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
-}
-
-/*! \brief Set rtp timeout */
-void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout)
-{
- rtp->rtptimeout = timeout;
-}
-
-/*! \brief Set rtp hold timeout */
-void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout)
-{
- rtp->rtpholdtimeout = timeout;
-}
-
-/*! \brief set RTP keepalive interval */
-void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period)
-{
- rtp->rtpkeepalive = period;
-}
-
-/*! \brief Get rtp timeout */
-int ast_rtp_get_rtptimeout(struct ast_rtp *rtp)
-{
- if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */
+/* Forward Declarations */
+static int ast_rtp_new(struct ast_rtp_instance *instance);
+static int ast_rtp_destroy(struct ast_rtp_instance *instance);
+static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit);
+static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit);
+static void ast_rtp_new_source(struct ast_rtp_instance *instance);
+static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
+static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance);
+
+/* RTP Engine Declaration */
+static struct ast_rtp_engine asterisk_rtp_engine = {
+ .name = "asterisk",
+ .new = ast_rtp_new,
+ .destroy = ast_rtp_destroy,
+ .dtmf_begin = ast_rtp_dtmf_begin,
+ .dtmf_end = ast_rtp_dtmf_end,
+ .new_source = ast_rtp_new_source,
+ .write = ast_rtp_write,
+ .read = ast_rtp_read,
+};
+
+static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
+{
+ if (!rtpdebug) {
return 0;
- return rtp->rtptimeout;
-}
-
-/*! \brief Get rtp hold timeout */
-int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp)
-{
- if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */
- return 0;
- return rtp->rtpholdtimeout;
-}
-
-/*! \brief Get RTP keepalive interval */
-int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp)
-{
- return rtp->rtpkeepalive;
-}
-
-void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
-{
- rtp->data = data;
-}
-
-void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
-{
- rtp->callback = callback;
-}
-
-void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
-{
- rtp->nat = nat;
-}
-
-int ast_rtp_getnat(struct ast_rtp *rtp)
-{
- return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
-}
-
-void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf)
-{
- ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
-}
-
-void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate)
-{
- ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
-}
-
-void ast_rtp_setstun(struct ast_rtp *rtp, int stun_enable)
-{
- ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
-}
-
-static void rtp_bridge_lock(struct ast_rtp *rtp)
-{
-#ifdef P2P_INTENSE
- ast_mutex_lock(&rtp->bridge_lock);
-#endif
- return;
-}
-
-static void rtp_bridge_unlock(struct ast_rtp *rtp)
-{
-#ifdef P2P_INTENSE
- ast_mutex_unlock(&rtp->bridge_lock);
-#endif
- return;
-}
-
-/*! \brief Calculate normal deviation */
-static double normdev_compute(double normdev, double sample, unsigned int sample_count)
-{
- normdev = normdev * sample_count + sample;
- sample_count++;
-
- return normdev / sample_count;
-}
-
-static double stddev_compute(double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
-{
-/*
- for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
- return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
- we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
- optimized formula
-*/
-#define SQUARE(x) ((x) * (x))
-
- stddev = sample_count * stddev;
- sample_count++;
-
- return stddev +
- ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
- ( SQUARE(sample - normdev_curent) / sample_count );
-
-#undef SQUARE
-}
-
-static struct ast_frame *send_dtmf(struct ast_rtp *rtp, enum ast_frame_type type)
-{
- if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
- (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
- ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
- rtp->resp = 0;
- rtp->dtmfsamples = 0;
- return &ast_null_frame;
- }
- ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
- if (rtp->resp == 'X') {
- rtp->f.frametype = AST_FRAME_CONTROL;
- rtp->f.subclass = AST_CONTROL_FLASH;
- } else {
- rtp->f.frametype = type;
- rtp->f.subclass = rtp->resp;
- }
- rtp->f.datalen = 0;
- rtp->f.samples = 0;
- rtp->f.mallocd = 0;
- rtp->f.src = "RTP";
- return &rtp->f;
+ }
-}
-
-static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
-{
- if (rtpdebug == 0)
- return 0;
if (rtpdebugaddr.sin_addr.s_addr) {
if (((ntohs(rtpdebugaddr.sin_port) != 0)
&& (rtpdebugaddr.sin_port != addr->sin_port))
|| (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
return 0;
}
+
return 1;
}
static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
{
- if (rtcpdebug == 0)
+ if (!rtcpdebug) {
return 0;
+ }
+
if (rtcpdebugaddr.sin_addr.s_addr) {
if (((ntohs(rtcpdebugaddr.sin_port) != 0)
&& (rtcpdebugaddr.sin_port != addr->sin_port))
|| (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
return 0;
}
+
return 1;
}
-
-static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
-{
- unsigned int event;
- char resp = 0;
- struct ast_frame *f = NULL;
- unsigned char seq;
- unsigned int flags;
- unsigned int power;
-
- /* We should have at least 4 bytes in RTP data */
- if (len < 4)
- return f;
-
- /* The format of Cisco RTP DTMF packet looks like next:
- +0 - sequence number of DTMF RTP packet (begins from 1,
- wrapped to 0)
- +1 - set of flags
- +1 (bit 0) - flaps by different DTMF digits delimited by audio
- or repeated digit without audio???
- +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
- then falls to 0 at its end)
- +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
- Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
- by each new packet and thus provides some redudancy.
+static int create_new_socket(const char *type)
+{
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (sock < 0) {
+ if (!type) {
+ type = "RTP/RTCP";
+ }
+ ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
+ } else {
+ long flags = fcntl(sock, F_GETFL);
+ fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+#ifdef SO_NO_CHECK
+ if (nochecksums) {
+ setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
+ }
+#endif
+ }
+
+ return sock;
+}
+
+static int ast_rtp_new(struct ast_rtp_instance *instance)
+{
+ struct ast_rtp *rtp = NULL;
+
+ /* Create a new RTP structure to hold all of our data */
+ if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
+ return -1;
+ }
+
+ /* Create a new socket for us to listen on and use */
+ if ((rtp->s = create_new_socket("RTP")) < 0) {
+ ast_free(rtp);
+ return -1;
+ }
+
+ /* Now actually find a free RTP port to use */
+
+ /* Associate the RTP structure with the RTP instance and be done */
+ instance->data = rtp;
+
+ return 0;
+}
+
+static int ast_rtp_destroy(struct ast_rtp_instance *instance)
+{
+ struct ast_rtp *rtp = instance->data;
+
+ /* Destroy the smoother that was smoothing out audio if present */
+ if (rtp->smoother) {
+ ast_smoother_free(rtp->smoother);
+ }
+
+ /* Close our own socket so we no longer get packets */
+ if (rtp->s > -1) {
+ close(rtp->s);
+ }
+
+ /* Destroy RTCP if it was being used */
+ if (rtp->rtcp) {
+ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+ close(rtp->rtcp->s);
+ ast_free(rtp->rtcp);
+ }
+
+ /* Finally destroy ourselves */
+ ast_free(rtp);
+
+ return 0;
+}
+
+static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
+{
+ struct ast_rtp *rtp = instance->data;
+ int hdrlen = 12, res = 0, i = 0, payload = 101;
+ char data[256];
+ unsigned int *rtpheader = (unsigned int*)data;
+
+ /* If we have no remote address information bail out now */
+ if (!instance->remote_address.sin_addr.s_addr || !instance->remote_address.sin_port) {
+ return -1;
+ }
+
+ /* Convert given digit into what we want to transmit */
+ if ((digit <= '9') && (digit >= '0')) {
+ digit -= '0';
+ } else if (digit == '*') {
+ digit = 10;
+ } else if (digit == '#') {
+ digit = 11;
+ } else if ((digit >= 'A') && (digit <= 'D')) {
+ digit = digit - 'A' + 12;
+ } else if ((digit >= 'a') && (digit <= 'd')) {
+ digit = digit - 'a' + 12;
+ } else {
+ ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
+ return -1;
+ }
+
+ /* Grab the payload that they expect the RFC2833 packet to be received in */
+ payload = ast_rtp_instance_payload_code(instance, 0, AST_RTP_DTMF);
+
+ /* Create the actual packet that we will be sending */
+ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
+ rtpheader[1] = htonl(rtp->lastdigitts);
+ rtpheader[2] = htonl(rtp->ssrc);
+
+ /* Actually send the packet */
+ for (i = 0; i < 2; i++) {
+ rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
+ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &instance->remote_address, sizeof(instance->remote_address));
+ if (res < 0) {
+ ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
+ ast_inet_ntoa(instance->remote_address.sin_addr), ntohs(instance->remote_address.sin_port), strerror(errno));
+ }
+ if (rtp_debug_test_addr(&instance->remote_address)) {
+ ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+ ast_inet_ntoa(instance->remote_address.sin_addr),
+ ntohs(instance->remote_address.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+ }
+ rtp->seqno++;
+ rtp->send_duration += 160;
+ rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
+ }
+
+ /* Record that we are in the process of sending a digit and information needed to continue doing so */
+ rtp->sending_digit = 1;
+ rtp->send_digit = digit;
+ rtp->send_payload = payload;
+
+ return 0;
+}
+
+static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
+{
+ struct ast_rtp *rtp = instance->data;
[... 3946 lines stripped ...]
More information about the asterisk-commits
mailing list