Sat Feb 11 06:34:36 2012

Asterisk developer's documentation


chan_jingle.c File Reference

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_engine.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"

Include dependency graph for chan_jingle.c:

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, struct ast_format *codec, iks *dcodecs)
static struct jinglefind_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_pvtjingle_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, const 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 void jingle_get_codec (struct ast_channel *chan, struct ast_format_cap *result)
static enum ast_rtp_glue_result jingle_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
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_channeljingle_new (struct jingle *client, struct jingle_pvt *i, int state, const char *title, const char *linkedid)
 Start new jingle channel.
static int jingle_newcall (struct jingle *client, ikspak *pak)
static int jingle_parser (void *data, ikspak *pak)
static struct ast_framejingle_read (struct ast_channel *ast)
static struct ast_channeljingle_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *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_framejingle_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_sendtext (struct ast_channel *ast, const char *text)
static int jingle_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, const struct ast_format_cap *cap, 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_LOAD_ORDER , .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, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
static struct in_addr __ourip
static struct ast_module_infoast_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 struct ast_format_capglobal_capability
static struct ast_jb_conf global_jbconf
static struct io_contextio
static struct ast_cli_entry jingle_cli []
static struct jingle_container jingle_list
static struct ast_rtp_glue jingle_rtp_glue
static struct ast_channel_tech jingle_tech
 PBX interface structure for channel registration.
static ast_mutex_t jinglelock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static struct ast_sched_contextsched


Detailed Description

Jingle Channel Driver.

Author:
Matt O'Gorman <mogorman@digium.com>
ExtRef:
Iksemel http://iksemel.jabberstudio.org/

Definition in file chan_jingle.c.


Define Documentation

#define FORMAT   "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n"

#define JINGLE_CONFIG   "jingle.conf"

Definition at line 74 of file chan_jingle.c.

Referenced by jingle_load_config(), and load_module().


Enumeration Type Documentation

Enumerator:
AJI_CONNECT_HOST 
AJI_CONNECT_PRFLX 
AJI_CONNECT_RELAY 
AJI_CONNECT_SRFLX 

Definition at line 92 of file chan_jingle.c.

00092                          {
00093    AJI_CONNECT_HOST,
00094    AJI_CONNECT_PRFLX,
00095    AJI_CONNECT_RELAY,
00096    AJI_CONNECT_SRFLX,
00097 };

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 87 of file chan_jingle.c.

00087                      {
00088    AJI_PROTOCOL_UDP,
00089    AJI_PROTOCOL_SSLTCP,
00090 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 2044 of file chan_jingle.c.

static void __unreg_module ( void   )  [static]

Definition at line 2044 of file chan_jingle.c.

static void add_codec_to_answer ( const struct jingle_pvt p,
struct ast_format codec,
iks *  dcodecs 
) [static]

Definition at line 268 of file chan_jingle.c.

References ast_getformatname(), and format.

00269 {
00270    const char *format = ast_getformatname(codec);
00271 
00272    if (!strcasecmp("ulaw", format)) {
00273       iks *payload_eg711u, *payload_pcmu;
00274       payload_pcmu = iks_new("payload-type");
00275       iks_insert_attrib(payload_pcmu, "id", "0");
00276       iks_insert_attrib(payload_pcmu, "name", "PCMU");
00277       payload_eg711u = iks_new("payload-type");
00278       iks_insert_attrib(payload_eg711u, "id", "100");
00279       iks_insert_attrib(payload_eg711u, "name", "EG711U");
00280       iks_insert_node(dcodecs, payload_pcmu);
00281       iks_insert_node(dcodecs, payload_eg711u);
00282    }
00283    if (!strcasecmp("alaw", format)) {
00284       iks *payload_eg711a;
00285       iks *payload_pcma = iks_new("payload-type");
00286       iks_insert_attrib(payload_pcma, "id", "8");
00287       iks_insert_attrib(payload_pcma, "name", "PCMA");
00288       payload_eg711a = iks_new("payload-type");
00289       iks_insert_attrib(payload_eg711a, "id", "101");
00290       iks_insert_attrib(payload_eg711a, "name", "EG711A");
00291       iks_insert_node(dcodecs, payload_pcma);
00292       iks_insert_node(dcodecs, payload_eg711a);
00293    }
00294    if (!strcasecmp("ilbc", format)) {
00295       iks *payload_ilbc = iks_new("payload-type");
00296       iks_insert_attrib(payload_ilbc, "id", "97");
00297       iks_insert_attrib(payload_ilbc, "name", "iLBC");
00298       iks_insert_node(dcodecs, payload_ilbc);
00299    }
00300    if (!strcasecmp("g723", format)) {
00301       iks *payload_g723 = iks_new("payload-type");
00302       iks_insert_attrib(payload_g723, "id", "4");
00303       iks_insert_attrib(payload_g723, "name", "G723");
00304       iks_insert_node(dcodecs, payload_g723);
00305    }
00306 }

static struct jingle* find_jingle ( char *  name,
char *  connection 
) [static, read]

Definition at line 242 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().

00243 {
00244    struct jingle *jingle = NULL;
00245 
00246    jingle = ASTOBJ_CONTAINER_FIND(&jingle_list, name);
00247    if (!jingle && strchr(name, '@'))
00248       jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingle_list, name, user,,, strcasecmp);
00249 
00250    if (!jingle) {          
00251       /* guest call */
00252       ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
00253          ASTOBJ_RDLOCK(iterator);
00254          if (!strcasecmp(iterator->name, "guest")) {
00255             jingle = iterator;
00256          }
00257          ASTOBJ_UNLOCK(iterator);
00258 
00259          if (jingle)
00260             break;
00261       });
00262 
00263    }
00264    return jingle;
00265 }

static int jingle_accept_call ( struct jingle client,
struct jingle_pvt p 
) [static]

Definition at line 308 of file chan_jingle.c.

References add_codec_to_answer(), ast_aji_increment_mid(), ast_aji_send(), ast_codec_pref_index(), AST_CODEC_PREF_SIZE, ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_iscompatible(), jingle::cap, jingle::connection, jingle_pvt::initiator, aji_client::jid, 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().

00309 {
00310    struct jingle_pvt *tmp = client->p;
00311    struct aji_client *c = client->connection;
00312    iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn;
00313    int x;
00314    struct ast_format pref_codec;
00315    struct ast_format_cap *alreadysent = ast_format_cap_alloc_nolock();
00316 
00317    if (p->initiator || !alreadysent)
00318       return 1;
00319 
00320    iq = iks_new("iq");
00321    jingle = iks_new(JINGLE_NODE);
00322    dcodecs = iks_new("description");
00323    if (iq && jingle && dcodecs) {
00324       iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS);
00325 
00326       for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
00327          if (!(ast_codec_pref_index(&client->prefs, x, &pref_codec)))
00328             break;
00329          if (!(ast_format_cap_iscompatible(client->cap, &pref_codec)))
00330             continue;
00331          if ((ast_format_cap_iscompatible(alreadysent, &pref_codec)))
00332             continue;
00333          add_codec_to_answer(p, &pref_codec, dcodecs);
00334          ast_format_cap_add(alreadysent, &pref_codec);
00335       }
00336       payload_red = iks_new("payload-type");
00337       iks_insert_attrib(payload_red, "id", "117");
00338       iks_insert_attrib(payload_red, "name", "red");
00339       payload_audio = iks_new("payload-type");
00340       iks_insert_attrib(payload_audio, "id", "106");
00341       iks_insert_attrib(payload_audio, "name", "audio/telephone-event");
00342       payload_cn = iks_new("payload-type");
00343       iks_insert_attrib(payload_cn, "id", "13");
00344       iks_insert_attrib(payload_cn, "name", "CN");
00345 
00346 
00347       iks_insert_attrib(iq, "type", "set");
00348       iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user);
00349       iks_insert_attrib(iq, "id", client->connection->mid);
00350       ast_aji_increment_mid(client->connection->mid);
00351 
00352       iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00353       iks_insert_attrib(jingle, "action", JINGLE_ACCEPT);
00354       iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
00355       iks_insert_attrib(jingle, JINGLE_SID, tmp->sid);
00356       iks_insert_node(iq, jingle);
00357       iks_insert_node(jingle, dcodecs);
00358       iks_insert_node(dcodecs, payload_red);
00359       iks_insert_node(dcodecs, payload_audio);
00360       iks_insert_node(dcodecs, payload_cn);
00361 
00362       ast_aji_send(c, iq);
00363 
00364       iks_delete(payload_red);
00365       iks_delete(payload_audio);
00366       iks_delete(payload_cn);
00367       iks_delete(dcodecs);
00368       iks_delete(jingle);
00369       iks_delete(iq);
00370    }
00371    alreadysent = ast_format_cap_destroy(alreadysent);
00372    return 1;
00373 }

static int jingle_action ( struct jingle client,
struct jingle_pvt p,
const char *  action 
) [static]

Definition at line 928 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().

00929 {
00930    iks *iq, *jingle = NULL;
00931    int res = -1;
00932 
00933    iq = iks_new("iq");
00934    jingle = iks_new("jingle");
00935    
00936    if (iq) {
00937       iks_insert_attrib(iq, "type", "set");
00938       iks_insert_attrib(iq, "from", client->connection->jid->full);
00939       iks_insert_attrib(iq, "to", p->them);
00940       iks_insert_attrib(iq, "id", client->connection->mid);
00941       ast_aji_increment_mid(client->connection->mid);
00942       if (jingle) {
00943          iks_insert_attrib(jingle, "action", action);
00944          iks_insert_attrib(jingle, JINGLE_SID, p->sid);
00945          iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
00946          iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00947 
00948          iks_insert_node(iq, jingle);
00949 
00950          ast_aji_send(client->connection, iq);
00951          res = 0;
00952       }
00953    }
00954    
00955    iks_delete(jingle);
00956    iks_delete(iq);
00957    
00958    return res;
00959 }

static int jingle_add_candidate ( struct jingle client,
ikspak *  pak 
) [static]

Definition at line 1143 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().

01144 {
01145    struct jingle_pvt *p = NULL, *tmp = NULL;
01146    struct aji_client *c = client->connection;
01147    struct jingle_candidate *newcandidate = NULL;
01148    iks *traversenodes = NULL, *receipt = NULL;
01149 
01150    for (tmp = client->p; tmp; tmp = tmp->next) {
01151       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
01152          p = tmp;
01153          break;
01154       }
01155    }
01156 
01157    if (!p)
01158       return -1;
01159 
01160    traversenodes = pak->query;
01161    while(traversenodes) {
01162       if(!strcasecmp(iks_name(traversenodes), "jingle")) {
01163          traversenodes = iks_child(traversenodes);
01164          continue;
01165       }
01166       if(!strcasecmp(iks_name(traversenodes), "content")) {
01167          traversenodes = iks_child(traversenodes);
01168          continue;
01169       }
01170       if(!strcasecmp(iks_name(traversenodes), "transport")) {
01171          traversenodes = iks_child(traversenodes);
01172          continue;
01173       }
01174 
01175       if(!strcasecmp(iks_name(traversenodes), "candidate")) {
01176          newcandidate = ast_calloc(1, sizeof(*newcandidate));
01177          if (!newcandidate)
01178             return 0;
01179          ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip));
01180          newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
01181          ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password));
01182          if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
01183             newcandidate->protocol = AJI_PROTOCOL_UDP;
01184          else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
01185             newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
01186          
01187          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host"))
01188             newcandidate->type = AJI_CONNECT_HOST;
01189          else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx"))
01190             newcandidate->type = AJI_CONNECT_PRFLX;
01191          else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
01192             newcandidate->type = AJI_CONNECT_RELAY;
01193          else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx"))
01194             newcandidate->type = AJI_CONNECT_SRFLX;
01195 
01196          newcandidate->network = atoi(iks_find_attrib(traversenodes, "network"));
01197          newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
01198          newcandidate->next = NULL;
01199       
01200          newcandidate->next = p->theircandidates;
01201          p->theircandidates = newcandidate;
01202          p->laststun = 0;
01203          jingle_update_stun(p->parent, p);
01204          newcandidate = NULL;
01205       }
01206       traversenodes = iks_next(traversenodes);
01207    }
01208    
01209    receipt = iks_new("iq");
01210    iks_insert_attrib(receipt, "type", "result");
01211    iks_insert_attrib(receipt, "from", c->jid->full);
01212    iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
01213    iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
01214    ast_aji_send(c, receipt);
01215 
01216    iks_delete(receipt);
01217 
01218    return 1;
01219 }

static struct jingle_pvt * jingle_alloc ( struct jingle client,
const char *  from,
const char *  sid 
) [static, read]

Definition at line 751 of file chan_jingle.c.

References ast_aji_buddy_destroy(), ast_calloc, ast_copy_string(), ast_debug, ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_free, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_rtp_instance_new(), ast_sockaddr_from_sin, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, aji_client::buddies, jingle::buddy, jingle_pvt::cap, aji_resource::cap, jingle::connection, jingle_pvt::exten, jingle_pvt::initiator, aji_version::jingle, jinglelock, jingle_pvt::jointcap, jingle_pvt::lock, LOG_ERROR, LOG_WARNING, jingle::name, jingle_pvt::next, aji_resource::next, jingle::p, jingle_pvt::parent, jingle_pvt::peercap, 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().

00752 {
00753    struct jingle_pvt *tmp = NULL;
00754    struct aji_resource *resources = NULL;
00755    struct aji_buddy *buddy = NULL;
00756    char idroster[200];
00757    struct ast_sockaddr bindaddr_tmp;
00758 
00759    ast_debug(1, "The client is %s for alloc\n", client->name);
00760    if (!sid && !strchr(from, '/')) {   /* I started call! */
00761       if (!strcasecmp(client->name, "guest")) {
00762          buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from);
00763          if (buddy) {
00764             resources = buddy->resources;
00765          }
00766       } else if (client->buddy)
00767          resources = client->buddy->resources;
00768       while (resources) {
00769          if (resources->cap->jingle) {
00770             break;
00771          }
00772          resources = resources->next;
00773       }
00774       if (resources)
00775          snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource);
00776       else {
00777          ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n");
00778          if (buddy) {
00779             ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
00780          }
00781          return NULL;
00782       }
00783       if (buddy) {
00784          ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
00785       }
00786    }
00787    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00788       return NULL;
00789    }
00790 
00791    tmp->cap = ast_format_cap_alloc_nolock();
00792    tmp->jointcap = ast_format_cap_alloc_nolock();
00793    tmp->peercap = ast_format_cap_alloc_nolock();
00794    if (!tmp->cap || !tmp->jointcap || !tmp->peercap) {
00795       tmp->cap = ast_format_cap_destroy(tmp->cap);
00796       tmp->jointcap = ast_format_cap_destroy(tmp->jointcap);
00797       tmp->peercap = ast_format_cap_destroy(tmp->peercap);
00798       ast_free(tmp);
00799       return NULL;
00800    }
00801    memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
00802 
00803    if (sid) {
00804       ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00805       ast_copy_string(tmp->them, from, sizeof(tmp->them));
00806    } else {
00807       snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00808       ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00809       tmp->initiator = 1;
00810    }
00811    ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
00812    tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
00813    tmp->parent = client;
00814    if (!tmp->rtp) {
00815       ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00816       ast_free(tmp);
00817       return NULL;
00818    }
00819    ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
00820    ast_mutex_init(&tmp->lock);
00821    ast_mutex_lock(&jinglelock);
00822    tmp->next = client->p;
00823    client->p = tmp;
00824    ast_mutex_unlock(&jinglelock);
00825    return tmp;
00826 }

static int jingle_answer ( struct ast_channel ast  )  [static]

Definition at line 387 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.

00388 {
00389    struct jingle_pvt *p = ast->tech_pvt;
00390    struct jingle *client = p->parent;
00391    int res = 0;
00392 
00393    ast_debug(1, "Answer!\n");
00394    ast_mutex_lock(&p->lock);
00395    jingle_accept_call(client, p);
00396    ast_mutex_unlock(&p->lock);
00397    return res;
00398 }

static int jingle_call ( struct ast_channel ast,
const char *  dest,
int  timeout 
) [static]

Initiate new call, part of PBX interface dest is the dial string.

Definition at line 1501 of file chan_jingle.c.

References ast_channel::_state, ast_channel_name(), ast_copy_string(), ast_format_cap_copy(), ast_log(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RING, jingle_pvt::cap, jingle::connection, aji_client::f, jingle_create_candidates(), jingle_ringing_ack(), jingle_transmit_invite(), jingle_pvt::jointcap, LOG_WARNING, aji_client::mid, jingle_pvt::parent, jingle_pvt::ring, jingle_pvt::ringrule, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.

01502 {
01503    struct jingle_pvt *p = ast->tech_pvt;
01504 
01505    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01506       ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
01507       return -1;
01508    }
01509 
01510    ast_setstate(ast, AST_STATE_RING);
01511    ast_format_cap_copy(p->jointcap, p->cap);
01512    if (!p->ringrule) {
01513       ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01514       p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
01515                      IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01516    } else
01517       ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01518 
01519    jingle_transmit_invite(p);
01520    jingle_create_candidates(p->parent, p, p->sid, p->them);
01521 
01522    return 0;
01523 }

static int jingle_create_candidates ( struct jingle client,
struct jingle_pvt p,
char *  sid,
char *  from 
) [static]

Definition at line 591 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_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_find_ourip(), ast_free, ast_inet_ntoa(), ast_log(), ast_random(), ast_rtp_instance_get_local_address(), ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ast_sockaddr_to_sin, 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().

00592 {
00593    struct jingle_candidate *tmp;
00594    struct aji_client *c = client->connection;
00595    struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
00596    struct sockaddr_in sin = { 0, };
00597    struct ast_sockaddr sin_tmp;
00598    struct ast_sockaddr us_tmp;
00599    struct ast_sockaddr bindaddr_tmp;
00600    struct in_addr us;
00601    struct in_addr externaddr;
00602    iks *iq, *jingle, *content, *transport, *candidate;
00603    char component[16], foundation[16], generation[16], network[16], pass[16], port[7], priority[16], user[16];
00604 
00605 
00606    iq = iks_new("iq");
00607    jingle = iks_new(JINGLE_NODE);
00608    content = iks_new("content");
00609    transport = iks_new("transport");
00610    candidate = iks_new("candidate");
00611    if (!iq || !jingle || !content || !transport || !candidate) {
00612       ast_log(LOG_ERROR, "Memory allocation error\n");
00613       goto safeout;
00614    }
00615    ours1 = ast_calloc(1, sizeof(*ours1));
00616    ours2 = ast_calloc(1, sizeof(*ours2));
00617    if (!ours1 || !ours2)
00618       goto safeout;
00619 
00620    iks_insert_node(iq, jingle);
00621    iks_insert_node(jingle, content);
00622    iks_insert_node(content, transport);
00623    iks_insert_node(transport, candidate);
00624 
00625    for (; p; p = p->next) {
00626       if (!strcasecmp(p->sid, sid))
00627          break;
00628    }
00629 
00630    if (!p) {
00631       ast_log(LOG_NOTICE, "No matching jingle session - SID %s!\n", sid);
00632       goto safeout;
00633    }
00634 
00635    ast_rtp_instance_get_local_address(p->rtp, &sin_tmp);
00636    ast_sockaddr_to_sin(&sin_tmp, &sin);
00637    ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
00638    ast_find_ourip(&us_tmp, &bindaddr_tmp, AF_INET);
00639    us.s_addr = htonl(ast_sockaddr_ipv4(&us_tmp));
00640 
00641    /* Setup our first jingle candidate */
00642    ours1->component = 1;
00643    ours1->foundation = (unsigned int)bindaddr.sin_addr.s_addr | AJI_CONNECT_HOST | AJI_PROTOCOL_UDP;
00644    ours1->generation = 0;
00645    ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
00646    ours1->network = 0;
00647    ours1->port = ntohs(sin.sin_port);
00648    ours1->priority = 1678246398;
00649    ours1->protocol = AJI_PROTOCOL_UDP;
00650    snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00651    ast_copy_string(ours1->password, pass, sizeof(ours1->password));
00652    ours1->type = AJI_CONNECT_HOST;
00653    snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00654    ast_copy_string(ours1->ufrag, user, sizeof(ours1->ufrag));
00655    p->ourcandidates = ours1;
00656 
00657    if (!ast_strlen_zero(externip)) {
00658       /* XXX We should really stun for this one not just go with externip XXX */
00659       if (inet_aton(externip, &externaddr))
00660          ast_log(LOG_WARNING, "Invalid extern IP : %s\n", externip);
00661 
00662       ours2->component = 1;
00663       ours2->foundation = (unsigned int)externaddr.s_addr | AJI_CONNECT_PRFLX | AJI_PROTOCOL_UDP;
00664       ours2->generation = 0;
00665       ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
00666       ours2->network = 0;
00667       ours2->port = ntohs(sin.sin_port);
00668       ours2->priority = 1678246397;
00669       ours2->protocol = AJI_PROTOCOL_UDP;
00670       snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00671       ast_copy_string(ours2->password, pass, sizeof(ours2->password));
00672       ours2->type = AJI_CONNECT_PRFLX;
00673 
00674       snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00675       ast_copy_string(ours2->ufrag, user, sizeof(ours2->ufrag));
00676       ours1->next = ours2;
00677       ours2 = NULL;
00678    }
00679    ours1 = NULL;
00680 
00681    for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
00682       snprintf(component, sizeof(component), "%u", tmp->component);
00683       snprintf(foundation, sizeof(foundation), "%u", tmp->foundation);
00684       snprintf(generation, sizeof(generation), "%u", tmp->generation);
00685       snprintf(network, sizeof(network), "%u", tmp->network);
00686       snprintf(port, sizeof(port), "%u", tmp->port);
00687       snprintf(priority, sizeof(priority), "%u", tmp->priority);
00688 
00689       iks_insert_attrib(iq, "from", c->jid->full);
00690       iks_insert_attrib(iq, "to", from);
00691       iks_insert_attrib(iq, "type", "set");
00692       iks_insert_attrib(iq, "id", c->mid);
00693       ast_aji_increment_mid(c->mid);
00694       iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE);
00695       iks_insert_attrib(jingle, JINGLE_SID, sid);
00696       iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from);
00697       iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00698       iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder");
00699       iks_insert_attrib(content, "name", "asterisk-audio-content");
00700       iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
00701       iks_insert_attrib(candidate, "component", component);
00702       iks_insert_attrib(candidate, "foundation", foundation);
00703       iks_insert_attrib(candidate, "generation", generation);
00704       iks_insert_attrib(candidate, "ip", tmp->ip);
00705       iks_insert_attrib(candidate, "network", network);
00706       iks_insert_attrib(candidate, "port", port);
00707       iks_insert_attrib(candidate, "priority", priority);
00708       switch (tmp->protocol) {
00709       case AJI_PROTOCOL_UDP:
00710          iks_insert_attrib(candidate, "protocol", "udp");
00711          break;
00712       case AJI_PROTOCOL_SSLTCP:
00713          iks_insert_attrib(candidate, "protocol", "ssltcp");
00714          break;
00715       }
00716       iks_insert_attrib(candidate, "pwd", tmp->password);
00717       switch (tmp->type) {
00718       case AJI_CONNECT_HOST:
00719          iks_insert_attrib(candidate, "type", "host");
00720          break;
00721       case AJI_CONNECT_PRFLX:
00722          iks_insert_attrib(candidate, "type", "prflx");
00723          break;
00724       case AJI_CONNECT_RELAY:
00725          iks_insert_attrib(candidate, "type", "relay");
00726          break;
00727       case AJI_CONNECT_SRFLX:
00728          iks_insert_attrib(candidate, "type", "srflx");
00729          break;
00730       }
00731       iks_insert_attrib(candidate, "ufrag", tmp->ufrag);
00732 
00733       ast_aji_send(c, iq);
00734    }
00735    p->laststun = 0;
00736 
00737 safeout:
00738    if (ours1)
00739       ast_free(ours1);
00740    if (ours2)
00741       ast_free(ours2);
00742    iks_delete(iq);
00743    iks_delete(jingle);
00744    iks_delete(content);
00745    iks_delete(transport);
00746    iks_delete(candidate);
00747 
00748    return 1;
00749 }

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 1746 of file chan_jingle.c.

References jingle::allowguest, ast_aji_get_client(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, jingle::buddy, jingle::cap, 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, jingle::prefs, jingle::user, and ast_variable::value.

Referenced by jingle_load_config().

01749 {
01750    struct aji_client *client;
01751 
01752    if (!member)
01753       ast_log(LOG_WARNING, "Out of memory.\n");
01754 
01755    ast_copy_string(member->name, label, sizeof(member->name));
01756    ast_copy_string(member->user, label, sizeof(member->user));
01757    ast_copy_string(member->context, context, sizeof(member->context));
01758    member->allowguest = allowguest;
01759    member->prefs = prefs;
01760    while (var) {
01761 #if 0
01762       struct jingle_candidate *candidate = NULL;
01763 #endif
01764       if (!strcasecmp(var->name, "username"))
01765          ast_copy_string(member->user, var->value, sizeof(member->user));
01766       else if (!strcasecmp(var->name, "disallow"))
01767          ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 0);
01768       else if (!strcasecmp(var->name, "allow"))
01769          ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 1);
01770       else if (!strcasecmp(var->name, "context"))
01771          ast_copy_string(member->context, var->value, sizeof(member->context));
01772 #if 0
01773       else if (!strcasecmp(var->name, "candidate")) {
01774          candidate = jingle_create_candidate(var->value);
01775          if (candidate) {
01776             candidate->next = member->ourcandidates;
01777             member->ourcandidates = candidate;
01778          }
01779       }
01780 #endif
01781       else if (!strcasecmp(var->name, "connection")) {
01782          if ((client = ast_aji_get_client(var->value))) {
01783             member->connection = client;
01784             iks_filter_add_rule(client->f, jingle_parser, member,
01785                       IKS_RULE_TYPE, IKS_PAK_IQ,
01786                       IKS_RULE_FROM_PARTIAL, member->user,
01787                       IKS_RULE_NS, JINGLE_NS,
01788                       IKS_RULE_DONE);
01789          } else {
01790             ast_log(LOG_ERROR, "connection referenced not found!\n");
01791             return 0;
01792          }
01793       }
01794       var = var->next;
01795    }
01796    if (member->connection && member->user)
01797       member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
01798    else {
01799       ast_log(LOG_ERROR, "No Connection or Username!\n");
01800    }
01801    return 1;
01802 }

static int jingle_digit ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 1361 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().

01362 {
01363    struct jingle_pvt *p = ast->tech_pvt;
01364    struct jingle *client = p->parent;
01365    iks *iq, *jingle, *dtmf;
01366    char buffer[2] = {digit, '\0'};
01367    iq = iks_new("iq");
01368    jingle = iks_new("jingle");
01369    dtmf = iks_new("dtmf");
01370    if(!iq || !jingle || !dtmf) {
01371       iks_delete(iq);
01372       iks_delete(jingle);
01373       iks_delete(dtmf);
01374       ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
01375       return -1;
01376    }
01377 
01378    iks_insert_attrib(iq, "type", "set");
01379    iks_insert_attrib(iq, "to", p->them);
01380    iks_insert_attrib(iq, "from", client->connection->jid->full);
01381    iks_insert_attrib(iq, "id", client->connection->mid);
01382    ast_aji_increment_mid(client->connection->mid);
01383    iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01384    iks_insert_attrib(jingle, "action", "session-info");
01385    iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
01386    iks_insert_attrib(jingle, "sid", p->sid);
01387    iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS);
01388    iks_insert_attrib(dtmf, "code", buffer);
01389    iks_insert_node(iq, jingle);
01390    iks_insert_node(jingle, dtmf);
01391 
01392    ast_mutex_lock(&p->lock);
01393    if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
01394       iks_insert_attrib(dtmf, "action", "button-down");
01395    } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
01396       iks_insert_attrib(dtmf, "action", "button-up");
01397    }
01398    ast_aji_send(client->connection, iq);
01399 
01400    iks_delete(iq);
01401    iks_delete(jingle);
01402    iks_delete(dtmf);
01403    ast_mutex_unlock(&p->lock);
01404    return 0;
01405 }

static int jingle_digit_begin ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 1407 of file chan_jingle.c.

References jingle_digit().

01408 {
01409    return jingle_digit(chan, digit, 0);
01410 }

static int jingle_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 1412 of file chan_jingle.c.

References jingle_digit().

01413 {
01414    return jingle_digit(ast, digit, duration);
01415 }

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 1657 of file chan_jingle.c.

References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

01658 {
01659    switch (cmd) {
01660    case CLI_INIT:
01661       e->command = "jingle reload";
01662       e->usage =
01663          "Usage: jingle reload\n"
01664          "       Reload jingle channel driver.\n";
01665       return NULL;
01666    case CLI_GENERATE:
01667       return NULL;
01668    }  
01669    
01670    return CLI_SUCCESS;
01671 }

static int jingle_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 1307 of file chan_jingle.c.

References ast_mutex_lock, ast_mutex_unlock, jingle_pvt::lock, jingle_pvt::owner, and ast_channel::tech_pvt.

01308 {
01309    struct jingle_pvt *p = newchan->tech_pvt;
01310    ast_mutex_lock(&p->lock);
01311 
01312    if ((p->owner != oldchan)) {
01313       ast_mutex_unlock(&p->lock);
01314       return -1;
01315    }
01316    if (p->owner == oldchan)
01317       p->owner = newchan;
01318    ast_mutex_unlock(&p->lock);
01319    return 0;
01320 }

static void jingle_free_candidates ( struct jingle_candidate candidate  )  [static]

Definition at line 961 of file chan_jingle.c.

References ast_free, last, and jingle_candidate::next.

Referenced by jingle_free_pvt(), and jingle_load_config().

00962 {
00963    struct jingle_candidate *last;
00964    while (candidate) {
00965       last = candidate;
00966       candidate = candidate->next;
00967       ast_free(last);
00968    }
00969 }

static void jingle_free_pvt ( struct jingle client,
struct jingle_pvt p 
) [static]

Definition at line 971 of file chan_jingle.c.

References ast_format_cap_destroy(), ast_free, ast_log(), ast_rtp_instance_destroy(), jingle_pvt::cap, jingle::connection, aji_client::f, jingle_free_candidates(), jingle_pvt::jointcap, LOG_WARNING, jingle_pvt::next, jingle_pvt::owner, jingle::p, jingle_pvt::parent, jingle_pvt::peercap, jingle_pvt::ringrule, jingle_pvt::rtp, jingle_pvt::theircandidates, and jingle_pvt::vrtp.

Referenced by jingle_hangup(), and jingle_newcall().

00972 {
00973    struct jingle_pvt *cur, *prev = NULL;
00974    cur = client->p;
00975    while (cur) {
00976       if (cur == p) {
00977          if (prev)
00978             prev->next = p->next;
00979          else
00980             client->p = p->next;
00981          break;
00982       }
00983       prev = cur;
00984       cur = cur->next;
00985    }
00986    if (p->ringrule)
00987       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00988    if (p->owner)
00989       ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
00990    if (p->rtp)
00991       ast_rtp_instance_destroy(p->rtp);
00992    if (p->vrtp)
00993       ast_rtp_instance_destroy(p->vrtp);
00994    jingle_free_candidates(p->theircandidates);
00995    p->cap = ast_format_cap_destroy(p->cap);
00996    p->jointcap = ast_format_cap_destroy(p->jointcap);
00997    p->peercap = ast_format_cap_destroy(p->peercap);
00998 
00999    ast_free(p);
01000 }

static void jingle_get_codec ( struct ast_channel chan,
struct ast_format_cap result 
) [static]

Definition at line 419 of file chan_jingle.c.

References ast_format_cap_copy(), ast_mutex_lock, ast_mutex_unlock, jingle_pvt::lock, jingle_pvt::peercap, and ast_channel::tech_pvt.

00420 {
00421    struct jingle_pvt *p = chan->tech_pvt;
00422    ast_mutex_lock(&p->lock);
00423    ast_format_cap_copy(result, p->peercap);
00424    ast_mutex_unlock(&p->lock);
00425 }

static enum ast_rtp_glue_result jingle_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp_instance **  instance 
) [static]

Definition at line 400 of file chan_jingle.c.

References ao2_ref, ast_mutex_lock, ast_mutex_unlock, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, jingle_pvt::lock, jingle_pvt::rtp, and ast_channel::tech_pvt.

00401 {
00402    struct jingle_pvt *p = chan->tech_pvt;
00403    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
00404 
00405    if (!p)
00406       return res;
00407 
00408    ast_mutex_lock(&p->lock);
00409    if (p->rtp) {
00410       ao2_ref(p->rtp, +1);
00411       *instance = p->rtp;
00412       res = AST_RTP_GLUE_RESULT_LOCAL;
00413    }
00414    ast_mutex_unlock(&p->lock);
00415 
00416    return res;
00417 }

static int jingle_handle_dtmf ( struct jingle client,
ikspak *  pak 
) [static]

Definition at line 506 of file chan_jingle.c.

References AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), ast_verbose, ast_frame_subclass::integer, 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().

00507 {
00508    struct jingle_pvt *tmp;
00509    iks *dtmfnode = NULL, *dtmfchild = NULL;
00510    char *dtmf;
00511    /* Make sure our new call doesn't exist yet */
00512    for (tmp = client->p; tmp; tmp = tmp->next) {
00513       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
00514          break;
00515    }
00516 
00517    if (tmp) {
00518       if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) {
00519          jingle_response(client,pak,
00520                "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
00521                "unsupported-dtmf-method xmlns='http://www.xmpp.org/extensions/xep-0181.html#ns-errors'");
00522          return -1;
00523       }
00524       if ((dtmfnode = iks_find(pak->x, "dtmf"))) {
00525          if((dtmf = iks_find_attrib(dtmfnode, "code"))) {
00526             if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) {
00527                struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00528                f.subclass.integer = dtmf[0];
00529                ast_queue_frame(tmp->owner, &f);
00530                ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00531             } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) {
00532                struct ast_frame f = {AST_FRAME_DTMF_END, };
00533                f.subclass.integer = dtmf[0];
00534                ast_queue_frame(tmp->owner, &f);
00535                ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00536             } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */
00537                struct ast_frame f = {AST_FRAME_DTMF, };
00538                f.subclass.integer = dtmf[0];
00539                ast_queue_frame(tmp->owner, &f);
00540                ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00541             }
00542          }
00543       } else if ((dtmfnode = iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "session-info"))) {
00544          if((dtmfchild = iks_find(dtmfnode, "dtmf"))) {
00545             if((dtmf = iks_find_attrib(dtmfchild, "code"))) {
00546                if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) {
00547                   struct ast_frame f = {AST_FRAME_DTMF_END, };
00548                   f.subclass.integer = dtmf[0];
00549                   ast_queue_frame(tmp->owner, &f);
00550                   ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00551                } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) {
00552                   struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00553                   f.subclass.integer = dtmf[0];
00554                   ast_queue_frame(tmp->owner, &f);
00555                   ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00556                }
00557             }
00558          }
00559       }
00560       jingle_response(client, pak, NULL, NULL);
00561       return 1;
00562    } else
00563       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00564 
00565    jingle_response(client, pak, NULL, NULL);
00566    return 1;
00567 }

static int jingle_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the jingle proxy channel.

Definition at line 1526 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.

01527 {
01528    struct jingle_pvt *p = ast->tech_pvt;
01529    struct jingle *client;
01530 
01531    ast_mutex_lock(&p->lock);
01532    client = p->parent;
01533    p->owner = NULL;
01534    ast->tech_pvt = NULL;
01535    if (!p->alreadygone)
01536       jingle_action(client, p, JINGLE_TERMINATE);
01537    ast_mutex_unlock(&p->lock);
01538 
01539    jingle_free_pvt(client, p);
01540 
01541    return 0;
01542 }

static int jingle_hangup_farend ( struct jingle client,
ikspak *  pak 
) [static]

Definition at line 570 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().

00571 {
00572    struct jingle_pvt *tmp;
00573 
00574    ast_debug(1, "The client is %s\n", client->name);
00575    /* Make sure our new call doesn't exist yet */
00576    for (tmp = client->p; tmp; tmp = tmp->next) {
00577       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
00578          break;
00579    }
00580 
00581    if (tmp) {
00582       tmp->alreadygone = 1;
00583       if (tmp->owner)
00584          ast_queue_hangup(tmp->owner);
00585    } else
00586       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00587    jingle_response(client, pak, NULL, NULL);
00588    return 1;
00589 }

static int jingle_indicate ( struct ast_channel ast,
int  condition,
const void *  data,
size_t  datalen 
) [static]

Definition at line 1322 of file chan_jingle.c.

References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), and LOG_NOTICE.

01323 {
01324    int res = 0;
01325 
01326    switch (condition) {
01327    case AST_CONTROL_HOLD:
01328       ast_moh_start(ast, data, NULL);
01329       break;
01330    case AST_CONTROL_UNHOLD:
01331       ast_moh_stop(ast);
01332       break;
01333    default:
01334       ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01335       res = -1;
01336    }
01337 
01338    return res;
01339 }

static int jingle_is_answered ( struct jingle client,
ikspak *  pak 
) [static]

Definition at line 486 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().

00487 {
00488    struct jingle_pvt *tmp;
00489 
00490    ast_debug(1, "The client is %s\n", client->name);
00491    /* Make sure our new call doesn't exist yet */
00492    for (tmp = client->p; tmp; tmp = tmp->next) {
00493       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
00494          break;
00495    }
00496 
00497    if (tmp) {
00498       if (tmp->owner)
00499          ast_queue_control(tmp->owner, AST_CONTROL_ANSWER);
00500    } else
00501       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00502    jingle_response(client, pak, NULL, NULL);
00503    return 1;
00504 }

static int jingle_load_config ( void   )  [static]

Definition at line 1804 of file chan_jingle.c.

References jingle::allowguest, ast_aji_client_destroy(), ast_aji_get_clients(), ast_calloc, ast_category_browse(), ast_config_load, ast_copy_string(), ast_format_cap_alloc_nolock(), 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::cap, 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, jingle::prefs, jingle::user, ast_variable::value, and var.

Referenced by load_module().

01805 {
01806    char *cat = NULL;
01807    struct ast_config *cfg = NULL;
01808    char context[100];
01809    int allowguest = 1;
01810    struct ast_variable *var;
01811    struct jingle *member;
01812    struct hostent *hp;
01813    struct ast_hostent ahp;
01814    struct ast_codec_pref prefs;
01815    struct aji_client_container *clients;
01816    struct jingle_candidate *global_candidates = NULL;
01817    struct ast_flags config_flags = { 0 };
01818 
01819    cfg = ast_config_load(JINGLE_CONFIG, config_flags);
01820    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
01821       return 0;
01822    }
01823 
01824    /* Copy the default jb config over global_jbconf */
01825    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01826 
01827    cat = ast_category_browse(cfg, NULL);
01828    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
01829       /* handle jb conf */
01830       if (!ast_jb_read_conf(&global_jbconf, var->name, var->value))
01831          continue;
01832 
01833       if (!strcasecmp(var->name, "allowguest"))
01834          allowguest =
01835             (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
01836       else if (!strcasecmp(var->name, "disallow"))
01837          ast_parse_allow_disallow(&prefs, global_capability, var->value, 0);
01838       else if (!strcasecmp(var->name, "allow"))
01839          ast_parse_allow_disallow(&prefs, global_capability, var->value, 1);
01840       else if (!strcasecmp(var->name, "context"))
01841          ast_copy_string(context, var->value, sizeof(context));
01842       else if (!strcasecmp(var->name, "externip"))
01843          ast_copy_string(externip, var->value, sizeof(externip));
01844       else if (!strcasecmp(var->name, "bindaddr")) {
01845          if (!(hp = ast_gethostbyname(var->value, &ahp))) {
01846             ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
01847          } else {
01848             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
01849          }
01850       }
01851 /*  Idea to allow for custom candidates  */
01852 /*
01853       else if (!strcasecmp(var->name, "candidate")) {
01854          candidate = jingle_create_candidate(var->value);
01855          if (candidate) {
01856             candidate->next = global_candidates;
01857             global_candidates = candidate;
01858          }
01859       }
01860 */
01861    }
01862    while (cat) {
01863       if (strcasecmp(cat, "general")) {
01864          var = ast_variable_browse(cfg, cat);
01865          member = ast_calloc(1, sizeof(*member));
01866          ASTOBJ_INIT(member);
01867          ASTOBJ_WRLOCK(member);
01868          member->cap = ast_format_cap_alloc_nolock();
01869          if (!strcasecmp(cat, "guest")) {
01870             ast_copy_string(member->name, "guest", sizeof(member->name));
01871             ast_copy_string(member->user, "guest", sizeof(member->user));
01872             ast_copy_string(member->context, context, sizeof(member->context));
01873             member->allowguest = allowguest;
01874             member->prefs = prefs;
01875             while (var) {
01876                if (!strcasecmp(var->name, "disallow"))
01877                   ast_parse_allow_disallow(&member->prefs, member->cap,
01878                                      var->value, 0);
01879                else if (!strcasecmp(var->name, "allow"))
01880                   ast_parse_allow_disallow(&member->prefs, member->cap,
01881                                      var->value, 1);
01882                else if (!strcasecmp(var->name, "context"))
01883                   ast_copy_string(member->context, var->value,
01884                               sizeof(member->context));
01885                else if (!strcasecmp(var->name, "parkinglot"))
01886                   ast_copy_string(member->parkinglot, var->value,
01887                               sizeof(member->parkinglot));
01888 /*  Idea to allow for custom candidates  */
01889 /*
01890                else if (!strcasecmp(var->name, "candidate")) {
01891                   candidate = jingle_create_candidate(var->value);
01892                   if (candidate) {
01893                      candidate->next = member->ourcandidates;
01894                      member->ourcandidates = candidate;
01895                   }
01896                }
01897 */
01898                var = var->next;
01899             }
01900             ASTOBJ_UNLOCK(member);
01901             clients = ast_aji_get_clients();
01902             if (clients) {
01903                ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
01904                   ASTOBJ_WRLOCK(iterator);
01905                   ASTOBJ_WRLOCK(member);
01906                   if (member->connection) {
01907                      ASTOBJ_UNREF(member->connection, ast_aji_client_destroy);
01908                   }
01909                   member->connection = NULL;
01910                   iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE);
01911                   iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE);
01912                   ASTOBJ_UNLOCK(member);
01913                   ASTOBJ_UNLOCK(iterator);
01914                });
01915                ASTOBJ_CONTAINER_LINK(&jingle_list, member);
01916             } else {
01917                ASTOBJ_UNLOCK(member);
01918                ASTOBJ_UNREF(member, jingle_member_destroy);
01919             }
01920          } else {
01921             ASTOBJ_UNLOCK(member);
01922             if (jingle_create_member(cat, var, allowguest, prefs, context, member))
01923                ASTOBJ_CONTAINER_LINK(&jingle_list, member);
01924             ASTOBJ_UNREF(member, jingle_member_destroy);
01925          }
01926       }
01927       cat = ast_category_browse(cfg, cat);
01928    }
01929    jingle_free_candidates(global_candidates);
01930    return 1;
01931 }

static void jingle_member_destroy ( struct jingle obj  )  [static]

Definition at line 228 of file chan_jingle.c.

References ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_format_cap_destroy(), ast_free, ASTOBJ_UNREF, jingle::buddy, jingle::cap, and jingle::connection.

Referenced by jingle_load_config(), jingle_parser(), and unload_module().

00229 {
00230    obj->cap = ast_format_cap_destroy(obj->cap);
00231    if (obj->connection) {
00232       ASTOBJ_UNREF(obj->connection, ast_aji_client_destroy);
00233    }
00234    if (obj->buddy) {
00235       ASTOBJ_UNREF(obj->buddy, ast_aji_buddy_destroy);
00236    }
00237    ast_free(obj);
00238 }

static struct ast_channel* jingle_new ( struct jingle client,
struct jingle_pvt i,
int  state,
const char *  title,
const char *  linkedid 
) [static, read]

Start new jingle channel.

Definition at line 829 of file chan_jingle.c.

References jingle::accountcode, ast_channel::adsicpe, ast_channel::amaflags, jingle::amaflags, ast_party_caller::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc, ast_channel_name(), ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), ast_format_cap_add(), ast_format_cap_is_empty(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_format_copy(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_VIDEO, ast_hangup(), ast_jb_configure(), ast_log(), ast_pbx_start(), ast_random(), ast_rtp_codecs_packetization_set(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_channel::caller, jingle::callgroup, ast_channel::callgroup, jingle::callingpres, jingle_pvt::cap, jingle_pvt::cid_name, jingle_pvt::cid_num, jingle::context, ast_channel::context, ast_channel::dialed, jingle_pvt::exten, ast_channel::exten, global_jbconf, ast_channel::hangupcause, ast_party_caller::id, ast_format::id, jingle_pvt::jointcap, jingle::language, LOG_WARNING, jingle::musicclass, ast_party_id::name, ast_channel::nativeformats, ast_party_dialed::number, ast_party_id::number, jingle_pvt::owner, jingle::pickupgroup, ast_channel::pickupgroup, jingle_pvt::prefs, ast_party_number::presentation, ast_party_name::presentation, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, jingle_pvt::rtp, ast_party_dialed::str, ast_party_number::str, str, ast_channel::tech, ast_channel::tech_pvt, jingle_pvt::them, ast_party_number::valid, jingle_pvt::vrtp, and ast_channel::writeformat.

Referenced by jingle_newcall(), and jingle_request().

00830 {
00831    struct ast_channel *tmp;
00832    struct ast_format_cap *what;  /* SHALLOW COPY DO NOT DESTROY */
00833    struct ast_format tmpfmt;
00834    const char *str;
00835 
00836    if (title)
00837       str = title;
00838    else
00839       str = i->them;
00840    tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff);
00841    if (!tmp) {
00842       ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
00843       return NULL;
00844    }
00845    tmp->tech = &jingle_tech;
00846 
00847    /* Select our native format based on codec preference until we receive
00848       something from another device to the contrary. */
00849    if (!ast_format_cap_is_empty(i->jointcap))
00850       what = i->jointcap;
00851    else if (!(ast_format_cap_is_empty(i->cap)))
00852       what = i->cap;
00853    else
00854       what = global_capability;
00855 
00856    /* Set Frame packetization */
00857    if (i->rtp)
00858       ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
00859 
00860    ast_codec_choose(&i->prefs, what, 1, &tmpfmt);
00861    ast_format_cap_add(tmp->nativeformats, &tmpfmt);
00862 
00863    ast_format_cap_iter_start(i->jointcap);
00864    while (!(ast_format_cap_iter_next(i->jointcap, &tmpfmt))) {
00865       if (AST_FORMAT_GET_TYPE(tmpfmt.id) == AST_FORMAT_TYPE_VIDEO) {
00866          ast_format_cap_add(tmp->nativeformats, &tmpfmt);
00867       }
00868    }
00869    ast_format_cap_iter_end(i->jointcap);
00870 
00871    if (i->rtp) {
00872       ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
00873       ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
00874    }
00875    if (i->vrtp) {
00876       ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
00877       ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
00878    }
00879    if (state == AST_STATE_RING)
00880       tmp->rings = 1;
00881    tmp->adsicpe = AST_ADSI_UNAVAILABLE;
00882 
00883 
00884    ast_best_codec(tmp->nativeformats, &tmpfmt);
00885    ast_format_copy(&tmp->writeformat, &tmpfmt);
00886    ast_format_copy(&tmp->rawwriteformat, &tmpfmt);
00887    ast_format_copy(&tmp->readformat, &tmpfmt);
00888    ast_format_copy(&tmp->rawreadformat, &tmpfmt);
00889    tmp->tech_pvt = i;
00890 
00891    tmp->callgroup = client->callgroup;
00892    tmp->pickupgroup = client->pickupgroup;
00893    tmp->caller.id.name.presentation = client->callingpres;
00894    tmp->caller.id.number.presentation = client->callingpres;
00895    if (!ast_strlen_zero(client->accountcode))
00896       ast_channel_accountcode_set(tmp, client->accountcode);
00897    if (client->amaflags)
00898       tmp->amaflags = client->amaflags;
00899    if (!ast_strlen_zero(client->language))
00900       ast_channel_language_set(tmp, client->language);
00901    if (!ast_strlen_zero(client->musicclass))
00902       ast_channel_musicclass_set(tmp, client->musicclass);
00903    i->owner = tmp;
00904    ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
00905    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
00906    /* Don't use ast_set_callerid() here because it will
00907     * generate an unnecessary NewCallerID event  */
00908    if (!ast_strlen_zero(i->cid_num)) {
00909       tmp->caller.ani.number.valid = 1;
00910       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
00911    }
00912    if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) {
00913       tmp->dialed.number.str = ast_strdup(i->exten);
00914    }
00915    tmp->priority = 1;
00916    if (i->rtp)
00917       ast_jb_configure(tmp, &global_jbconf);
00918    if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
00919       ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
00920       tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
00921       ast_hangup(tmp);
00922       tmp = NULL;
00923    }
00924 
00925    return tmp;
00926 }

static int jingle_newcall ( struct jingle client,
ikspak *  pak 
) [static]

Definition at line 1003 of file chan_jingle.c.

References ast_aji_client_destroy(), 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_codecs_payloads_set_m_type(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, ASTOBJ_UNREF, jingle_pvt::audio_content_name, jingle::connection, 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().

01004 {
01005    struct jingle_pvt *p, *tmp = client->p;
01006    struct ast_channel *chan;
01007    int res;
01008    iks *codec, *content, *description;
01009    char *from = NULL;
01010 
01011    /* Make sure our new call doesn't exist yet */
01012    from = iks_find_attrib(pak->x,"to");
01013    if(!from)
01014       from = client->connection->jid->full;
01015 
01016    while (tmp) {
01017       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
01018          ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
01019          jingle_response(client, pak, "out-of-order", NULL);
01020          return -1;
01021       }
01022       tmp = tmp->next;
01023    }
01024 
01025    if (!strcasecmp(client->name, "guest")){
01026       /* the guest account is not tied to any configured XMPP client,
01027          let's set it now */
01028       if (client->connection) {
01029          ASTOBJ_UNREF(client->connection, ast_aji_client_destroy);
01030       }
01031       client->connection = ast_aji_get_client(from);
01032       if (!client->connection) {
01033          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from);
01034          return -1;
01035       }
01036    }
01037 
01038    p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID));
01039    if (!p) {
01040       ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
01041       return -1;
01042    }
01043    chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user, NULL);
01044    if (!chan) {
01045       jingle_free_pvt(client, p);
01046       return -1;
01047    }
01048    ast_mutex_lock(&p->lock);
01049    ast_copy_string(p->them, pak->from->full, sizeof(p->them));
01050    if (iks_find_attrib(pak->query, JINGLE_SID)) {
01051       ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID),
01052             sizeof(p->sid));
01053    }
01054    
01055    /* content points to the first <content/> tag */   
01056    content = iks_child(iks_child(pak->x));
01057    while (content) {
01058       description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS);
01059       if (description) {
01060          /* audio content found */
01061          codec = iks_child(iks_child(content));
01062               ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
01063 
01064          while (codec) {
01065             ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
01066             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);
01067             codec = iks_next(codec);
01068          }
01069       }
01070       
01071       description = NULL;
01072       codec = NULL;
01073 
01074       description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS);
01075       if (description) {
01076          /* video content found */
01077          codec = iks_child(iks_child(content));
01078               ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
01079 
01080          while (codec) {
01081             ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
01082             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);
01083             codec = iks_next(codec);
01084          }
01085       }
01086       
01087       content = iks_next(content);
01088    }
01089 
01090    ast_mutex_unlock(&p->lock);
01091    ast_setstate(chan, AST_STATE_RING);
01092    res = ast_pbx_start(chan);
01093    
01094    switch (res) {
01095    case AST_PBX_FAILED:
01096       ast_log(LOG_WARNING, "Failed to start PBX :(\n");
01097       jingle_response(client, pak, "service-unavailable", NULL);
01098       break;
01099    case AST_PBX_CALL_LIMIT:
01100       ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
01101       jingle_response(client, pak, "service-unavailable", NULL);
01102       break;
01103    case AST_PBX_SUCCESS:
01104       jingle_response(client, pak, NULL, NULL);
01105       jingle_create_candidates(client, p,
01106                 iks_find_attrib(pak->query, JINGLE_SID),
01107                 iks_find_attrib(pak->x, "from"));
01108       /* nothing to do */
01109       break;
01110    }
01111 
01112    return 1;
01113 }

static int jingle_parser ( void *  data,
ikspak *  pak 
) [static]

Definition at line 1673 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().

01674 {
01675    struct jingle *client = ASTOBJ_REF((struct jingle *) data);
01676    ast_log(LOG_NOTICE, "Filter matched\n");
01677 
01678    if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
01679       /* New call */
01680       jingle_newcall(client, pak);
01681    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
01682       ast_debug(3, "About to add candidate!\n");
01683       jingle_add_candidate(client, pak);
01684       ast_debug(3, "Candidate Added!\n");
01685    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
01686       jingle_is_answered(client, pak);
01687    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
01688       jingle_handle_dtmf(client, pak);
01689    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
01690       jingle_hangup_farend(client, pak);
01691    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
01692       jingle_hangup_farend(client, pak);
01693    }
01694    ASTOBJ_UNREF(client, jingle_member_destroy);
01695    return IKS_FILTER_EAT;
01696 }

static struct ast_frame * jingle_read ( struct ast_channel ast  )  [static, read]

Definition at line 1249 of file chan_jingle.c.

References ast_mutex_lock, ast_mutex_unlock, jingle_rtp_read(), jingle_pvt::lock, and ast_channel::tech_pvt.

01250 {
01251    struct ast_frame *fr;
01252    struct jingle_pvt *p = ast->tech_pvt;
01253 
01254    ast_mutex_lock(&p->lock);
01255    fr = jingle_rtp_read(ast, p);
01256    ast_mutex_unlock(&p->lock);
01257    return fr;
01258 }

static struct ast_channel * jingle_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_channel requestor,
const char *  data,
int *  cause 
) [static, read]

Part of PBX interface.

Definition at line 1545 of file chan_jingle.c.

References ast_aji_client_destroy(), ast_aji_get_client(), ast_channel_linkedid(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, jingle::connection, find_jingle(), jingle_alloc(), jingle_new(), LOG_ERROR, LOG_WARNING, jingle::name, and strsep().

01546 {
01547    struct jingle_pvt *p = NULL;
01548    struct jingle *client = NULL;
01549    char *sender = NULL, *to = NULL, *s = NULL;
01550    struct ast_channel *chan = NULL;
01551 
01552    if (data) {
01553       s = ast_strdupa(data);
01554       if (s) {
01555          sender = strsep(&s, "/");
01556          if (sender && (sender[0] != '\0'))
01557             to = strsep(&s, "/");
01558          if (!to) {
01559             ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", data);
01560             return NULL;
01561          }
01562       }
01563    }
01564 
01565    client = find_jingle(to, sender);
01566    if (!client) {
01567       ast_log(LOG_WARNING, "Could not find recipient.\n");
01568       return NULL;
01569    }
01570    if (!strcasecmp(client->name, "guest")){
01571       /* the guest account is not tied to any configured XMPP client,
01572          let's set it now */
01573       if (client->connection) {
01574          ASTOBJ_UNREF(client->connection, ast_aji_client_destroy);
01575       }
01576       client->connection = ast_aji_get_client(sender);
01577       if (!client->connection) {
01578          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01579          return NULL;
01580       }
01581    }
01582        
01583    ASTOBJ_WRLOCK(client);
01584    p = jingle_alloc(client, to, NULL);
01585    if (p)
01586       chan = jingle_new(client, p, AST_STATE_DOWN, to, requestor ? ast_channel_linkedid(requestor) : NULL);
01587    ASTOBJ_UNLOCK(client);
01588 
01589    return chan;
01590 }

static int jingle_response ( struct jingle client,
ikspak *  pak,
const char *  reasonstr,
const char *  reasonstr2 
) [static]

Definition at line 454 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().

00455 {
00456    iks *response = NULL, *error = NULL, *reason = NULL;
00457    int res = -1;
00458 
00459    response = iks_new("iq");
00460    if (response) {
00461       iks_insert_attrib(response, "type", "result");
00462       iks_insert_attrib(response, "from", client->connection->jid->full);
00463       iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
00464       iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
00465       if (reasonstr) {
00466          error = iks_new("error");
00467          if (error) {
00468             iks_insert_attrib(error, "type", "cancel");
00469             reason = iks_new(reasonstr);
00470             if (reason)
00471                iks_insert_node(error, reason);
00472             iks_insert_node(response, error);
00473          }
00474       }
00475       ast_aji_send(client->connection, response);
00476       res = 0;
00477    }
00478    
00479    iks_delete(reason);
00480    iks_delete(error);
00481    iks_delete(response);
00482 
00483    return res;
00484 }

static int jingle_ringing_ack ( void *  data,
ikspak *  pak 
) [static]

Definition at line 375 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().

00376 {
00377    struct jingle_pvt *p = data;
00378 
00379    if (p->ringrule)
00380       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00381    p->ringrule = NULL;
00382    if (p->owner)
00383       ast_queue_control(p->owner, AST_CONTROL_RINGING);
00384    return IKS_FILTER_EAT;
00385 }

static struct ast_frame* jingle_rtp_read ( struct ast_channel ast,
struct jingle_pvt p 
) [static, read]

Definition at line 1221 of file chan_jingle.c.

References ast_debug, ast_format_cap_add(), ast_format_cap_iscompatible(), ast_format_cap_remove_bytype(), AST_FORMAT_TYPE_AUDIO, AST_FRAME_VOICE, ast_getformatname(), ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), f, ast_frame_subclass::format, 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().

01222 {
01223    struct ast_frame *f;
01224 
01225    if (!p->rtp)
01226       return &ast_null_frame;
01227    f = ast_rtp_instance_read(p->rtp, 0);
01228    jingle_update_stun(p->parent, p);
01229    if (p->owner) {
01230       /* We already hold the channel lock */
01231       if (f->frametype == AST_FRAME_VOICE) {
01232          if (!(ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format))) {
01233             ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
01234             ast_format_cap_remove_bytype(p->owner->nativeformats, AST_FORMAT_TYPE_AUDIO);
01235             ast_format_cap_add(p->owner->nativeformats, &f->subclass.format);
01236             ast_set_read_format(p->owner, &p->owner->readformat);
01237             ast_set_write_format(p->owner, &p->owner->writeformat);
01238          }
01239 /*       if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
01240             f = ast_dsp_process(p->owner, p->vad, f);
01241             if (f && (f->frametype == AST_FRAME_DTMF))
01242                ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.codec);
01243               } */
01244       }
01245    }
01246    return f;
01247 }

static int jingle_sendhtml ( struct ast_channel ast,
int  subclass,
const char *  data,
int  datalen 
) [static]

Definition at line 1417 of file chan_jingle.c.

References ast_log(), and LOG_NOTICE.

01418 {
01419    ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
01420 
01421    return -1;
01422 }

static int jingle_sendtext ( struct ast_channel ast,
const char *  text 
) [static]

Definition at line 1341 of file chan_jingle.c.

References ast_aji_send_chat(), ast_log(), jingle::connection, LOG_ERROR, jingle_pvt::parent, ast_channel::tech_pvt, and jingle_pvt::them.

01342 {
01343    int res = 0;
01344    struct aji_client *client = NULL;
01345    struct jingle_pvt *p = chan->tech_pvt;
01346 
01347 
01348    if (!p->parent) {
01349       ast_log(LOG_ERROR, "Parent channel not found\n");
01350       return -1;
01351    }
01352    if (!p->parent->connection) {
01353       ast_log(LOG_ERROR, "XMPP client not found\n");
01354       return -1;
01355    }
01356    client = p->parent->connection;
01357    res = ast_aji_send_chat(client, p->them, text);
01358    return res;
01359 }

static int jingle_set_rtp_peer ( struct ast_channel chan,
struct ast_rtp_instance rtp,
struct ast_rtp_instance vrtp,
struct ast_rtp_instance tpeer,
const struct ast_format_cap cap,
int  nat_active 
) [static]

Definition at line 427 of file chan_jingle.c.

References ast_mutex_lock, ast_mutex_unlock, jingle_pvt::lock, and ast_channel::tech_pvt.

00428 {
00429    struct jingle_pvt *p;
00430 
00431    p = chan->tech_pvt;
00432    if (!p)
00433       return -1;
00434    ast_mutex_lock(&p->lock);
00435 
00436 /* if (rtp)
00437       ast_rtp_get_peer(rtp, &p->redirip);
00438    else
00439       memset(&p->redirip, 0, sizeof(p->redirip));
00440    p->redircodecs = codecs; */
00441 
00442    /* Reset lastrtprx timer */
00443    ast_mutex_unlock(&p->lock);
00444    return 0;
00445 }

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 1593 of file chan_jingle.c.

References AJI_MAX_JIDLEN, ast_cli_args::argc, ast_channel_name(), ast_cli(), ast_copy_string(), ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, jingle_list, jinglelock, LOG_WARNING, jingle_pvt::next, jingle_pvt::owner, ast_channel::readformat, jingle_pvt::them, ast_cli_entry::usage, and ast_channel::writeformat.

01594 {
01595 #define FORMAT  "%-30.30s  %-30.30s  %-15.15s  %-5.5s %-5.5s \n"
01596    struct jingle_pvt *p;
01597    struct ast_channel *chan;
01598    int numchans = 0;
01599    char them[AJI_MAX_JIDLEN];
01600    char *jid = NULL;
01601    char *resource = NULL;
01602 
01603    switch (cmd) {
01604    case CLI_INIT:
01605       e->command = "jingle show channels";
01606       e->usage =
01607          "Usage: jingle show channels\n"
01608          "       Shows current state of the Jingle channels.\n";
01609       return NULL;
01610    case CLI_GENERATE:
01611       return NULL;
01612    }
01613 
01614    if (a->argc != 3)
01615       return CLI_SHOWUSAGE;
01616 
01617    ast_mutex_lock(&jinglelock);
01618    ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
01619    ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01620       ASTOBJ_WRLOCK(iterator);
01621       p = iterator->p;
01622       while(p) {
01623          chan = p->owner;
01624          ast_copy_string(them, p->them, sizeof(them));
01625          jid = them;
01626          resource = strchr(them, '/');
01627          if (!resource)
01628             resource = "None";
01629          else {
01630             *resource = '\0';
01631             resource ++;
01632          }
01633          if (chan)
01634             ast_cli(a->fd, FORMAT, 
01635                ast_channel_name(chan),
01636                jid,
01637                resource,
01638                ast_getformatname(&chan->readformat),
01639                ast_getformatname(&chan->writeformat)
01640                );
01641          else 
01642             ast_log(LOG_WARNING, "No available channel\n");
01643          numchans ++;
01644          p = p->next;
01645       }
01646       ASTOBJ_UNLOCK(iterator);
01647    });
01648 
01649    ast_mutex_unlock(&jinglelock);
01650 
01651    ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : "");
01652    return CLI_SUCCESS;
01653 #undef FORMAT
01654 }

static int jingle_transmit_invite ( struct jingle_pvt p  )  [static]

Definition at line 1423 of file chan_jingle.c.

References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle_pvt::audio_content_name, jingle::connection, aji_client::jid, 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().

01424 {
01425    struct jingle *aux = NULL;
01426    struct aji_client *client = NULL;
01427    iks *iq, *jingle, *content, *description, *transport;
01428    iks *payload_eg711u, *payload_pcmu;
01429 
01430    aux = p->parent;
01431    client = aux->connection;
01432    iq = iks_new("iq");
01433    jingle = iks_new(JINGLE_NODE);
01434    content = iks_new("content");
01435    description = iks_new("description");
01436    transport = iks_new("transport");
01437    payload_pcmu = iks_new("payload-type");
01438    payload_eg711u = iks_new("payload-type");
01439 
01440    ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name));
01441 
01442    iks_insert_attrib(iq, "type", "set");
01443    iks_insert_attrib(iq, "to", p->them);
01444    iks_insert_attrib(iq, "from", client->jid->full);
01445    iks_insert_attrib(iq, "id", client->mid);
01446    ast_aji_increment_mid(client->mid);
01447    iks_insert_attrib(jingle, "action", JINGLE_INITIATE);
01448    iks_insert_attrib(jingle, JINGLE_SID, p->sid);
01449    iks_insert_attrib(jingle, "initiator", client->jid->full);
01450    iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01451 
01452    /* For now, we only send one audio based content */
01453    iks_insert_attrib(content, "creator", "initiator");
01454    iks_insert_attrib(content, "name", p->audio_content_name);
01455    iks_insert_attrib(content, "profile", "RTP/AVP");
01456    iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS);
01457    iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
01458    iks_insert_attrib(payload_pcmu, "id", "0");
01459    iks_insert_attrib(payload_pcmu, "name", "PCMU");
01460    iks_insert_attrib(payload_eg711u, "id", "100");
01461    iks_insert_attrib(payload_eg711u, "name", "EG711U");
01462    iks_insert_node(description, payload_pcmu);
01463    iks_insert_node(description, payload_eg711u);
01464    iks_insert_node(content, description);
01465    iks_insert_node(content, transport);
01466    iks_insert_node(jingle, content);
01467    iks_insert_node(iq, jingle);
01468 
01469    ast_aji_send(client, iq);
01470 
01471    iks_delete(iq);
01472    iks_delete(jingle);
01473    iks_delete(content);
01474    iks_delete(description);
01475    iks_delete(transport);
01476    iks_delete(payload_eg711u);
01477    iks_delete(payload_pcmu);
01478    return 0;
01479 }

static int jingle_update_stun ( struct jingle client,
struct jingle_pvt p 
) [static]

Definition at line 1115 of file chan_jingle.c.

References ast_gethostbyname(), ast_rtp_instance_stun_request(), ast_sockaddr_from_sin, 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().

01116 {
01117    struct jingle_candidate *tmp;
01118    struct hostent *hp;
01119    struct ast_hostent ahp;
01120    struct sockaddr_in sin;
01121    struct ast_sockaddr sin_tmp;
01122 
01123    if (time(NULL) == p->laststun)
01124       return 0;
01125 
01126    tmp = p->theircandidates;
01127    p->laststun = time(NULL);
01128    while (tmp) {
01129       char username[256];
01130       hp = ast_gethostbyname(tmp->ip, &ahp);
01131       sin.sin_family = AF_INET;
01132       memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01133       sin.sin_port = htons(tmp->port);
01134       snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
01135 
01136       ast_sockaddr_from_sin(&sin_tmp, &sin);
01137       ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username);
01138       tmp = tmp->next;
01139    }
01140    return 1;
01141 }

static int jingle_write ( struct ast_channel ast,
struct ast_frame f 
) [static]

Send frame to media channel (rtp).

Definition at line 1261 of file chan_jingle.c.

References ast_format_cap_iscompatible(), AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_frame_subclass::format, 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.

01262 {
01263    struct jingle_pvt *p = ast->tech_pvt;
01264    int res = 0;
01265    char buf[256];
01266 
01267    switch (frame->frametype) {
01268    case AST_FRAME_VOICE:
01269       if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) {
01270          ast_log(LOG_WARNING,
01271                "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
01272                ast_getformatname(&frame->subclass.format),
01273                ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
01274                ast_getformatname(&ast->readformat),
01275                ast_getformatname(&ast->writeformat));
01276          return 0;
01277       }
01278       if (p) {
01279          ast_mutex_lock(&p->lock);
01280          if (p->rtp) {
01281             res = ast_rtp_instance_write(p->rtp, frame);
01282          }
01283          ast_mutex_unlock(&p->lock);
01284       }
01285       break;
01286    case AST_FRAME_VIDEO:
01287       if (p) {
01288          ast_mutex_lock(&p->lock);
01289          if (p->vrtp) {
01290             res = ast_rtp_instance_write(p->vrtp, frame);
01291          }
01292          ast_mutex_unlock(&p->lock);
01293       }
01294       break;
01295    case AST_FRAME_IMAGE:
01296       return 0;
01297       break;
01298    default:
01299       ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n",
01300             frame->frametype);
01301       return 0;
01302    }
01303 
01304    return res;
01305 }

static int load_module ( void   )  [static]

Load module into PBX, register channel.

Definition at line 1934 of file chan_jingle.c.

References __ourip, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_find_ourip(), AST_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_add_all_by_type(), ast_format_cap_alloc(), AST_FORMAT_GSM, AST_FORMAT_H263, ast_format_set(), AST_FORMAT_TYPE_AUDIO, AST_FORMAT_ULAW, ast_log(), ast_module_helper(), AST_MODULE_LOAD_DECLINE, ast_rtp_glue_register, ast_sched_context_create(), ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ASTOBJ_CONTAINER_INIT, ast_channel_tech::capabilities, free, io_context_create(), JINGLE_CONFIG, jingle_list, jingle_load_config(), LOG_ERROR, and LOG_WARNING.

01935 {
01936    struct ast_sockaddr ourip_tmp;
01937    struct ast_sockaddr bindaddr_tmp;
01938    struct ast_format tmpfmt;
01939 
01940    char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
01941 
01942    if (!(jingle_tech.capabilities = ast_format_cap_alloc())) {
01943       return AST_MODULE_LOAD_DECLINE;
01944    }
01945 
01946    ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
01947    if (!(global_capability = ast_format_cap_alloc())) {
01948       return AST_MODULE_LOAD_DECLINE;
01949    }
01950    ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
01951    ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0));
01952    ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
01953    ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_H263, 0));
01954 
01955    free(jabber_loaded);
01956    if (!jabber_loaded) {
01957       /* Dependency module has a different name, if embedded */
01958       jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
01959       free(jabber_loaded);
01960       if (!jabber_loaded) {
01961          ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n");
01962          return AST_MODULE_LOAD_DECLINE;
01963       }
01964    }
01965 
01966    ASTOBJ_CONTAINER_INIT(&jingle_list);
01967    if (!jingle_load_config()) {
01968       ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
01969       return AST_MODULE_LOAD_DECLINE;
01970    }
01971 
01972    sched = ast_sched_context_create();
01973    if (!sched) {
01974       ast_log(LOG_WARNING, "Unable to create schedule context\n");
01975    }
01976 
01977    io = io_context_create();
01978    if (!io) {
01979       ast_log(LOG_WARNING, "Unable to create I/O context\n");
01980    }
01981 
01982    ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
01983    if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp, AF_INET)) {
01984       ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
01985       return 0;
01986    }
01987    __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp));
01988 
01989    ast_rtp_glue_register(&jingle_rtp_glue);
01990    ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01991    /* Make sure we can register our channel type */
01992    if (ast_channel_register(&jingle_tech)) {
01993       ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
01994       return -1;
01995    }
01996    return 0;
01997 }

static int reload ( void   )  [static]

Reload module.

Definition at line 2000 of file chan_jingle.c.

02001 {
02002    return 0;
02003 }

static int unload_module ( void   )  [static]

Unload the jingle channel from Asterisk.

Definition at line 2006 of file chan_jingle.c.

References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_format_cap_destroy(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_glue_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.

02007 {
02008    struct jingle_pvt *privates = NULL;
02009    ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
02010    /* First, take us out of the channel loop */
02011    ast_channel_unregister(&jingle_tech);
02012    ast_rtp_glue_unregister(&jingle_rtp_glue);
02013 
02014    if (!ast_mutex_lock(&jinglelock)) {
02015       /* Hangup all interfaces if they have an owner */
02016       ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
02017          ASTOBJ_WRLOCK(iterator);
02018          privates = iterator->p;
02019          while(privates) {
02020             if (privates->owner)
02021                ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
02022             privates = privates->next;
02023          }
02024          iterator->p = NULL;
02025          ASTOBJ_UNLOCK(iterator);
02026       });
02027       ast_mutex_unlock(&jinglelock);
02028    } else {
02029       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
02030       return -1;
02031    }
02032    ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
02033    ASTOBJ_CONTAINER_DESTROY(&jingle_list);
02034 
02035    global_capability = ast_format_cap_destroy(global_capability);
02036    return 0;
02037 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static]

Definition at line 2044 of file chan_jingle.c.

struct in_addr __ourip [static]

Definition at line 216 of file chan_jingle.c.

Definition at line 2044 of file chan_jingle.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 212 of file chan_jingle.c.

const char channel_type[] = "Jingle" [static]

Definition at line 167 of file chan_jingle.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 77 of file chan_jingle.c.

const char desc[] = "Jingle Channel" [static]

Definition at line 166 of file chan_jingle.c.

char externip[16] [static]

Definition at line 224 of file chan_jingle.c.

Definition at line 169 of file chan_jingle.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 85 of file chan_jingle.c.

struct io_context* io [static]

The IO context

Definition at line 215 of file chan_jingle.c.

struct ast_cli_entry jingle_cli[] [static]

Initial value:

 {
   AST_CLI_DEFINE(jingle_do_reload, "Reload Jingle configuration"),
   AST_CLI_DEFINE(jingle_show_channels, "Show Jingle channels"),
}

Definition at line 218 of file chan_jingle.c.

struct jingle_container jingle_list [static]

struct ast_rtp_glue jingle_rtp_glue [static]

Definition at line 447 of file chan_jingle.c.

struct ast_channel_tech jingle_tech [static]

PBX interface structure for channel registration.

Definition at line 192 of file chan_jingle.c.

ast_mutex_t jinglelock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Protect the interface list (of jingle_pvt's)

Definition at line 171 of file chan_jingle.c.

Referenced by jingle_alloc(), jingle_show_channels(), and unload_module().

struct ast_sched_context* sched [static]

The scheduling context

Definition at line 214 of file chan_jingle.c.


Generated on Sat Feb 11 06:34:37 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6