Jingle Channel Driver. More...
#include "asterisk.h"#include <sys/socket.h>#include <fcntl.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/signal.h>#include <iksemel.h>#include <pthread.h>#include "asterisk/lock.h"#include "asterisk/channel.h"#include "asterisk/config.h"#include "asterisk/module.h"#include "asterisk/pbx.h"#include "asterisk/sched.h"#include "asterisk/io.h"#include "asterisk/rtp.h"#include "asterisk/acl.h"#include "asterisk/callerid.h"#include "asterisk/file.h"#include "asterisk/cli.h"#include "asterisk/app.h"#include "asterisk/musiconhold.h"#include "asterisk/manager.h"#include "asterisk/stringfields.h"#include "asterisk/utils.h"#include "asterisk/causes.h"#include "asterisk/astobj.h"#include "asterisk/abstract_jb.h"#include "asterisk/jabber.h"#include "asterisk/jingle.h"
Go to the source code of this file.
Data Structures | |
| struct | jingle |
| struct | jingle_candidate |
| struct | jingle_container |
| struct | jingle_pvt |
Defines | |
| #define | FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
| #define | JINGLE_CONFIG "jingle.conf" |
Enumerations | |
| enum | jingle_connect_type { AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX } |
| enum | jingle_protocol { AJI_PROTOCOL_UDP, AJI_PROTOCOL_SSLTCP } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static void | add_codec_to_answer (const struct jingle_pvt *p, int codec, iks *dcodecs) |
| static struct jingle * | find_jingle (char *name, char *connection) |
| static int | jingle_accept_call (struct jingle *client, struct jingle_pvt *p) |
| static int | jingle_action (struct jingle *client, struct jingle_pvt *p, const char *action) |
| static int | jingle_add_candidate (struct jingle *client, ikspak *pak) |
| static struct jingle_pvt * | jingle_alloc (struct jingle *client, const char *from, const char *sid) |
| static int | jingle_answer (struct ast_channel *ast) |
| static int | jingle_call (struct ast_channel *ast, char *dest, int timeout) |
| Initiate new call, part of PBX interface dest is the dial string. | |
| static int | jingle_create_candidates (struct jingle *client, struct jingle_pvt *p, char *sid, char *from) |
| static int | jingle_create_member (char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct jingle *member) |
| static int | jingle_digit (struct ast_channel *ast, char digit, unsigned int duration) |
| static int | jingle_digit_begin (struct ast_channel *ast, char digit) |
| static int | jingle_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| static char * | jingle_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command "jingle reload". | |
| static int | jingle_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static void | jingle_free_candidates (struct jingle_candidate *candidate) |
| static void | jingle_free_pvt (struct jingle *client, struct jingle_pvt *p) |
| static int | jingle_get_codec (struct ast_channel *chan) |
| static enum ast_rtp_get_result | jingle_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
| static int | jingle_handle_dtmf (struct jingle *client, ikspak *pak) |
| static int | jingle_hangup (struct ast_channel *ast) |
| Hangup a call through the jingle proxy channel. | |
| static int | jingle_hangup_farend (struct jingle *client, ikspak *pak) |
| static int | jingle_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen) |
| static int | jingle_is_answered (struct jingle *client, ikspak *pak) |
| static int | jingle_load_config (void) |
| static void | jingle_member_destroy (struct jingle *obj) |
| static struct ast_channel * | jingle_new (struct jingle *client, struct jingle_pvt *i, int state, const char *title) |
| Start new jingle channel. | |
| static int | jingle_newcall (struct jingle *client, ikspak *pak) |
| static int | jingle_parser (void *data, ikspak *pak) |
| static struct ast_frame * | jingle_read (struct ast_channel *ast) |
| static struct ast_channel * | jingle_request (const char *request_type, int format, void *data, int *cause) |
| Part of PBX interface. | |
| static int | jingle_response (struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2) |
| static int | jingle_ringing_ack (void *data, ikspak *pak) |
| static struct ast_frame * | jingle_rtp_read (struct ast_channel *ast, struct jingle_pvt *p) |
| static int | jingle_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen) |
| static int | jingle_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *tpeer, int codecs, int nat_active) |
| static char * | jingle_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command "jingle show channels". | |
| static int | jingle_transmit_invite (struct jingle_pvt *p) |
| static int | jingle_update_stun (struct jingle *client, struct jingle_pvt *p) |
| static int | jingle_write (struct ast_channel *ast, struct ast_frame *frame) |
| Send frame to media channel (rtp) | |
| static int | load_module (void) |
| Load module into PBX, register channel. | |
| static int | reload (void) |
| Reload module. | |
| static int | unload_module (void) |
| Unload the jingle channel from Asterisk. | |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Jingle Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } |
| static struct in_addr | __ourip |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct sockaddr_in | bindaddr = { 0, } |
| static const char | channel_type [] = "Jingle" |
| static struct ast_jb_conf | default_jbconf |
| static const char | desc [] = "Jingle Channel" |
| static char | externip [16] |
| static int | global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 |
| static struct ast_jb_conf | global_jbconf |
| static struct io_context * | io |
| static struct ast_cli_entry | jingle_cli [] |
| static struct jingle_container | jingle_list |
| static struct ast_rtp_protocol | jingle_rtp |
| RTP driver interface. | |
| static struct ast_channel_tech | jingle_tech |
| PBX interface structure for channel registration. | |
| static ast_mutex_t | jinglelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static struct sched_context * | sched |
Jingle Channel Driver.
Definition in file chan_jingle.c.
| #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
| #define JINGLE_CONFIG "jingle.conf" |
Definition at line 72 of file chan_jingle.c.
Referenced by jingle_load_config(), and load_module().
| enum jingle_connect_type |
Definition at line 90 of file chan_jingle.c.
| enum jingle_protocol |
Definition at line 85 of file chan_jingle.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 1935 of file chan_jingle.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1935 of file chan_jingle.c.
| static void add_codec_to_answer | ( | const struct jingle_pvt * | p, |
| int | codec, | ||
| iks * | dcodecs | ||
| ) | [static] |
Definition at line 270 of file chan_jingle.c.
References ast_getformatname(), ast_rtp_lookup_code(), format, and jingle_pvt::rtp.
Referenced by jingle_accept_call().
{
char *format = ast_getformatname(codec);
if (!strcasecmp("ulaw", format)) {
iks *payload_eg711u, *payload_pcmu;
payload_pcmu = iks_new("payload-type");
iks_insert_attrib(payload_pcmu, "id", "0");
iks_insert_attrib(payload_pcmu, "name", "PCMU");
payload_eg711u = iks_new("payload-type");
iks_insert_attrib(payload_eg711u, "id", "100");
iks_insert_attrib(payload_eg711u, "name", "EG711U");
iks_insert_node(dcodecs, payload_pcmu);
iks_insert_node(dcodecs, payload_eg711u);
}
if (!strcasecmp("alaw", format)) {
iks *payload_eg711a;
iks *payload_pcma = iks_new("payload-type");
iks_insert_attrib(payload_pcma, "id", "8");
iks_insert_attrib(payload_pcma, "name", "PCMA");
payload_eg711a = iks_new("payload-type");
iks_insert_attrib(payload_eg711a, "id", "101");
iks_insert_attrib(payload_eg711a, "name", "EG711A");
iks_insert_node(dcodecs, payload_pcma);
iks_insert_node(dcodecs, payload_eg711a);
}
if (!strcasecmp("ilbc", format)) {
iks *payload_ilbc = iks_new("payload-type");
iks_insert_attrib(payload_ilbc, "id", "97");
iks_insert_attrib(payload_ilbc, "name", "iLBC");
iks_insert_node(dcodecs, payload_ilbc);
}
if (!strcasecmp("g723", format)) {
iks *payload_g723 = iks_new("payload-type");
iks_insert_attrib(payload_g723, "id", "4");
iks_insert_attrib(payload_g723, "name", "G723");
iks_insert_node(dcodecs, payload_g723);
}
ast_rtp_lookup_code(p->rtp, 1, codec);
}
| static struct jingle* find_jingle | ( | char * | name, |
| char * | connection | ||
| ) | [static, read] |
Definition at line 244 of file chan_jingle.c.
References ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and jingle_list.
Referenced by jingle_request().
{
struct jingle *jingle = NULL;
jingle = ASTOBJ_CONTAINER_FIND(&jingle_list, name);
if (!jingle && strchr(name, '@'))
jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingle_list, name, user,,, strcasecmp);
if (!jingle) {
/* guest call */
ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
ASTOBJ_RDLOCK(iterator);
if (!strcasecmp(iterator->name, "guest")) {
jingle = iterator;
}
ASTOBJ_UNLOCK(iterator);
if (jingle)
break;
});
}
return jingle;
}
| static int jingle_accept_call | ( | struct jingle * | client, |
| struct jingle_pvt * | p | ||
| ) | [static] |
Definition at line 311 of file chan_jingle.c.
References add_codec_to_answer(), ast_aji_increment_mid(), ast_aji_send(), ast_codec_pref_index(), jingle::capability, jingle::connection, jingle_pvt::initiator, aji_client::jid, aji_client::jingle, JINGLE_ACCEPT, JINGLE_AUDIO_RTP_NS, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, jingle::p, jingle::prefs, jingle_pvt::sid, jingle_pvt::them, and jingle::user.
Referenced by jingle_answer().
{
struct jingle_pvt *tmp = client->p;
struct aji_client *c = client->connection;
iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn;
int x;
int pref_codec = 0;
int alreadysent = 0;
if (p->initiator)
return 1;
iq = iks_new("iq");
jingle = iks_new(JINGLE_NODE);
dcodecs = iks_new("description");
if (iq && jingle && dcodecs) {
iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS);
for (x = 0; x < 32; x++) {
if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
break;
if (!(client->capability & pref_codec))
continue;
if (alreadysent & pref_codec)
continue;
add_codec_to_answer(p, pref_codec, dcodecs);
alreadysent |= pref_codec;
}
payload_red = iks_new("payload-type");
iks_insert_attrib(payload_red, "id", "117");
iks_insert_attrib(payload_red, "name", "red");
payload_audio = iks_new("payload-type");
iks_insert_attrib(payload_audio, "id", "106");
iks_insert_attrib(payload_audio, "name", "audio/telephone-event");
payload_cn = iks_new("payload-type");
iks_insert_attrib(payload_cn, "id", "13");
iks_insert_attrib(payload_cn, "name", "CN");
iks_insert_attrib(iq, "type", "set");
iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user);
iks_insert_attrib(iq, "id", client->connection->mid);
ast_aji_increment_mid(client->connection->mid);
iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
iks_insert_attrib(jingle, "action", JINGLE_ACCEPT);
iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
iks_insert_attrib(jingle, JINGLE_SID, tmp->sid);
iks_insert_node(iq, jingle);
iks_insert_node(jingle, dcodecs);
iks_insert_node(dcodecs, payload_red);
iks_insert_node(dcodecs, payload_audio);
iks_insert_node(dcodecs, payload_cn);
ast_aji_send(c, iq);
iks_delete(payload_red);
iks_delete(payload_audio);
iks_delete(payload_cn);
iks_delete(dcodecs);
iks_delete(jingle);
iks_delete(iq);
}
return 1;
}
| static int jingle_action | ( | struct jingle * | client, |
| struct jingle_pvt * | p, | ||
| const char * | action | ||
| ) | [static] |
Definition at line 883 of file chan_jingle.c.
References ast_aji_increment_mid(), ast_aji_send(), jingle::connection, jingle_pvt::initiator, aji_client::jid, JINGLE_NS, JINGLE_SID, aji_client::mid, jingle_pvt::sid, and jingle_pvt::them.
Referenced by jingle_hangup().
{
iks *iq, *jingle = NULL;
int res = -1;
iq = iks_new("iq");
jingle = iks_new("jingle");
if (iq) {
iks_insert_attrib(iq, "type", "set");
iks_insert_attrib(iq, "from", client->connection->jid->full);
iks_insert_attrib(iq, "to", p->them);
iks_insert_attrib(iq, "id", client->connection->mid);
ast_aji_increment_mid(client->connection->mid);
if (jingle) {
iks_insert_attrib(jingle, "action", action);
iks_insert_attrib(jingle, JINGLE_SID, p->sid);
iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
iks_insert_node(iq, jingle);
ast_aji_send(client->connection, iq);
res = 0;
}
}
iks_delete(jingle);
iks_delete(iq);
return res;
}
| static int jingle_add_candidate | ( | struct jingle * | client, |
| ikspak * | pak | ||
| ) | [static] |
Definition at line 1089 of file chan_jingle.c.
References AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_send(), ast_calloc, ast_copy_string(), jingle::connection, jingle_candidate::generation, jingle_candidate::ip, aji_client::jid, JINGLE_NODE, JINGLE_SID, jingle_update_stun(), jingle_pvt::laststun, jingle_candidate::network, jingle_candidate::next, jingle_pvt::next, jingle::p, jingle_pvt::parent, jingle_candidate::password, jingle_candidate::port, jingle_candidate::protocol, jingle_pvt::theircandidates, and jingle_candidate::type.
Referenced by jingle_parser().
{
struct jingle_pvt *p = NULL, *tmp = NULL;
struct aji_client *c = client->connection;
struct jingle_candidate *newcandidate = NULL;
iks *traversenodes = NULL, *receipt = NULL;
for (tmp = client->p; tmp; tmp = tmp->next) {
if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
p = tmp;
break;
}
}
if (!p)
return -1;
traversenodes = pak->query;
while(traversenodes) {
if(!strcasecmp(iks_name(traversenodes), "jingle")) {
traversenodes = iks_child(traversenodes);
continue;
}
if(!strcasecmp(iks_name(traversenodes), "content")) {
traversenodes = iks_child(traversenodes);
continue;
}
if(!strcasecmp(iks_name(traversenodes), "transport")) {
traversenodes = iks_child(traversenodes);
continue;
}
if(!strcasecmp(iks_name(traversenodes), "candidate")) {
newcandidate = ast_calloc(1, sizeof(*newcandidate));
if (!newcandidate)
return 0;
ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip));
newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password));
if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
newcandidate->protocol = AJI_PROTOCOL_UDP;
else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host"))
newcandidate->type = AJI_CONNECT_HOST;
else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx"))
newcandidate->type = AJI_CONNECT_PRFLX;
else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
newcandidate->type = AJI_CONNECT_RELAY;
else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx"))
newcandidate->type = AJI_CONNECT_SRFLX;
newcandidate->network = atoi(iks_find_attrib(traversenodes, "network"));
newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
newcandidate->next = NULL;
newcandidate->next = p->theircandidates;
p->theircandidates = newcandidate;
p->laststun = 0;
jingle_update_stun(p->parent, p);
newcandidate = NULL;
}
traversenodes = iks_next(traversenodes);
}
receipt = iks_new("iq");
iks_insert_attrib(receipt, "type", "result");
iks_insert_attrib(receipt, "from", c->jid->full);
iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
ast_aji_send(c, receipt);
iks_delete(receipt);
return 1;
}
| static struct jingle_pvt * jingle_alloc | ( | struct jingle * | client, |
| const char * | from, | ||
| const char * | sid | ||
| ) | [static, read] |
Definition at line 741 of file chan_jingle.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_new_with_bindaddr(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, jingle::buddy, aji_resource::cap, jingle::connection, jingle_pvt::exten, jingle_pvt::initiator, aji_version::jingle, jinglelock, jingle_pvt::lock, LOG_ERROR, LOG_WARNING, jingle::name, jingle_pvt::next, aji_resource::next, jingle::p, jingle_pvt::parent, jingle::prefs, jingle_pvt::prefs, aji_resource::resource, aji_buddy::resources, jingle_pvt::rtp, jingle_pvt::sid, and jingle_pvt::them.
Referenced by jingle_newcall(), and jingle_request().
{
struct jingle_pvt *tmp = NULL;
struct aji_resource *resources = NULL;
struct aji_buddy *buddy;
char idroster[200];
ast_debug(1, "The client is %s for alloc\n", client->name);
if (!sid && !strchr(from, '/')) { /* I started call! */
if (!strcasecmp(client->name, "guest")) {
buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from);
if (buddy)
resources = buddy->resources;
} else if (client->buddy)
resources = client->buddy->resources;
while (resources) {
if (resources->cap->jingle) {
break;
}
resources = resources->next;
}
if (resources)
snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource);
else {
ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n");
return NULL;
}
}
if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
return NULL;
}
memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
if (sid) {
ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
ast_copy_string(tmp->them, from, sizeof(tmp->them));
} else {
snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
tmp->initiator = 1;
}
tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
tmp->parent = client;
if (!tmp->rtp) {
ast_log(LOG_WARNING, "Out of RTP sessions?\n");
ast_free(tmp);
return NULL;
}
ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
ast_mutex_init(&tmp->lock);
ast_mutex_lock(&jinglelock);
tmp->next = client->p;
client->p = tmp;
ast_mutex_unlock(&jinglelock);
return tmp;
}
| static int jingle_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 389 of file chan_jingle.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), jingle_accept_call(), jingle_pvt::lock, jingle_pvt::parent, and ast_channel::tech_pvt.
{
struct jingle_pvt *p = ast->tech_pvt;
struct jingle *client = p->parent;
int res = 0;
ast_debug(1, "Answer!\n");
ast_mutex_lock(&p->lock);
jingle_accept_call(client, p);
ast_mutex_unlock(&p->lock);
return res;
}
| static int jingle_call | ( | struct ast_channel * | ast, |
| char * | dest, | ||
| int | timeout | ||
| ) | [static] |
Initiate new call, part of PBX interface dest is the dial string.
Definition at line 1424 of file chan_jingle.c.
References ast_channel::_state, ast_copy_string(), ast_log(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RING, jingle_pvt::capability, jingle::connection, aji_client::f, jingle_create_candidates(), jingle_ringing_ack(), jingle_transmit_invite(), jingle_pvt::jointcapability, LOG_WARNING, aji_client::mid, ast_channel::name, jingle_pvt::parent, jingle_pvt::ring, jingle_pvt::ringrule, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.
{
struct jingle_pvt *p = ast->tech_pvt;
if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name);
return -1;
}
ast_setstate(ast, AST_STATE_RING);
p->jointcapability = p->capability;
if (!p->ringrule) {
ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
IKS_RULE_ID, p->ring, IKS_RULE_DONE);
} else
ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
jingle_transmit_invite(p);
jingle_create_candidates(p->parent, p, p->sid, p->them);
return 0;
}
| static int jingle_create_candidates | ( | struct jingle * | client, |
| struct jingle_pvt * | p, | ||
| char * | sid, | ||
| char * | from | ||
| ) | [static] |
Definition at line 583 of file chan_jingle.c.
References __ourip, AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_find_ourip(), ast_free, ast_inet_ntoa(), ast_log(), ast_random(), ast_rtp_get_us(), ast_strlen_zero(), jingle_candidate::component, jingle::connection, jingle_candidate::foundation, jingle_candidate::generation, inet_aton(), jingle_pvt::initiator, jingle_candidate::ip, aji_client::jid, JINGLE_ICE_UDP_NS, JINGLE_NEGOTIATE, JINGLE_NODE, JINGLE_NS, JINGLE_SID, jingle_pvt::laststun, LOG_ERROR, LOG_NOTICE, LOG_WARNING, aji_client::mid, jingle_candidate::network, jingle_candidate::next, jingle_pvt::next, jingle_pvt::ourcandidates, pass, jingle_candidate::password, jingle_candidate::port, jingle_candidate::priority, jingle_candidate::protocol, jingle_pvt::rtp, jingle_pvt::sid, jingle_candidate::type, and jingle_candidate::ufrag.
Referenced by jingle_call(), and jingle_newcall().
{
struct jingle_candidate *tmp;
struct aji_client *c = client->connection;
struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
struct sockaddr_in sin;
struct sockaddr_in dest;
struct in_addr us;
struct in_addr externaddr;
iks *iq, *jingle, *content, *transport, *candidate;
char component[16], foundation[16], generation[16], network[16], pass[16], port[7], priority[16], user[16];
iq = iks_new("iq");
jingle = iks_new(JINGLE_NODE);
content = iks_new("content");
transport = iks_new("transport");
candidate = iks_new("candidate");
if (!iq || !jingle || !content || !transport || !candidate) {
ast_log(LOG_ERROR, "Memory allocation error\n");
goto safeout;
}
ours1 = ast_calloc(1, sizeof(*ours1));
ours2 = ast_calloc(1, sizeof(*ours2));
if (!ours1 || !ours2)
goto safeout;
iks_insert_node(iq, jingle);
iks_insert_node(jingle, content);
iks_insert_node(content, transport);
iks_insert_node(transport, candidate);
for (; p; p = p->next) {
if (!strcasecmp(p->sid, sid))
break;
}
if (!p) {
ast_log(LOG_NOTICE, "No matching jingle session - SID %s!\n", sid);
goto safeout;
}
ast_rtp_get_us(p->rtp, &sin);
ast_find_ourip(&us, bindaddr);
/* Setup our first jingle candidate */
ours1->component = 1;
ours1->foundation = (unsigned int)bindaddr.sin_addr.s_addr | AJI_CONNECT_HOST | AJI_PROTOCOL_UDP;
ours1->generation = 0;
ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
ours1->network = 0;
ours1->port = ntohs(sin.sin_port);
ours1->priority = 1678246398;
ours1->protocol = AJI_PROTOCOL_UDP;
snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
ast_copy_string(ours1->password, pass, sizeof(ours1->password));
ours1->type = AJI_CONNECT_HOST;
snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
ast_copy_string(ours1->ufrag, user, sizeof(ours1->ufrag));
p->ourcandidates = ours1;
if (!ast_strlen_zero(externip)) {
/* XXX We should really stun for this one not just go with externip XXX */
if (inet_aton(externip, &externaddr))
ast_log(LOG_WARNING, "Invalid extern IP : %s\n", externip);
ours2->component = 1;
ours2->foundation = (unsigned int)externaddr.s_addr | AJI_CONNECT_PRFLX | AJI_PROTOCOL_UDP;
ours2->generation = 0;
ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
ours2->network = 0;
ours2->port = ntohs(sin.sin_port);
ours2->priority = 1678246397;
ours2->protocol = AJI_PROTOCOL_UDP;
snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
ast_copy_string(ours2->password, pass, sizeof(ours2->password));
ours2->type = AJI_CONNECT_PRFLX;
snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
ast_copy_string(ours2->ufrag, user, sizeof(ours2->ufrag));
ours1->next = ours2;
ours2 = NULL;
}
ours1 = NULL;
dest.sin_addr = __ourip;
dest.sin_port = sin.sin_port;
for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
snprintf(component, sizeof(component), "%u", tmp->component);
snprintf(foundation, sizeof(foundation), "%u", tmp->foundation);
snprintf(generation, sizeof(generation), "%u", tmp->generation);
snprintf(network, sizeof(network), "%u", tmp->network);
snprintf(port, sizeof(port), "%u", tmp->port);
snprintf(priority, sizeof(priority), "%u", tmp->priority);
iks_insert_attrib(iq, "from", c->jid->full);
iks_insert_attrib(iq, "to", from);
iks_insert_attrib(iq, "type", "set");
iks_insert_attrib(iq, "id", c->mid);
ast_aji_increment_mid(c->mid);
iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE);
iks_insert_attrib(jingle, JINGLE_SID, sid);
iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from);
iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder");
iks_insert_attrib(content, "name", "asterisk-audio-content");
iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
iks_insert_attrib(candidate, "component", component);
iks_insert_attrib(candidate, "foundation", foundation);
iks_insert_attrib(candidate, "generation", generation);
iks_insert_attrib(candidate, "ip", tmp->ip);
iks_insert_attrib(candidate, "network", network);
iks_insert_attrib(candidate, "port", port);
iks_insert_attrib(candidate, "priority", priority);
switch (tmp->protocol) {
case AJI_PROTOCOL_UDP:
iks_insert_attrib(candidate, "protocol", "udp");
break;
case AJI_PROTOCOL_SSLTCP:
iks_insert_attrib(candidate, "protocol", "ssltcp");
break;
}
iks_insert_attrib(candidate, "pwd", tmp->password);
switch (tmp->type) {
case AJI_CONNECT_HOST:
iks_insert_attrib(candidate, "type", "host");
break;
case AJI_CONNECT_PRFLX:
iks_insert_attrib(candidate, "type", "prflx");
break;
case AJI_CONNECT_RELAY:
iks_insert_attrib(candidate, "type", "relay");
break;
case AJI_CONNECT_SRFLX:
iks_insert_attrib(candidate, "type", "srflx");
break;
}
iks_insert_attrib(candidate, "ufrag", tmp->ufrag);
ast_aji_send(c, iq);
}
p->laststun = 0;
safeout:
if (ours1)
ast_free(ours1);
if (ours2)
ast_free(ours2);
iks_delete(iq);
iks_delete(jingle);
iks_delete(content);
iks_delete(transport);
iks_delete(candidate);
return 1;
}
| static int jingle_create_member | ( | char * | label, |
| struct ast_variable * | var, | ||
| int | allowguest, | ||
| struct ast_codec_pref | prefs, | ||
| char * | context, | ||
| struct jingle * | member | ||
| ) | [static] |
Definition at line 1666 of file chan_jingle.c.
References aji_client::allowguest, jingle::allowguest, ast_aji_get_client(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, jingle::buddy, jingle::capability, jingle::connection, jingle::context, aji_client::f, JINGLE_NS, jingle_parser(), LOG_ERROR, LOG_WARNING, ast_variable::name, jingle::name, ast_variable::next, jingle_candidate::next, prefs, jingle::prefs, jingle::user, and ast_variable::value.
Referenced by jingle_load_config().
{
struct aji_client *client;
if (!member)
ast_log(LOG_WARNING, "Out of memory.\n");
ast_copy_string(member->name, label, sizeof(member->name));
ast_copy_string(member->user, label, sizeof(member->user));
ast_copy_string(member->context, context, sizeof(member->context));
member->allowguest = allowguest;
member->prefs = prefs;
while (var) {
#if 0
struct jingle_candidate *candidate = NULL;
#endif
if (!strcasecmp(var->name, "username"))
ast_copy_string(member->user, var->value, sizeof(member->user));
else if (!strcasecmp(var->name, "disallow"))
ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
else if (!strcasecmp(var->name, "allow"))
ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
else if (!strcasecmp(var->name, "context"))
ast_copy_string(member->context, var->value, sizeof(member->context));
#if 0
else if (!strcasecmp(var->name, "candidate")) {
candidate = jingle_create_candidate(var->value);
if (candidate) {
candidate->next = member->ourcandidates;
member->ourcandidates = candidate;
}
}
#endif
else if (!strcasecmp(var->name, "connection")) {
if ((client = ast_aji_get_client(var->value))) {
member->connection = client;
iks_filter_add_rule(client->f, jingle_parser, member,
IKS_RULE_TYPE, IKS_PAK_IQ,
IKS_RULE_FROM_PARTIAL, member->user,
IKS_RULE_NS, JINGLE_NS,
IKS_RULE_DONE);
} else {
ast_log(LOG_ERROR, "connection referenced not found!\n");
return 0;
}
}
var = var->next;
}
if (member->connection && member->user)
member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
else {
ast_log(LOG_ERROR, "No Connection or Username!\n");
}
return 1;
}
| static int jingle_digit | ( | struct ast_channel * | ast, |
| char | digit, | ||
| unsigned int | duration | ||
| ) | [static] |
Definition at line 1284 of file chan_jingle.c.
References ast_aji_increment_mid(), ast_aji_send(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), jingle::connection, ast_channel::dtmff, ast_frame::frametype, jingle_pvt::initiator, aji_client::jid, JINGLE_DTMF_NS, JINGLE_NS, jingle_pvt::lock, LOG_ERROR, aji_client::mid, jingle_pvt::parent, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.
Referenced by jingle_digit_begin(), and jingle_digit_end().
{
struct jingle_pvt *p = ast->tech_pvt;
struct jingle *client = p->parent;
iks *iq, *jingle, *dtmf;
char buffer[2] = {digit, '\0'};
iq = iks_new("iq");
jingle = iks_new("jingle");
dtmf = iks_new("dtmf");
if(!iq || !jingle || !dtmf) {
iks_delete(iq);
iks_delete(jingle);
iks_delete(dtmf);
ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
return -1;
}
iks_insert_attrib(iq, "type", "set");
iks_insert_attrib(iq, "to", p->them);
iks_insert_attrib(iq, "from", client->connection->jid->full);
iks_insert_attrib(iq, "id", client->connection->mid);
ast_aji_increment_mid(client->connection->mid);
iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
iks_insert_attrib(jingle, "action", "session-info");
iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
iks_insert_attrib(jingle, "sid", p->sid);
iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS);
iks_insert_attrib(dtmf, "code", buffer);
iks_insert_node(iq, jingle);
iks_insert_node(jingle, dtmf);
ast_mutex_lock(&p->lock);
if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
iks_insert_attrib(dtmf, "action", "button-down");
} else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
iks_insert_attrib(dtmf, "action", "button-up");
}
ast_aji_send(client->connection, iq);
iks_delete(iq);
iks_delete(jingle);
iks_delete(dtmf);
ast_mutex_unlock(&p->lock);
return 0;
}
| static int jingle_digit_begin | ( | struct ast_channel * | ast, |
| char | digit | ||
| ) | [static] |
Definition at line 1330 of file chan_jingle.c.
References jingle_digit().
{
return jingle_digit(chan, digit, 0);
}
| static int jingle_digit_end | ( | struct ast_channel * | ast, |
| char | digit, | ||
| unsigned int | duration | ||
| ) | [static] |
Definition at line 1335 of file chan_jingle.c.
References jingle_digit().
{
return jingle_digit(ast, digit, duration);
}
| static char * jingle_do_reload | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
CLI command "jingle reload".
Definition at line 1577 of file chan_jingle.c.
References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "jingle reload";
e->usage =
"Usage: jingle reload\n"
" Reload jingle channel driver.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
return CLI_SUCCESS;
}
| static int jingle_fixup | ( | struct ast_channel * | oldchan, |
| struct ast_channel * | newchan | ||
| ) | [static] |
Definition at line 1250 of file chan_jingle.c.
References ast_mutex_lock(), ast_mutex_unlock(), jingle_pvt::lock, jingle_pvt::owner, and ast_channel::tech_pvt.
{
struct jingle_pvt *p = newchan->tech_pvt;
ast_mutex_lock(&p->lock);
if ((p->owner != oldchan)) {
ast_mutex_unlock(&p->lock);
return -1;
}
if (p->owner == oldchan)
p->owner = newchan;
ast_mutex_unlock(&p->lock);
return 0;
}
| static void jingle_free_candidates | ( | struct jingle_candidate * | candidate | ) | [static] |
Definition at line 916 of file chan_jingle.c.
References ast_free, last, and jingle_candidate::next.
Referenced by jingle_free_pvt(), and jingle_load_config().
{
struct jingle_candidate *last;
while (candidate) {
last = candidate;
candidate = candidate->next;
ast_free(last);
}
}
| static void jingle_free_pvt | ( | struct jingle * | client, |
| struct jingle_pvt * | p | ||
| ) | [static] |
Definition at line 926 of file chan_jingle.c.
References ast_free, ast_log(), ast_rtp_destroy(), jingle::connection, aji_client::f, jingle_free_candidates(), LOG_WARNING, jingle_pvt::next, jingle_pvt::owner, jingle::p, jingle_pvt::parent, jingle_pvt::ringrule, jingle_pvt::rtp, jingle_pvt::theircandidates, and jingle_pvt::vrtp.
Referenced by jingle_hangup(), and jingle_newcall().
{
struct jingle_pvt *cur, *prev = NULL;
cur = client->p;
while (cur) {
if (cur == p) {
if (prev)
prev->next = p->next;
else
client->p = p->next;
break;
}
prev = cur;
cur = cur->next;
}
if (p->ringrule)
iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
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);
if (p->vrtp)
ast_rtp_destroy(p->vrtp);
jingle_free_candidates(p->theircandidates);
ast_free(p);
}
| static int jingle_get_codec | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 420 of file chan_jingle.c.
References jingle_pvt::peercapability, and ast_channel::tech_pvt.
{
struct jingle_pvt *p = chan->tech_pvt;
return p->peercapability;
}
| static enum ast_rtp_get_result jingle_get_rtp_peer | ( | struct ast_channel * | chan, |
| struct ast_rtp ** | rtp | ||
| ) | [static] |
Definition at line 402 of file chan_jingle.c.
References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_PARTIAL, jingle_pvt::lock, jingle_pvt::rtp, and ast_channel::tech_pvt.
{
struct jingle_pvt *p = chan->tech_pvt;
enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
if (!p)
return res;
ast_mutex_lock(&p->lock);
if (p->rtp) {
*rtp = p->rtp;
res = AST_RTP_TRY_PARTIAL;
}
ast_mutex_unlock(&p->lock);
return res;
}
| static int jingle_handle_dtmf | ( | struct jingle * | client, |
| ikspak * | pak | ||
| ) | [static] |
Definition at line 498 of file chan_jingle.c.
References AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), ast_verbose(), JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle_pvt::next, jingle_pvt::owner, jingle::p, jingle_pvt::sid, and ast_frame::subclass.
Referenced by jingle_parser().
{
struct jingle_pvt *tmp;
iks *dtmfnode = NULL, *dtmfchild = NULL;
char *dtmf;
/* Make sure our new call doesn't exist yet */
for (tmp = client->p; tmp; tmp = tmp->next) {
if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
break;
}
if (tmp) {
if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) {
jingle_response(client,pak,
"feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
"unsupported-dtmf-method xmlns='http://www.xmpp.org/extensions/xep-0181.html#ns-errors'");
return -1;
}
if ((dtmfnode = iks_find(pak->x, "dtmf"))) {
if((dtmf = iks_find_attrib(dtmfnode, "code"))) {
if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) {
struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
f.subclass = dtmf[0];
ast_queue_frame(tmp->owner, &f);
ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass);
} else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) {
struct ast_frame f = {AST_FRAME_DTMF_END, };
f.subclass = dtmf[0];
ast_queue_frame(tmp->owner, &f);
ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass);
} else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */
struct ast_frame f = {AST_FRAME_DTMF, };
f.subclass = dtmf[0];
ast_queue_frame(tmp->owner, &f);
ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass);
}
}
} else if ((dtmfnode = iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "session-info"))) {
if((dtmfchild = iks_find(dtmfnode, "dtmf"))) {
if((dtmf = iks_find_attrib(dtmfchild, "code"))) {
if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) {
struct ast_frame f = {AST_FRAME_DTMF_END, };
f.subclass = dtmf[0];
ast_queue_frame(tmp->owner, &f);
ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass);
} else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) {
struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
f.subclass = dtmf[0];
ast_queue_frame(tmp->owner, &f);
ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass);
}
}
}
}
jingle_response(client, pak, NULL, NULL);
return 1;
} else
ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
jingle_response(client, pak, NULL, NULL);
return 1;
}
| static int jingle_hangup | ( | struct ast_channel * | ast | ) | [static] |
Hangup a call through the jingle proxy channel.
Definition at line 1449 of file chan_jingle.c.
References jingle_pvt::alreadygone, ast_mutex_lock(), ast_mutex_unlock(), jingle_action(), jingle_free_pvt(), JINGLE_TERMINATE, jingle_pvt::lock, jingle_pvt::owner, jingle_pvt::parent, and ast_channel::tech_pvt.
{
struct jingle_pvt *p = ast->tech_pvt;
struct jingle *client;
ast_mutex_lock(&p->lock);
client = p->parent;
p->owner = NULL;
ast->tech_pvt = NULL;
if (!p->alreadygone)
jingle_action(client, p, JINGLE_TERMINATE);
ast_mutex_unlock(&p->lock);
jingle_free_pvt(client, p);
return 0;
}
| static int jingle_hangup_farend | ( | struct jingle * | client, |
| ikspak * | pak | ||
| ) | [static] |
Definition at line 562 of file chan_jingle.c.
References jingle_pvt::alreadygone, ast_debug, ast_log(), ast_queue_hangup(), JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle::name, jingle_pvt::next, jingle_pvt::owner, jingle::p, and jingle_pvt::sid.
Referenced by jingle_parser().
{
struct jingle_pvt *tmp;
ast_debug(1, "The client is %s\n", client->name);
/* Make sure our new call doesn't exist yet */
for (tmp = client->p; tmp; tmp = tmp->next) {
if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
break;
}
if (tmp) {
tmp->alreadygone = 1;
if (tmp->owner)
ast_queue_hangup(tmp->owner);
} else
ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
jingle_response(client, pak, NULL, NULL);
return 1;
}
| static int jingle_indicate | ( | struct ast_channel * | ast, |
| int | condition, | ||
| const void * | data, | ||
| size_t | datalen | ||
| ) | [static] |
Definition at line 1265 of file chan_jingle.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), and LOG_NOTICE.
{
int res = 0;
switch (condition) {
case AST_CONTROL_HOLD:
ast_moh_start(ast, data, NULL);
break;
case AST_CONTROL_UNHOLD:
ast_moh_stop(ast);
break;
default:
ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
res = -1;
}
return res;
}
| static int jingle_is_answered | ( | struct jingle * | client, |
| ikspak * | pak | ||
| ) | [static] |
Definition at line 478 of file chan_jingle.c.
References AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_queue_control(), JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle::name, jingle_pvt::next, jingle_pvt::owner, jingle::p, and jingle_pvt::sid.
Referenced by jingle_parser().
{
struct jingle_pvt *tmp;
ast_debug(1, "The client is %s\n", client->name);
/* Make sure our new call doesn't exist yet */
for (tmp = client->p; tmp; tmp = tmp->next) {
if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
break;
}
if (tmp) {
if (tmp->owner)
ast_queue_control(tmp->owner, AST_CONTROL_ANSWER);
} else
ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
jingle_response(client, pak, NULL, NULL);
return 1;
}
| static int jingle_load_config | ( | void | ) | [static] |
Definition at line 1724 of file chan_jingle.c.
References jingle::allowguest, ast_aji_get_clients(), ast_calloc, ast_category_browse(), ast_config_load, ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_parse_allow_disallow(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, jingle::capability, clients, CONFIG_STATUS_FILEINVALID, jingle::connection, jingle::context, context, global_jbconf, hp, JINGLE_CONFIG, jingle_create_member(), JINGLE_DTMF_NS, jingle_free_candidates(), jingle_list, jingle_member_destroy(), JINGLE_NS, jingle_parser(), LOG_WARNING, jingle::name, ast_variable::name, ast_variable::next, jingle::parkinglot, prefs, jingle::prefs, jingle::user, ast_variable::value, and var.
Referenced by load_module().
{
char *cat = NULL;
struct ast_config *cfg = NULL;
char context[100];
int allowguest = 1;
struct ast_variable *var;
struct jingle *member;
struct hostent *hp;
struct ast_hostent ahp;
struct ast_codec_pref prefs;
struct aji_client_container *clients;
struct jingle_candidate *global_candidates = NULL;
struct ast_flags config_flags = { 0 };
cfg = ast_config_load(JINGLE_CONFIG, config_flags);
if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
return 0;
}
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
cat = ast_category_browse(cfg, NULL);
for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
/* handle jb conf */
if (!ast_jb_read_conf(&global_jbconf, var->name, var->value))
continue;
if (!strcasecmp(var->name, "allowguest"))
allowguest =
(ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
else if (!strcasecmp(var->name, "disallow"))
ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0);
else if (!strcasecmp(var->name, "allow"))
ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
else if (!strcasecmp(var->name, "context"))
ast_copy_string(context, var->value, sizeof(context));
else if (!strcasecmp(var->name, "externip"))
ast_copy_string(externip, var->value, sizeof(externip));
else if (!strcasecmp(var->name, "bindaddr")) {
if (!(hp = ast_gethostbyname(var->value, &ahp))) {
ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
} else {
memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
}
}
/* Idea to allow for custom candidates */
/*
else if (!strcasecmp(var->name, "candidate")) {
candidate = jingle_create_candidate(var->value);
if (candidate) {
candidate->next = global_candidates;
global_candidates = candidate;
}
}
*/
}
while (cat) {
if (strcasecmp(cat, "general")) {
var = ast_variable_browse(cfg, cat);
member = ast_calloc(1, sizeof(*member));
ASTOBJ_INIT(member);
ASTOBJ_WRLOCK(member);
if (!strcasecmp(cat, "guest")) {
ast_copy_string(member->name, "guest", sizeof(member->name));
ast_copy_string(member->user, "guest", sizeof(member->user));
ast_copy_string(member->context, context, sizeof(member->context));
member->allowguest = allowguest;
member->prefs = prefs;
while (var) {
if (!strcasecmp(var->name, "disallow"))
ast_parse_allow_disallow(&member->prefs, &member->capability,
var->value, 0);
else if (!strcasecmp(var->name, "allow"))
ast_parse_allow_disallow(&member->prefs, &member->capability,
var->value, 1);
else if (!strcasecmp(var->name, "context"))
ast_copy_string(member->context, var->value,
sizeof(member->context));
else if (!strcasecmp(var->name, "parkinglot"))
ast_copy_string(member->parkinglot, var->value,
sizeof(member->parkinglot));
/* Idea to allow for custom candidates */
/*
else if (!strcasecmp(var->name, "candidate")) {
candidate = jingle_create_candidate(var->value);
if (candidate) {
candidate->next = member->ourcandidates;
member->ourcandidates = candidate;
}
}
*/
var = var->next;
}
ASTOBJ_UNLOCK(member);
clients = ast_aji_get_clients();
if (clients) {
ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
ASTOBJ_WRLOCK(iterator);
ASTOBJ_WRLOCK(member);
member->connection = NULL;
iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE);
iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE);
ASTOBJ_UNLOCK(member);
ASTOBJ_UNLOCK(iterator);
});
ASTOBJ_CONTAINER_LINK(&jingle_list, member);
} else {
ASTOBJ_UNLOCK(member);
ASTOBJ_UNREF(member, jingle_member_destroy);
}
} else {
ASTOBJ_UNLOCK(member);
if (jingle_create_member(cat, var, allowguest, prefs, context, member))
ASTOBJ_CONTAINER_LINK(&jingle_list, member);
ASTOBJ_UNREF(member, jingle_member_destroy);
}
}
cat = ast_category_browse(cfg, cat);
}
jingle_free_candidates(global_candidates);
return 1;
}
| static void jingle_member_destroy | ( | struct jingle * | obj | ) | [static] |
Definition at line 239 of file chan_jingle.c.
References ast_free.
Referenced by jingle_load_config(), jingle_parser(), and unload_module().
{
ast_free(obj);
}
| static struct ast_channel* jingle_new | ( | struct jingle * | client, |
| struct jingle_pvt * | i, | ||
| int | state, | ||
| const char * | title | ||
| ) | [static, read] |
Start new jingle channel.
Definition at line 800 of file chan_jingle.c.
References accountcode, jingle::accountcode, ast_channel::adsicpe, ast_channel::amaflags, jingle::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc(), ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), AST_FORMAT_VIDEO_MASK, ast_hangup(), ast_jb_configure(), ast_log(), ast_pbx_start(), ast_random(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), jingle::callgroup, ast_channel::callgroup, jingle::callingpres, jingle_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, jingle_pvt::cid_name, jingle_pvt::cid_num, ast_callerid::cid_pres, jingle::context, ast_channel::context, jingle_pvt::exten, ast_channel::exten, global_capability, global_jbconf, ast_channel::hangupcause, jingle_tech, jingle_pvt::jointcapability, language, jingle::language, LOG_WARNING, musicclass, jingle::musicclass, ast_channel::name, ast_channel::nativeformats, jingle_pvt::owner, jingle::pickupgroup, ast_channel::pickupgroup, jingle_pvt::prefs, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, jingle_pvt::rtp, str, ast_channel::tech, ast_channel::tech_pvt, jingle_pvt::them, jingle_pvt::vrtp, and ast_channel::writeformat.
Referenced by jingle_newcall(), and jingle_request().
{
struct ast_channel *tmp;
int fmt;
int what;
const char *str;
if (title)
str = title;
else
str = i->them;
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff);
if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
return NULL;
}
tmp->tech = &jingle_tech;
/* Select our native format based on codec preference until we receive
something from another device to the contrary. */
if (i->jointcapability)
what = i->jointcapability;
else if (i->capability)
what = i->capability;
else
what = global_capability;
/* Set Frame packetization */
if (i->rtp)
ast_rtp_codec_setpref(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_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
}
if (i->vrtp) {
ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
}
if (state == AST_STATE_RING)
tmp->rings = 1;
tmp->adsicpe = AST_ADSI_UNAVAILABLE;
tmp->writeformat = fmt;
tmp->rawwriteformat = fmt;
tmp->readformat = fmt;
tmp->rawreadformat = fmt;
tmp->tech_pvt = i;
tmp->callgroup = client->callgroup;
tmp->pickupgroup = client->pickupgroup;
tmp->cid.cid_pres = client->callingpres;
if (!ast_strlen_zero(client->accountcode))
ast_string_field_set(tmp, accountcode, client->accountcode);
if (client->amaflags)
tmp->amaflags = client->amaflags;
if (!ast_strlen_zero(client->language))
ast_string_field_set(tmp, language, client->language);
if (!ast_strlen_zero(client->musicclass))
ast_string_field_set(tmp, musicclass, client->musicclass);
i->owner = tmp;
ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
/* Don't use ast_set_callerid() here because it will
* generate an unnecessary NewCallerID event */
tmp->cid.cid_ani = ast_strdup(i->cid_num);
if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
tmp->cid.cid_dnid = ast_strdup(i->exten);
tmp->priority = 1;
if (i->rtp)
ast_jb_configure(tmp, &global_jbconf);
if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
ast_hangup(tmp);
tmp = NULL;
}
return tmp;
}
| static int jingle_newcall | ( | struct jingle * | client, |
| ikspak * | pak | ||
| ) | [static] |
Definition at line 954 of file chan_jingle.c.
References ast_aji_get_client(), ast_copy_string(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, jingle_pvt::audio_content_name, chan, jingle::connection, description, aji_client::jid, jingle_alloc(), JINGLE_AUDIO_RTP_NS, jingle_create_candidates(), jingle_free_pvt(), jingle_new(), JINGLE_NODE, jingle_response(), JINGLE_SID, JINGLE_VIDEO_RTP_NS, jingle_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, jingle::name, jingle_pvt::next, jingle::p, jingle_pvt::rtp, jingle_pvt::sid, jingle_pvt::them, and jingle_pvt::video_content_name.
Referenced by jingle_parser().
{
struct jingle_pvt *p, *tmp = client->p;
struct ast_channel *chan;
int res;
iks *codec, *content, *description;
char *from = NULL;
/* Make sure our new call doesn't exist yet */
from = iks_find_attrib(pak->x,"to");
if(!from)
from = client->connection->jid->full;
while (tmp) {
if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
jingle_response(client, pak, "out-of-order", NULL);
return -1;
}
tmp = tmp->next;
}
if (!strcasecmp(client->name, "guest")){
/* the guest account is not tied to any configured XMPP client,
let's set it now */
client->connection = ast_aji_get_client(from);
if (!client->connection) {
ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from);
return -1;
}
}
p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID));
if (!p) {
ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
return -1;
}
chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user);
if (!chan) {
jingle_free_pvt(client, p);
return -1;
}
ast_mutex_lock(&p->lock);
ast_copy_string(p->them, pak->from->full, sizeof(p->them));
if (iks_find_attrib(pak->query, JINGLE_SID)) {
ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID),
sizeof(p->sid));
}
/* content points to the first <content/> tag */
content = iks_child(iks_child(pak->x));
while (content) {
description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS);
if (description) {
/* audio content found */
codec = iks_child(iks_child(content));
ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
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);
codec = iks_next(codec);
}
}
description = NULL;
codec = NULL;
description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS);
if (description) {
/* video content found */
codec = iks_child(iks_child(content));
ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
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);
codec = iks_next(codec);
}
}
content = iks_next(content);
}
ast_mutex_unlock(&p->lock);
ast_setstate(chan, AST_STATE_RING);
res = ast_pbx_start(chan);
switch (res) {
case AST_PBX_FAILED:
ast_log(LOG_WARNING, "Failed to start PBX :(\n");
jingle_response(client, pak, "service-unavailable", NULL);
break;
case AST_PBX_CALL_LIMIT:
ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
jingle_response(client, pak, "service-unavailable", NULL);
break;
case AST_PBX_SUCCESS:
jingle_response(client, pak, NULL, NULL);
jingle_create_candidates(client, p,
iks_find_attrib(pak->query, JINGLE_SID),
iks_find_attrib(pak->x, "from"));
/* nothing to do */
break;
}
return 1;
}
| static int jingle_parser | ( | void * | data, |
| ikspak * | pak | ||
| ) | [static] |
Definition at line 1593 of file chan_jingle.c.
References ast_debug, ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, JINGLE_ACCEPT, jingle_add_candidate(), jingle_handle_dtmf(), jingle_hangup_farend(), JINGLE_INFO, JINGLE_INITIATE, jingle_is_answered(), jingle_member_destroy(), JINGLE_NEGOTIATE, jingle_newcall(), JINGLE_NODE, JINGLE_TERMINATE, and LOG_NOTICE.
Referenced by jingle_create_member(), and jingle_load_config().
{
struct jingle *client = ASTOBJ_REF((struct jingle *) data);
ast_log(LOG_NOTICE, "Filter matched\n");
if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
/* New call */
jingle_newcall(client, pak);
} else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
ast_debug(3, "About to add candidate!\n");
jingle_add_candidate(client, pak);
ast_debug(3, "Candidate Added!\n");
} else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
jingle_is_answered(client, pak);
} else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
jingle_handle_dtmf(client, pak);
} else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
jingle_hangup_farend(client, pak);
} else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
jingle_hangup_farend(client, pak);
}
ASTOBJ_UNREF(client, jingle_member_destroy);
return IKS_FILTER_EAT;
}
| static struct ast_frame * jingle_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 1195 of file chan_jingle.c.
References ast_mutex_lock(), ast_mutex_unlock(), jingle_rtp_read(), jingle_pvt::lock, and ast_channel::tech_pvt.
{
struct ast_frame *fr;
struct jingle_pvt *p = ast->tech_pvt;
ast_mutex_lock(&p->lock);
fr = jingle_rtp_read(ast, p);
ast_mutex_unlock(&p->lock);
return fr;
}
| static struct ast_channel * jingle_request | ( | const char * | type, |
| int | format, | ||
| void * | data, | ||
| int * | cause | ||
| ) | [static, read] |
Part of PBX interface.
Definition at line 1468 of file chan_jingle.c.
References ast_aji_get_client(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, chan, jingle::connection, find_jingle(), jingle_alloc(), jingle_new(), LOG_ERROR, LOG_WARNING, jingle::name, s, and strsep().
{
struct jingle_pvt *p = NULL;
struct jingle *client = NULL;
char *sender = NULL, *to = NULL, *s = NULL;
struct ast_channel *chan = NULL;
if (data) {
s = ast_strdupa(data);
if (s) {
sender = strsep(&s, "/");
if (sender && (sender[0] != '\0'))
to = strsep(&s, "/");
if (!to) {
ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data);
return NULL;
}
}
}
client = find_jingle(to, sender);
if (!client) {
ast_log(LOG_WARNING, "Could not find recipient.\n");
return NULL;
}
if (!strcasecmp(client->name, "guest")){
/* the guest account is not tied to any configured XMPP client,
let's set it now */
client->connection = ast_aji_get_client(sender);
if (!client->connection) {
ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
return NULL;
}
}
ASTOBJ_WRLOCK(client);
p = jingle_alloc(client, to, NULL);
if (p)
chan = jingle_new(client, p, AST_STATE_DOWN, to);
ASTOBJ_UNLOCK(client);
return chan;
}
| static int jingle_response | ( | struct jingle * | client, |
| ikspak * | pak, | ||
| const char * | reasonstr, | ||
| const char * | reasonstr2 | ||
| ) | [static] |
Definition at line 446 of file chan_jingle.c.
References ast_aji_send(), jingle::connection, and aji_client::jid.
Referenced by jingle_handle_dtmf(), jingle_hangup_farend(), jingle_is_answered(), and jingle_newcall().
{
iks *response = NULL, *error = NULL, *reason = NULL;
int res = -1;
response = iks_new("iq");
if (response) {
iks_insert_attrib(response, "type", "result");
iks_insert_attrib(response, "from", client->connection->jid->full);
iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
if (reasonstr) {
error = iks_new("error");
if (error) {
iks_insert_attrib(error, "type", "cancel");
reason = iks_new(reasonstr);
if (reason)
iks_insert_node(error, reason);
iks_insert_node(response, error);
}
}
ast_aji_send(client->connection, response);
res = 0;
}
iks_delete(reason);
iks_delete(error);
iks_delete(response);
return res;
}
| static int jingle_ringing_ack | ( | void * | data, |
| ikspak * | pak | ||
| ) | [static] |
Definition at line 377 of file chan_jingle.c.
References AST_CONTROL_RINGING, ast_queue_control(), jingle::connection, aji_client::f, jingle_pvt::owner, jingle_pvt::parent, and jingle_pvt::ringrule.
Referenced by jingle_call().
{
struct jingle_pvt *p = data;
if (p->ringrule)
iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
p->ringrule = NULL;
if (p->owner)
ast_queue_control(p->owner, AST_CONTROL_RINGING);
return IKS_FILTER_EAT;
}
| static struct ast_frame* jingle_rtp_read | ( | struct ast_channel * | ast, |
| struct jingle_pvt * | p | ||
| ) | [static, read] |
Definition at line 1167 of file chan_jingle.c.
References ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_VOICE, ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), f, ast_frame::frametype, jingle_update_stun(), ast_channel::nativeformats, jingle_pvt::owner, jingle_pvt::parent, ast_channel::readformat, jingle_pvt::rtp, ast_frame::subclass, and ast_channel::writeformat.
Referenced by jingle_read().
{
struct ast_frame *f;
if (!p->rtp)
return &ast_null_frame;
f = ast_rtp_read(p->rtp);
jingle_update_stun(p->parent, p);
if (p->owner) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
p->owner->nativeformats =
(p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
ast_set_read_format(p->owner, p->owner->readformat);
ast_set_write_format(p->owner, p->owner->writeformat);
}
/* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
f = ast_dsp_process(p->owner, p->vad, f);
if (f && (f->frametype == AST_FRAME_DTMF))
ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass);
} */
}
}
return f;
}
| static int jingle_sendhtml | ( | struct ast_channel * | ast, |
| int | subclass, | ||
| const char * | data, | ||
| int | datalen | ||
| ) | [static] |
Definition at line 1340 of file chan_jingle.c.
References ast_log(), and LOG_NOTICE.
{
ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
return -1;
}
| static int jingle_set_rtp_peer | ( | struct ast_channel * | chan, |
| struct ast_rtp * | rtp, | ||
| struct ast_rtp * | vrtp, | ||
| struct ast_rtp * | tpeer, | ||
| int | codecs, | ||
| int | nat_active | ||
| ) | [static] |
Definition at line 426 of file chan_jingle.c.
References ast_mutex_lock(), ast_mutex_unlock(), jingle_pvt::lock, and ast_channel::tech_pvt.
{
struct jingle_pvt *p;
p = chan->tech_pvt;
if (!p)
return -1;
ast_mutex_lock(&p->lock);
/* if (rtp)
ast_rtp_get_peer(rtp, &p->redirip);
else
memset(&p->redirip, 0, sizeof(p->redirip));
p->redircodecs = codecs; */
/* Reset lastrtprx timer */
ast_mutex_unlock(&p->lock);
return 0;
}
| static char * jingle_show_channels | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
CLI command "jingle show channels".
Definition at line 1513 of file chan_jingle.c.
References AJI_MAX_JIDLEN, ast_cli_args::argc, ast_cli(), ast_copy_string(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, chan, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, jingle_list, jinglelock, LOG_WARNING, ast_channel::name, jingle_pvt::next, jingle_pvt::owner, ast_channel::readformat, jingle_pvt::them, ast_cli_entry::usage, and ast_channel::writeformat.
{
#define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n"
struct jingle_pvt *p;
struct ast_channel *chan;
int numchans = 0;
char them[AJI_MAX_JIDLEN];
char *jid = NULL;
char *resource = NULL;
switch (cmd) {
case CLI_INIT:
e->command = "jingle show channels";
e->usage =
"Usage: jingle show channels\n"
" Shows current state of the Jingle channels.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
ast_mutex_lock(&jinglelock);
ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
ASTOBJ_WRLOCK(iterator);
p = iterator->p;
while(p) {
chan = p->owner;
ast_copy_string(them, p->them, sizeof(them));
jid = them;
resource = strchr(them, '/');
if (!resource)
resource = "None";
else {
*resource = '\0';
resource ++;
}
if (chan)
ast_cli(a->fd, FORMAT,
chan->name,
jid,
resource,
ast_getformatname(chan->readformat),
ast_getformatname(chan->writeformat)
);
else
ast_log(LOG_WARNING, "No available channel\n");
numchans ++;
p = p->next;
}
ASTOBJ_UNLOCK(iterator);
});
ast_mutex_unlock(&jinglelock);
ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : "");
return CLI_SUCCESS;
#undef FORMAT
}
| static int jingle_transmit_invite | ( | struct jingle_pvt * | p | ) | [static] |
Definition at line 1346 of file chan_jingle.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle_pvt::audio_content_name, jingle::connection, description, aji_client::jid, aji_client::jingle, JINGLE_AUDIO_RTP_NS, JINGLE_ICE_UDP_NS, JINGLE_INITIATE, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, jingle_pvt::parent, jingle_pvt::sid, and jingle_pvt::them.
Referenced by jingle_call().
{
struct jingle *aux = NULL;
struct aji_client *client = NULL;
iks *iq, *jingle, *content, *description, *transport;
iks *payload_eg711u, *payload_pcmu;
aux = p->parent;
client = aux->connection;
iq = iks_new("iq");
jingle = iks_new(JINGLE_NODE);
content = iks_new("content");
description = iks_new("description");
transport = iks_new("transport");
payload_pcmu = iks_new("payload-type");
payload_eg711u = iks_new("payload-type");
ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name));
iks_insert_attrib(iq, "type", "set");
iks_insert_attrib(iq, "to", p->them);
iks_insert_attrib(iq, "from", client->jid->full);
iks_insert_attrib(iq, "id", client->mid);
ast_aji_increment_mid(client->mid);
iks_insert_attrib(jingle, "action", JINGLE_INITIATE);
iks_insert_attrib(jingle, JINGLE_SID, p->sid);
iks_insert_attrib(jingle, "initiator", client->jid->full);
iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
/* For now, we only send one audio based content */
iks_insert_attrib(content, "creator", "initiator");
iks_insert_attrib(content, "name", p->audio_content_name);
iks_insert_attrib(content, "profile", "RTP/AVP");
iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS);
iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
iks_insert_attrib(payload_pcmu, "id", "0");
iks_insert_attrib(payload_pcmu, "name", "PCMU");
iks_insert_attrib(payload_eg711u, "id", "100");
iks_insert_attrib(payload_eg711u, "name", "EG711U");
iks_insert_node(description, payload_pcmu);
iks_insert_node(description, payload_eg711u);
iks_insert_node(content, description);
iks_insert_node(content, transport);
iks_insert_node(jingle, content);
iks_insert_node(iq, jingle);
ast_aji_send(client, iq);
iks_delete(iq);
iks_delete(jingle);
iks_delete(content);
iks_delete(description);
iks_delete(transport);
iks_delete(payload_eg711u);
iks_delete(payload_pcmu);
return 0;
}
| static int jingle_update_stun | ( | struct jingle * | client, |
| struct jingle_pvt * | p | ||
| ) | [static] |
Definition at line 1063 of file chan_jingle.c.
References ast_gethostbyname(), ast_rtp_stun_request(), hp, jingle_candidate::ip, jingle_pvt::laststun, jingle_candidate::next, jingle_pvt::ourcandidates, jingle_candidate::port, jingle_pvt::rtp, jingle_pvt::theircandidates, and jingle_candidate::ufrag.
Referenced by jingle_add_candidate(), and jingle_rtp_read().
{
struct jingle_candidate *tmp;
struct hostent *hp;
struct ast_hostent ahp;
struct sockaddr_in sin;
if (time(NULL) == p->laststun)
return 0;
tmp = p->theircandidates;
p->laststun = time(NULL);
while (tmp) {
char username[256];
hp = ast_gethostbyname(tmp->ip, &ahp);
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
sin.sin_port = htons(tmp->port);
snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
ast_rtp_stun_request(p->rtp, &sin, username);
tmp = tmp->next;
}
return 1;
}
| static int jingle_write | ( | struct ast_channel * | ast, |
| struct ast_frame * | f | ||
| ) | [static] |
Send frame to media channel (rtp)
Definition at line 1207 of file chan_jingle.c.
References AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, jingle_pvt::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, jingle_pvt::rtp, ast_frame::subclass, ast_channel::tech_pvt, jingle_pvt::vrtp, and ast_channel::writeformat.
{
struct jingle_pvt *p = ast->tech_pvt;
int res = 0;
switch (frame->frametype) {
case AST_FRAME_VOICE:
if (!(frame->subclass & ast->nativeformats)) {
ast_log(LOG_WARNING,
"Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
frame->subclass, ast->nativeformats, ast->readformat,
ast->writeformat);
return 0;
}
if (p) {
ast_mutex_lock(&p->lock);
if (p->rtp) {
res = ast_rtp_write(p->rtp, frame);
}
ast_mutex_unlock(&p->lock);
}
break;
case AST_FRAME_VIDEO:
if (p) {
ast_mutex_lock(&p->lock);
if (p->vrtp) {
res = ast_rtp_write(p->vrtp, frame);
}
ast_mutex_unlock(&p->lock);
}
break;
case AST_FRAME_IMAGE:
return 0;
break;
default:
ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n",
frame->frametype);
return 0;
}
return res;
}
| static int load_module | ( | void | ) | [static] |
Load module into PBX, register channel.
Definition at line 1850 of file chan_jingle.c.
References __ourip, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_find_ourip(), ast_log(), ast_module_helper(), AST_MODULE_LOAD_DECLINE, ast_rtp_proto_register(), ASTOBJ_CONTAINER_INIT, free, io_context_create(), JINGLE_CONFIG, jingle_list, jingle_load_config(), LOG_ERROR, LOG_WARNING, and sched_context_create().
{
char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
free(jabber_loaded);
if (!jabber_loaded) {
/* Dependency module has a different name, if embedded */
jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
free(jabber_loaded);
if (!jabber_loaded) {
ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n");
return AST_MODULE_LOAD_DECLINE;
}
}
ASTOBJ_CONTAINER_INIT(&jingle_list);
if (!jingle_load_config()) {
ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
return AST_MODULE_LOAD_DECLINE;
}
sched = sched_context_create();
if (!sched)
ast_log(LOG_WARNING, "Unable to create schedule context\n");
io = io_context_create();
if (!io)
ast_log(LOG_WARNING, "Unable to create I/O context\n");
if (ast_find_ourip(&__ourip, bindaddr)) {
ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
return 0;
}
ast_rtp_proto_register(&jingle_rtp);
ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
/* Make sure we can register our channel type */
if (ast_channel_register(&jingle_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
return -1;
}
return 0;
}
| static int reload | ( | void | ) | [static] |
| static int unload_module | ( | void | ) | [static] |
Unload the jingle channel from Asterisk.
Definition at line 1900 of file chan_jingle.c.
References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, jingle_list, jingle_member_destroy(), jinglelock, LOG_WARNING, jingle_pvt::next, and jingle_pvt::owner.
{
struct jingle_pvt *privates = NULL;
ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
/* First, take us out of the channel loop */
ast_channel_unregister(&jingle_tech);
ast_rtp_proto_unregister(&jingle_rtp);
if (!ast_mutex_lock(&jinglelock)) {
/* Hangup all interfaces if they have an owner */
ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
ASTOBJ_WRLOCK(iterator);
privates = iterator->p;
while(privates) {
if (privates->owner)
ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
privates = privates->next;
}
iterator->p = NULL;
ASTOBJ_UNLOCK(iterator);
});
ast_mutex_unlock(&jinglelock);
} else {
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
return -1;
}
ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
ASTOBJ_CONTAINER_DESTROY(&jingle_list);
return 0;
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Jingle Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1935 of file chan_jingle.c.
struct in_addr __ourip [static] |
Definition at line 218 of file chan_jingle.c.
Referenced by jingle_create_candidates(), and load_module().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1935 of file chan_jingle.c.
struct sockaddr_in bindaddr = { 0, } [static] |
The address we bind to
Definition at line 214 of file chan_jingle.c.
const char channel_type[] = "Jingle" [static] |
Definition at line 165 of file chan_jingle.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 75 of file chan_jingle.c.
const char desc[] = "Jingle Channel" [static] |
Definition at line 164 of file chan_jingle.c.
char externip[16] [static] |
Definition at line 235 of file chan_jingle.c.
int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 [static] |
Definition at line 167 of file chan_jingle.c.
Referenced by jingle_new().
struct ast_jb_conf global_jbconf [static] |
Definition at line 83 of file chan_jingle.c.
Referenced by jingle_load_config(), and jingle_new().
struct io_context* io [static] |
The IO context
Definition at line 217 of file chan_jingle.c.
struct ast_cli_entry jingle_cli[] [static] |
{
AST_CLI_DEFINE(jingle_do_reload, "Reload Jingle configuration"),
AST_CLI_DEFINE(jingle_show_channels, "Show Jingle channels"),
}
Definition at line 229 of file chan_jingle.c.
struct jingle_container jingle_list [static] |
Definition at line 237 of file chan_jingle.c.
Referenced by find_jingle(), jingle_load_config(), jingle_show_channels(), load_module(), and unload_module().
struct ast_rtp_protocol jingle_rtp [static] |
RTP driver interface.
Definition at line 222 of file chan_jingle.c.
struct ast_channel_tech jingle_tech [static] |
PBX interface structure for channel registration.
Definition at line 194 of file chan_jingle.c.
Referenced by jingle_new().
ast_mutex_t jinglelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the interface list (of jingle_pvt's)
Definition at line 169 of file chan_jingle.c.
Referenced by jingle_alloc(), jingle_show_channels(), and unload_module().
struct sched_context* sched [static] |
The scheduling context
Definition at line 216 of file chan_jingle.c.