mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
Merge in the RTP engine API.
This API provides a generic way for multiple RTP stacks to be integrated into Asterisk. Right now there is only one present, res_rtp_asterisk, which is the existing Asterisk RTP stack. Functionality wise this commit performs the same as previously. API documentation can be viewed in the rtp_engine.h header file. Review: http://reviewboard.digium.com/r/209/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@186078 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -52,7 +52,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/sched.h"
|
||||
#include "asterisk/io.h"
|
||||
#include "asterisk/rtp.h"
|
||||
#include "asterisk/rtp_engine.h"
|
||||
#include "asterisk/stun.h"
|
||||
#include "asterisk/acl.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/file.h"
|
||||
@@ -112,8 +113,8 @@ struct gtalk_pvt {
|
||||
char cid_name[80]; /*!< Caller ID name */
|
||||
char exten[80]; /*!< Called extension */
|
||||
struct ast_channel *owner; /*!< Master Channel */
|
||||
struct ast_rtp *rtp; /*!< RTP audio session */
|
||||
struct ast_rtp *vrtp; /*!< RTP video session */
|
||||
struct ast_rtp_instance *rtp; /*!< RTP audio session */
|
||||
struct ast_rtp_instance *vrtp; /*!< RTP video session */
|
||||
int jointcapability; /*!< Supported capability at both ends (codecs ) */
|
||||
int peercapability;
|
||||
struct gtalk_pvt *next; /* Next entity */
|
||||
@@ -183,11 +184,6 @@ static int gtalk_sendhtml(struct ast_channel *ast, int subclass, const char *dat
|
||||
static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const char *them, const char *sid);
|
||||
static char *gtalk_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
||||
static char *gtalk_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
||||
/*----- RTP interface functions */
|
||||
static int gtalk_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 gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
|
||||
static int gtalk_get_codec(struct ast_channel *chan);
|
||||
|
||||
/*! \brief PBX interface structure for channel registration */
|
||||
static const struct ast_channel_tech gtalk_tech = {
|
||||
@@ -197,7 +193,7 @@ static const struct ast_channel_tech gtalk_tech = {
|
||||
.requester = gtalk_request,
|
||||
.send_digit_begin = gtalk_digit_begin,
|
||||
.send_digit_end = gtalk_digit_end,
|
||||
.bridge = ast_rtp_bridge,
|
||||
.bridge = ast_rtp_instance_bridge,
|
||||
.call = gtalk_call,
|
||||
.hangup = gtalk_hangup,
|
||||
.answer = gtalk_answer,
|
||||
@@ -216,14 +212,6 @@ static struct sched_context *sched; /*!< The scheduling context */
|
||||
static struct io_context *io; /*!< The IO context */
|
||||
static struct in_addr __ourip;
|
||||
|
||||
/*! \brief RTP driver interface */
|
||||
static struct ast_rtp_protocol gtalk_rtp = {
|
||||
type: "Gtalk",
|
||||
get_rtp_info: gtalk_get_rtp_peer,
|
||||
set_rtp_peer: gtalk_set_rtp_peer,
|
||||
get_codec: gtalk_get_codec,
|
||||
};
|
||||
|
||||
static struct ast_cli_entry gtalk_cli[] = {
|
||||
AST_CLI_DEFINE(gtalk_do_reload, "Reload GoogleTalk configuration"),
|
||||
AST_CLI_DEFINE(gtalk_show_channels, "Show GoogleTalk channels"),
|
||||
@@ -371,7 +359,7 @@ static int add_codec_to_answer(const struct gtalk_pvt *p, int codec, iks *dcodec
|
||||
iks_insert_node(dcodecs, payload_gsm);
|
||||
res++;
|
||||
}
|
||||
ast_rtp_lookup_code(p->rtp, 1, codec);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -523,18 +511,19 @@ static int gtalk_answer(struct ast_channel *ast)
|
||||
return res;
|
||||
}
|
||||
|
||||
static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
|
||||
static enum ast_rtp_glue_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
|
||||
{
|
||||
struct gtalk_pvt *p = chan->tech_pvt;
|
||||
enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
|
||||
enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
|
||||
|
||||
if (!p)
|
||||
return res;
|
||||
|
||||
ast_mutex_lock(&p->lock);
|
||||
if (p->rtp){
|
||||
*rtp = p->rtp;
|
||||
res = AST_RTP_TRY_PARTIAL;
|
||||
ao2_ref(p->rtp, +1);
|
||||
*instance = p->rtp;
|
||||
res = AST_RTP_GLUE_RESULT_LOCAL;
|
||||
}
|
||||
ast_mutex_unlock(&p->lock);
|
||||
|
||||
@@ -547,7 +536,7 @@ static int gtalk_get_codec(struct ast_channel *chan)
|
||||
return p->peercapability;
|
||||
}
|
||||
|
||||
static int gtalk_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 int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
|
||||
{
|
||||
struct gtalk_pvt *p;
|
||||
|
||||
@@ -567,6 +556,13 @@ static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, str
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_rtp_glue gtalk_rtp_glue = {
|
||||
.type = "Gtalk",
|
||||
.get_rtp_info = gtalk_get_rtp_peer,
|
||||
.get_codec = gtalk_get_codec,
|
||||
.update_peer = gtalk_set_rtp_peer,
|
||||
};
|
||||
|
||||
static int gtalk_response(struct gtalk *client, char *from, ikspak *pak, const char *reasonstr, const char *reasonstr2)
|
||||
{
|
||||
iks *response = NULL, *error = NULL, *reason = NULL;
|
||||
@@ -617,13 +613,13 @@ static int gtalk_is_answered(struct gtalk *client, ikspak *pak)
|
||||
/* codec points to the first <payload-type/> tag */
|
||||
codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
|
||||
while (codec) {
|
||||
ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")));
|
||||
ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
|
||||
ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp, atoi(iks_find_attrib(codec, "id")));
|
||||
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
|
||||
codec = iks_next_tag(codec);
|
||||
}
|
||||
|
||||
/* Now gather all of the codecs that we are asked for */
|
||||
ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability);
|
||||
ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(tmp->rtp), &tmp->peercapability, &peernoncodeccapability);
|
||||
|
||||
/* at this point, we received an awser from the remote Gtalk client,
|
||||
which allows us to compare capabilities */
|
||||
@@ -810,7 +806,7 @@ static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, ch
|
||||
goto safeout;
|
||||
}
|
||||
|
||||
ast_rtp_get_us(p->rtp, &sin);
|
||||
ast_rtp_instance_get_local_address(p->rtp, &sin);
|
||||
ast_find_ourip(&us, bindaddr);
|
||||
if (!strcmp(ast_inet_ntoa(us), "127.0.0.1")) {
|
||||
ast_log(LOG_WARNING, "Found a loopback IP on the system, check your network configuration or set the bindaddr attribute.");
|
||||
@@ -951,8 +947,9 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const
|
||||
tmp->initiator = 1;
|
||||
}
|
||||
/* clear codecs */
|
||||
tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
|
||||
ast_rtp_pt_clear(tmp->rtp);
|
||||
tmp->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
|
||||
ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_RTCP, 1);
|
||||
ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp);
|
||||
|
||||
/* add user configured codec capabilites */
|
||||
if (client->capability)
|
||||
@@ -1014,20 +1011,20 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
|
||||
|
||||
/* Set Frame packetization */
|
||||
if (i->rtp)
|
||||
ast_rtp_codec_setpref(i->rtp, &i->prefs);
|
||||
ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
|
||||
|
||||
tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
|
||||
fmt = ast_best_codec(tmp->nativeformats);
|
||||
|
||||
if (i->rtp) {
|
||||
ast_rtp_setstun(i->rtp, 1);
|
||||
ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
|
||||
ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
|
||||
ast_rtp_instance_set_prop(i->rtp, AST_RTP_PROPERTY_STUN, 1);
|
||||
ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
|
||||
ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
|
||||
}
|
||||
if (i->vrtp) {
|
||||
ast_rtp_setstun(i->rtp, 1);
|
||||
ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
|
||||
ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
|
||||
ast_rtp_instance_set_prop(i->vrtp, AST_RTP_PROPERTY_STUN, 1);
|
||||
ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
|
||||
ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
|
||||
}
|
||||
if (state == AST_STATE_RING)
|
||||
tmp->rings = 1;
|
||||
@@ -1142,9 +1139,9 @@ static void gtalk_free_pvt(struct gtalk *client, struct gtalk_pvt *p)
|
||||
if (p->owner)
|
||||
ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
|
||||
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);
|
||||
gtalk_free_candidates(p->theircandidates);
|
||||
ast_free(p);
|
||||
}
|
||||
@@ -1207,13 +1204,13 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak)
|
||||
codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
|
||||
|
||||
while (codec) {
|
||||
ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
|
||||
ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
|
||||
ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
|
||||
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
|
||||
codec = iks_next_tag(codec);
|
||||
}
|
||||
|
||||
/* Now gather all of the codecs that we are asked for */
|
||||
ast_rtp_get_current_formats(p->rtp, &p->peercapability, &peernoncodeccapability);
|
||||
ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(p->rtp), &p->peercapability, &peernoncodeccapability);
|
||||
p->jointcapability = p->capability & p->peercapability;
|
||||
ast_mutex_unlock(&p->lock);
|
||||
|
||||
@@ -1277,16 +1274,16 @@ static int gtalk_update_stun(struct gtalk *client, struct gtalk_pvt *p)
|
||||
p->ourcandidates->username);
|
||||
|
||||
/* Find out the result of the STUN */
|
||||
ast_rtp_get_peer(p->rtp, &aux);
|
||||
ast_rtp_instance_get_remote_address(p->rtp, &aux);
|
||||
|
||||
/* If the STUN result is different from the IP of the hostname,
|
||||
lock on the stun IP of the hostname advertised by the
|
||||
remote client */
|
||||
if (aux.sin_addr.s_addr &&
|
||||
aux.sin_addr.s_addr != sin.sin_addr.s_addr)
|
||||
ast_rtp_stun_request(p->rtp, &aux, username);
|
||||
ast_rtp_instance_stun_request(p->rtp, &aux, username);
|
||||
else
|
||||
ast_rtp_stun_request(p->rtp, &sin, username);
|
||||
ast_rtp_instance_stun_request(p->rtp, &sin, username);
|
||||
|
||||
if (aux.sin_addr.s_addr) {
|
||||
ast_debug(4, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip);
|
||||
@@ -1387,7 +1384,7 @@ static struct ast_frame *gtalk_rtp_read(struct ast_channel *ast, struct gtalk_pv
|
||||
|
||||
if (!p->rtp)
|
||||
return &ast_null_frame;
|
||||
f = ast_rtp_read(p->rtp);
|
||||
f = ast_rtp_instance_read(p->rtp, 0);
|
||||
gtalk_update_stun(p->parent, p);
|
||||
if (p->owner) {
|
||||
/* We already hold the channel lock */
|
||||
@@ -1438,7 +1435,7 @@ static int gtalk_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
if (p) {
|
||||
ast_mutex_lock(&p->lock);
|
||||
if (p->rtp) {
|
||||
res = ast_rtp_write(p->rtp, frame);
|
||||
res = ast_rtp_instance_write(p->rtp, frame);
|
||||
}
|
||||
ast_mutex_unlock(&p->lock);
|
||||
}
|
||||
@@ -1447,7 +1444,7 @@ static int gtalk_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
if (p) {
|
||||
ast_mutex_lock(&p->lock);
|
||||
if (p->vrtp) {
|
||||
res = ast_rtp_write(p->vrtp, frame);
|
||||
res = ast_rtp_instance_write(p->vrtp, frame);
|
||||
}
|
||||
ast_mutex_unlock(&p->lock);
|
||||
}
|
||||
@@ -2062,7 +2059,7 @@ static int load_module(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ast_rtp_proto_register(>alk_rtp);
|
||||
ast_rtp_glue_register(>alk_rtp_glue);
|
||||
ast_cli_register_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli));
|
||||
|
||||
/* Make sure we can register our channel type */
|
||||
@@ -2086,7 +2083,7 @@ static int unload_module(void)
|
||||
ast_cli_unregister_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli));
|
||||
/* First, take us out of the channel loop */
|
||||
ast_channel_unregister(>alk_tech);
|
||||
ast_rtp_proto_unregister(>alk_rtp);
|
||||
ast_rtp_glue_unregister(>alk_rtp_glue);
|
||||
|
||||
if (!ast_mutex_lock(>alklock)) {
|
||||
/* Hangup all interfaces if they have an owner */
|
||||
|
Reference in New Issue
Block a user