Wed Apr 6 11:29:57 2011

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"

Go to the source code of this file.

Data Structures

struct  jingle
struct  jingle_candidate
struct  jingle_container
struct  jingle_pvt

Defines

#define FORMAT   "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n"
#define JINGLE_CONFIG   "jingle.conf"

Enumerations

enum  jingle_connect_type { AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX }
enum  jingle_protocol { AJI_PROTOCOL_UDP, AJI_PROTOCOL_SSLTCP }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void add_codec_to_answer (const struct jingle_pvt *p, int codec, iks *dcodecs)
static struct 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, 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 format_t jingle_get_codec (struct ast_channel *chan)
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, format_t format, const struct ast_channel *requestor, void *data, int *cause)
 Part of PBX interface.
static int jingle_response (struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2)
static int jingle_ringing_ack (void *data, ikspak *pak)
static struct ast_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, format_t codecs, int nat_active)
static char * jingle_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command "jingle show channels".
static int jingle_transmit_invite (struct jingle_pvt *p)
static int jingle_update_stun (struct jingle *client, struct jingle_pvt *p)
static int jingle_write (struct ast_channel *ast, struct ast_frame *frame)
 Send frame to media channel (rtp).
static int load_module (void)
 Load module into PBX, register channel.
static int reload (void)
 Reload module.
static int unload_module (void)
 Unload the jingle channel from Asterisk.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 format_t global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263
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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static struct 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 72 of file chan_jingle.c.

Referenced by jingle_load_config(), and load_module().


Enumeration Type Documentation

enum jingle_connect_type

Enumerator:
AJI_CONNECT_HOST 
AJI_CONNECT_PRFLX 
AJI_CONNECT_RELAY 
AJI_CONNECT_SRFLX 

Definition at line 90 of file chan_jingle.c.

00090                          {
00091    AJI_CONNECT_HOST,
00092    AJI_CONNECT_PRFLX,
00093    AJI_CONNECT_RELAY,
00094    AJI_CONNECT_SRFLX,
00095 };

enum jingle_protocol

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 85 of file chan_jingle.c.

00085                      {
00086    AJI_PROTOCOL_UDP,
00087    AJI_PROTOCOL_SSLTCP,
00088 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1976 of file chan_jingle.c.

static void __unreg_module ( void   )  [static]

Definition at line 1976 of file chan_jingle.c.

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

Definition at line 258 of file chan_jingle.c.

References ast_getformatname(), and format.

00259 {
00260    char *format = ast_getformatname(codec);
00261 
00262    if (!strcasecmp("ulaw", format)) {
00263       iks *payload_eg711u, *payload_pcmu;
00264       payload_pcmu = iks_new("payload-type");
00265       iks_insert_attrib(payload_pcmu, "id", "0");
00266       iks_insert_attrib(payload_pcmu, "name", "PCMU");
00267       payload_eg711u = iks_new("payload-type");
00268       iks_insert_attrib(payload_eg711u, "id", "100");
00269       iks_insert_attrib(payload_eg711u, "name", "EG711U");
00270       iks_insert_node(dcodecs, payload_pcmu);
00271       iks_insert_node(dcodecs, payload_eg711u);
00272    }
00273    if (!strcasecmp("alaw", format)) {
00274       iks *payload_eg711a;
00275       iks *payload_pcma = iks_new("payload-type");
00276       iks_insert_attrib(payload_pcma, "id", "8");
00277       iks_insert_attrib(payload_pcma, "name", "PCMA");
00278       payload_eg711a = iks_new("payload-type");
00279       iks_insert_attrib(payload_eg711a, "id", "101");
00280       iks_insert_attrib(payload_eg711a, "name", "EG711A");
00281       iks_insert_node(dcodecs, payload_pcma);
00282       iks_insert_node(dcodecs, payload_eg711a);
00283    }
00284    if (!strcasecmp("ilbc", format)) {
00285       iks *payload_ilbc = iks_new("payload-type");
00286       iks_insert_attrib(payload_ilbc, "id", "97");
00287       iks_insert_attrib(payload_ilbc, "name", "iLBC");
00288       iks_insert_node(dcodecs, payload_ilbc);
00289    }
00290    if (!strcasecmp("g723", format)) {
00291       iks *payload_g723 = iks_new("payload-type");
00292       iks_insert_attrib(payload_g723, "id", "4");
00293       iks_insert_attrib(payload_g723, "name", "G723");
00294       iks_insert_node(dcodecs, payload_g723);
00295    }
00296 }

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

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

00233 {
00234    struct jingle *jingle = NULL;
00235 
00236    jingle = ASTOBJ_CONTAINER_FIND(&jingle_list, name);
00237    if (!jingle && strchr(name, '@'))
00238       jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingle_list, name, user,,, strcasecmp);
00239 
00240    if (!jingle) {          
00241       /* guest call */
00242       ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
00243          ASTOBJ_RDLOCK(iterator);
00244          if (!strcasecmp(iterator->name, "guest")) {
00245             jingle = iterator;
00246          }
00247          ASTOBJ_UNLOCK(iterator);
00248 
00249          if (jingle)
00250             break;
00251       });
00252 
00253    }
00254    return jingle;
00255 }

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

Definition at line 298 of file chan_jingle.c.

References add_codec_to_answer(), ast_aji_increment_mid(), ast_aji_send(), ast_codec_pref_index(), jingle::capability, jingle::connection, aji_client::jid, JINGLE_ACCEPT, JINGLE_AUDIO_RTP_NS, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, aji_client::p, jingle::p, jingle::prefs, jingle_pvt::sid, and jingle::user.

Referenced by jingle_answer().

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

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

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

00892 {
00893    iks *iq, *jingle = NULL;
00894    int res = -1;
00895 
00896    iq = iks_new("iq");
00897    jingle = iks_new("jingle");
00898    
00899    if (iq) {
00900       iks_insert_attrib(iq, "type", "set");
00901       iks_insert_attrib(iq, "from", client->connection->jid->full);
00902       iks_insert_attrib(iq, "to", p->them);
00903       iks_insert_attrib(iq, "id", client->connection->mid);
00904       ast_aji_increment_mid(client->connection->mid);
00905       if (jingle) {
00906          iks_insert_attrib(jingle, "action", action);
00907          iks_insert_attrib(jingle, JINGLE_SID, p->sid);
00908          iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
00909          iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00910 
00911          iks_insert_node(iq, jingle);
00912 
00913          ast_aji_send(client->connection, iq);
00914          res = 0;
00915       }
00916    }
00917    
00918    iks_delete(jingle);
00919    iks_delete(iq);
00920    
00921    return res;
00922 }

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

Definition at line 1099 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, aji_client::jid, JINGLE_NODE, JINGLE_SID, jingle_update_stun(), jingle_pvt::laststun, jingle_pvt::next, jingle::p, jingle_pvt::parent, and jingle_pvt::theircandidates.

Referenced by jingle_parser().

01100 {
01101    struct jingle_pvt *p = NULL, *tmp = NULL;
01102    struct aji_client *c = client->connection;
01103    struct jingle_candidate *newcandidate = NULL;
01104    iks *traversenodes = NULL, *receipt = NULL;
01105 
01106    for (tmp = client->p; tmp; tmp = tmp->next) {
01107       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
01108          p = tmp;
01109          break;
01110       }
01111    }
01112 
01113    if (!p)
01114       return -1;
01115 
01116    traversenodes = pak->query;
01117    while(traversenodes) {
01118       if(!strcasecmp(iks_name(traversenodes), "jingle")) {
01119          traversenodes = iks_child(traversenodes);
01120          continue;
01121       }
01122       if(!strcasecmp(iks_name(traversenodes), "content")) {
01123          traversenodes = iks_child(traversenodes);
01124          continue;
01125       }
01126       if(!strcasecmp(iks_name(traversenodes), "transport")) {
01127          traversenodes = iks_child(traversenodes);
01128          continue;
01129       }
01130 
01131       if(!strcasecmp(iks_name(traversenodes), "candidate")) {
01132          newcandidate = ast_calloc(1, sizeof(*newcandidate));
01133          if (!newcandidate)
01134             return 0;
01135          ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip));
01136          newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
01137          ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password));
01138          if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
01139             newcandidate->protocol = AJI_PROTOCOL_UDP;
01140          else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
01141             newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
01142          
01143          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host"))
01144             newcandidate->type = AJI_CONNECT_HOST;
01145          else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx"))
01146             newcandidate->type = AJI_CONNECT_PRFLX;
01147          else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
01148             newcandidate->type = AJI_CONNECT_RELAY;
01149          else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx"))
01150             newcandidate->type = AJI_CONNECT_SRFLX;
01151 
01152          newcandidate->network = atoi(iks_find_attrib(traversenodes, "network"));
01153          newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
01154          newcandidate->next = NULL;
01155       
01156          newcandidate->next = p->theircandidates;
01157          p->theircandidates = newcandidate;
01158          p->laststun = 0;
01159          jingle_update_stun(p->parent, p);
01160          newcandidate = NULL;
01161       }
01162       traversenodes = iks_next(traversenodes);
01163    }
01164    
01165    receipt = iks_new("iq");
01166    iks_insert_attrib(receipt, "type", "result");
01167    iks_insert_attrib(receipt, "from", c->jid->full);
01168    iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
01169    iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
01170    ast_aji_send(c, receipt);
01171 
01172    iks_delete(receipt);
01173 
01174    return 1;
01175 }

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

Definition at line 742 of file chan_jingle.c.

References ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_rtp_instance_new(), ast_sockaddr_from_sin, ASTOBJ_CONTAINER_FIND, bindaddr, aji_client::buddies, jingle::buddy, aji_resource::cap, jingle::connection, aji_version::jingle, jinglelock, LOG_ERROR, LOG_WARNING, jingle::name, aji_resource::next, jingle::p, jingle::prefs, aji_resource::resource, and aji_buddy::resources.

Referenced by jingle_newcall(), and jingle_request().

00743 {
00744    struct jingle_pvt *tmp = NULL;
00745    struct aji_resource *resources = NULL;
00746    struct aji_buddy *buddy;
00747    char idroster[200];
00748    struct ast_sockaddr bindaddr_tmp;
00749 
00750    ast_debug(1, "The client is %s for alloc\n", client->name);
00751    if (!sid && !strchr(from, '/')) {   /* I started call! */
00752       if (!strcasecmp(client->name, "guest")) {
00753          buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from);
00754          if (buddy)
00755             resources = buddy->resources;
00756       } else if (client->buddy)
00757          resources = client->buddy->resources;
00758       while (resources) {
00759          if (resources->cap->jingle) {
00760             break;
00761          }
00762          resources = resources->next;
00763       }
00764       if (resources)
00765          snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource);
00766       else {
00767          ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n");
00768          return NULL;
00769       }
00770    }
00771    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00772       return NULL;
00773    }
00774 
00775    memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
00776 
00777    if (sid) {
00778       ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00779       ast_copy_string(tmp->them, from, sizeof(tmp->them));
00780    } else {
00781       snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00782       ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00783       tmp->initiator = 1;
00784    }
00785    ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
00786    tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
00787    tmp->parent = client;
00788    if (!tmp->rtp) {
00789       ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00790       ast_free(tmp);
00791       return NULL;
00792    }
00793    ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
00794    ast_mutex_init(&tmp->lock);
00795    ast_mutex_lock(&jinglelock);
00796    tmp->next = client->p;
00797    client->p = tmp;
00798    ast_mutex_unlock(&jinglelock);
00799    return tmp;
00800 }

static int jingle_answer ( struct ast_channel ast  )  [static]

Definition at line 376 of file chan_jingle.c.

References ast_debug, ast_mutex_lock, ast_mutex_unlock, jingle_accept_call(), jingle_pvt::lock, jingle::p, jingle_pvt::parent, and ast_channel::tech_pvt.

00377 {
00378    struct jingle_pvt *p = ast->tech_pvt;
00379    struct jingle *client = p->parent;
00380    int res = 0;
00381 
00382    ast_debug(1, "Answer!\n");
00383    ast_mutex_lock(&p->lock);
00384    jingle_accept_call(client, p);
00385    ast_mutex_unlock(&p->lock);
00386    return res;
00387 }

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

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

Definition at line 1457 of file chan_jingle.c.

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

01458 {
01459    struct jingle_pvt *p = ast->tech_pvt;
01460 
01461    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01462       ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name);
01463       return -1;
01464    }
01465 
01466    ast_setstate(ast, AST_STATE_RING);
01467    p->jointcapability = p->capability;
01468    if (!p->ringrule) {
01469       ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01470       p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
01471                      IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01472    } else
01473       ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01474 
01475    jingle_transmit_invite(p);
01476    jingle_create_candidates(p->parent, p, p->sid, p->them);
01477 
01478    return 0;
01479 }

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

Definition at line 578 of file chan_jingle.c.

References __ourip, AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_find_ourip(), ast_free, ast_inet_ntoa(), ast_log(), ast_random(), ast_rtp_instance_get_local_address(), ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ast_sockaddr_to_sin, ast_strlen_zero(), bindaddr, jingle_candidate::component, jingle::connection, externip, 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().

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

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 1699 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::capability, jingle::connection, jingle::context, aji_client::f, JINGLE_NS, jingle_parser(), LOG_ERROR, LOG_WARNING, jingle::name, jingle_candidate::next, prefs, jingle::prefs, jingle::user, and var.

01702 {
01703    struct aji_client *client;
01704 
01705    if (!member)
01706       ast_log(LOG_WARNING, "Out of memory.\n");
01707 
01708    ast_copy_string(member->name, label, sizeof(member->name));
01709    ast_copy_string(member->user, label, sizeof(member->user));
01710    ast_copy_string(member->context, context, sizeof(member->context));
01711    member->allowguest = allowguest;
01712    member->prefs = prefs;
01713    while (var) {
01714 #if 0
01715       struct jingle_candidate *candidate = NULL;
01716 #endif
01717       if (!strcasecmp(var->name, "username"))
01718          ast_copy_string(member->user, var->value, sizeof(member->user));
01719       else if (!strcasecmp(var->name, "disallow"))
01720          ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
01721       else if (!strcasecmp(var->name, "allow"))
01722          ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
01723       else if (!strcasecmp(var->name, "context"))
01724          ast_copy_string(member->context, var->value, sizeof(member->context));
01725 #if 0
01726       else if (!strcasecmp(var->name, "candidate")) {
01727          candidate = jingle_create_candidate(var->value);
01728          if (candidate) {
01729             candidate->next = member->ourcandidates;
01730             member->ourcandidates = candidate;
01731          }
01732       }
01733 #endif
01734       else if (!strcasecmp(var->name, "connection")) {
01735          if ((client = ast_aji_get_client(var->value))) {
01736             member->connection = client;
01737             iks_filter_add_rule(client->f, jingle_parser, member,
01738                       IKS_RULE_TYPE, IKS_PAK_IQ,
01739                       IKS_RULE_FROM_PARTIAL, member->user,
01740                       IKS_RULE_NS, JINGLE_NS,
01741                       IKS_RULE_DONE);
01742          } else {
01743             ast_log(LOG_ERROR, "connection referenced not found!\n");
01744             return 0;
01745          }
01746       }
01747       var = var->next;
01748    }
01749    if (member->connection && member->user)
01750       member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
01751    else {
01752       ast_log(LOG_ERROR, "No Connection or Username!\n");
01753    }
01754    return 1;
01755 }

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

Definition at line 1317 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::p, jingle_pvt::parent, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.

Referenced by jingle_digit_begin(), and jingle_digit_end().

01318 {
01319    struct jingle_pvt *p = ast->tech_pvt;
01320    struct jingle *client = p->parent;
01321    iks *iq, *jingle, *dtmf;
01322    char buffer[2] = {digit, '\0'};
01323    iq = iks_new("iq");
01324    jingle = iks_new("jingle");
01325    dtmf = iks_new("dtmf");
01326    if(!iq || !jingle || !dtmf) {
01327       iks_delete(iq);
01328       iks_delete(jingle);
01329       iks_delete(dtmf);
01330       ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
01331       return -1;
01332    }
01333 
01334    iks_insert_attrib(iq, "type", "set");
01335    iks_insert_attrib(iq, "to", p->them);
01336    iks_insert_attrib(iq, "from", client->connection->jid->full);
01337    iks_insert_attrib(iq, "id", client->connection->mid);
01338    ast_aji_increment_mid(client->connection->mid);
01339    iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01340    iks_insert_attrib(jingle, "action", "session-info");
01341    iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
01342    iks_insert_attrib(jingle, "sid", p->sid);
01343    iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS);
01344    iks_insert_attrib(dtmf, "code", buffer);
01345    iks_insert_node(iq, jingle);
01346    iks_insert_node(jingle, dtmf);
01347 
01348    ast_mutex_lock(&p->lock);
01349    if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
01350       iks_insert_attrib(dtmf, "action", "button-down");
01351    } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
01352       iks_insert_attrib(dtmf, "action", "button-up");
01353    }
01354    ast_aji_send(client->connection, iq);
01355 
01356    iks_delete(iq);
01357    iks_delete(jingle);
01358    iks_delete(dtmf);
01359    ast_mutex_unlock(&p->lock);
01360    return 0;
01361 }

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

Definition at line 1363 of file chan_jingle.c.

References jingle_digit().

01364 {
01365    return jingle_digit(chan, digit, 0);
01366 }

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

Definition at line 1368 of file chan_jingle.c.

References jingle_digit().

01369 {
01370    return jingle_digit(ast, digit, duration);
01371 }

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

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

01611 {
01612    switch (cmd) {
01613    case CLI_INIT:
01614       e->command = "jingle reload";
01615       e->usage =
01616          "Usage: jingle reload\n"
01617          "       Reload jingle channel driver.\n";
01618       return NULL;
01619    case CLI_GENERATE:
01620       return NULL;
01621    }  
01622    
01623    return CLI_SUCCESS;
01624 }

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

Definition at line 1263 of file chan_jingle.c.

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

01264 {
01265    struct jingle_pvt *p = newchan->tech_pvt;
01266    ast_mutex_lock(&p->lock);
01267 
01268    if ((p->owner != oldchan)) {
01269       ast_mutex_unlock(&p->lock);
01270       return -1;
01271    }
01272    if (p->owner == oldchan)
01273       p->owner = newchan;
01274    ast_mutex_unlock(&p->lock);
01275    return 0;
01276 }

static void jingle_free_candidates ( struct jingle_candidate candidate  )  [static]

Definition at line 924 of file chan_jingle.c.

References ast_free, last, and jingle_candidate::next.

Referenced by jingle_free_pvt().

00925 {
00926    struct jingle_candidate *last;
00927    while (candidate) {
00928       last = candidate;
00929       candidate = candidate->next;
00930       ast_free(last);
00931    }
00932 }

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

Definition at line 934 of file chan_jingle.c.

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

Referenced by jingle_hangup(), and jingle_newcall().

00935 {
00936    struct jingle_pvt *cur, *prev = NULL;
00937    cur = client->p;
00938    while (cur) {
00939       if (cur == p) {
00940          if (prev)
00941             prev->next = p->next;
00942          else
00943             client->p = p->next;
00944          break;
00945       }
00946       prev = cur;
00947       cur = cur->next;
00948    }
00949    if (p->ringrule)
00950       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00951    if (p->owner)
00952       ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
00953    if (p->rtp)
00954       ast_rtp_instance_destroy(p->rtp);
00955    if (p->vrtp)
00956       ast_rtp_instance_destroy(p->vrtp);
00957    jingle_free_candidates(p->theircandidates);
00958    ast_free(p);
00959 }

static format_t jingle_get_codec ( struct ast_channel chan  )  [static]

Definition at line 408 of file chan_jingle.c.

References jingle_pvt::peercapability, and ast_channel::tech_pvt.

00409 {
00410    struct jingle_pvt *p = chan->tech_pvt;
00411    return p->peercapability;
00412 }

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

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

00390 {
00391    struct jingle_pvt *p = chan->tech_pvt;
00392    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
00393 
00394    if (!p)
00395       return res;
00396 
00397    ast_mutex_lock(&p->lock);
00398    if (p->rtp) {
00399       ao2_ref(p->rtp, +1);
00400       *instance = p->rtp;
00401       res = AST_RTP_GLUE_RESULT_LOCAL;
00402    }
00403    ast_mutex_unlock(&p->lock);
00404 
00405    return res;
00406 }

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

Definition at line 493 of file chan_jingle.c.

References AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), ast_verbose, f, JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle_pvt::next, jingle_pvt::owner, jingle::p, and jingle_pvt::sid.

Referenced by jingle_parser().

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

static int jingle_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the jingle proxy channel.

Definition at line 1482 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::p, jingle_pvt::parent, and ast_channel::tech_pvt.

01483 {
01484    struct jingle_pvt *p = ast->tech_pvt;
01485    struct jingle *client;
01486 
01487    ast_mutex_lock(&p->lock);
01488    client = p->parent;
01489    p->owner = NULL;
01490    ast->tech_pvt = NULL;
01491    if (!p->alreadygone)
01492       jingle_action(client, p, JINGLE_TERMINATE);
01493    ast_mutex_unlock(&p->lock);
01494 
01495    jingle_free_pvt(client, p);
01496 
01497    return 0;
01498 }

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

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

00558 {
00559    struct jingle_pvt *tmp;
00560 
00561    ast_debug(1, "The client is %s\n", client->name);
00562    /* Make sure our new call doesn't exist yet */
00563    for (tmp = client->p; tmp; tmp = tmp->next) {
00564       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
00565          break;
00566    }
00567 
00568    if (tmp) {
00569       tmp->alreadygone = 1;
00570       if (tmp->owner)
00571          ast_queue_hangup(tmp->owner);
00572    } else
00573       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00574    jingle_response(client, pak, NULL, NULL);
00575    return 1;
00576 }

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

Definition at line 1278 of file chan_jingle.c.

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

01279 {
01280    int res = 0;
01281 
01282    switch (condition) {
01283    case AST_CONTROL_HOLD:
01284       ast_moh_start(ast, data, NULL);
01285       break;
01286    case AST_CONTROL_UNHOLD:
01287       ast_moh_stop(ast);
01288       break;
01289    default:
01290       ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01291       res = -1;
01292    }
01293 
01294    return res;
01295 }

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

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

00474 {
00475    struct jingle_pvt *tmp;
00476 
00477    ast_debug(1, "The client is %s\n", client->name);
00478    /* Make sure our new call doesn't exist yet */
00479    for (tmp = client->p; tmp; tmp = tmp->next) {
00480       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
00481          break;
00482    }
00483 
00484    if (tmp) {
00485       if (tmp->owner)
00486          ast_queue_control(tmp->owner, AST_CONTROL_ANSWER);
00487    } else
00488       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00489    jingle_response(client, pak, NULL, NULL);
00490    return 1;
00491 }

static int jingle_load_config ( void   )  [static]

Definition at line 1757 of file chan_jingle.c.

References ahp, ast_category_browse(), ast_config_load, ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_parse_allow_disallow(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), bindaddr, clients, config_flags, CONFIG_STATUS_FILEINVALID, context, default_jbconf, externip, global_capability, global_jbconf, hp, JINGLE_CONFIG, LOG_WARNING, prefs, and var.

Referenced by load_module().

01758 {
01759    char *cat = NULL;
01760    struct ast_config *cfg = NULL;
01761    char context[100];
01762    int allowguest = 1;
01763    struct ast_variable *var;
01764    struct jingle *member;
01765    struct hostent *hp;
01766    struct ast_hostent ahp;
01767    struct ast_codec_pref prefs;
01768    struct aji_client_container *clients;
01769    struct jingle_candidate *global_candidates = NULL;
01770    struct ast_flags config_flags = { 0 };
01771 
01772    cfg = ast_config_load(JINGLE_CONFIG, config_flags);
01773    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
01774       return 0;
01775    }
01776 
01777    /* Copy the default jb config over global_jbconf */
01778    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01779 
01780    cat = ast_category_browse(cfg, NULL);
01781    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
01782       /* handle jb conf */
01783       if (!ast_jb_read_conf(&global_jbconf, var->name, var->value))
01784          continue;
01785 
01786       if (!strcasecmp(var->name, "allowguest"))
01787          allowguest =
01788             (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
01789       else if (!strcasecmp(var->name, "disallow"))
01790          ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0);
01791       else if (!strcasecmp(var->name, "allow"))
01792          ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
01793       else if (!strcasecmp(var->name, "context"))
01794          ast_copy_string(context, var->value, sizeof(context));
01795       else if (!strcasecmp(var->name, "externip"))
01796          ast_copy_string(externip, var->value, sizeof(externip));
01797       else if (!strcasecmp(var->name, "bindaddr")) {
01798          if (!(hp = ast_gethostbyname(var->value, &ahp))) {
01799             ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
01800          } else {
01801             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
01802          }
01803       }
01804 /*  Idea to allow for custom candidates  */
01805 /*
01806       else if (!strcasecmp(var->name, "candidate")) {
01807          candidate = jingle_create_candidate(var->value);
01808          if (candidate) {
01809             candidate->next = global_candidates;
01810             global_candidates = candidate;
01811          }
01812       }
01813 */
01814    }
01815    while (cat) {
01816       if (strcasecmp(cat, "general")) {
01817          var = ast_variable_browse(cfg, cat);
01818          member = ast_calloc(1, sizeof(*member));
01819          ASTOBJ_INIT(member);
01820          ASTOBJ_WRLOCK(member);
01821          if (!strcasecmp(cat, "guest")) {
01822             ast_copy_string(member->name, "guest", sizeof(member->name));
01823             ast_copy_string(member->user, "guest", sizeof(member->user));
01824             ast_copy_string(member->context, context, sizeof(member->context));
01825             member->allowguest = allowguest;
01826             member->prefs = prefs;
01827             while (var) {
01828                if (!strcasecmp(var->name, "disallow"))
01829                   ast_parse_allow_disallow(&member->prefs, &member->capability,
01830                                      var->value, 0);
01831                else if (!strcasecmp(var->name, "allow"))
01832                   ast_parse_allow_disallow(&member->prefs, &member->capability,
01833                                      var->value, 1);
01834                else if (!strcasecmp(var->name, "context"))
01835                   ast_copy_string(member->context, var->value,
01836                               sizeof(member->context));
01837                else if (!strcasecmp(var->name, "parkinglot"))
01838                   ast_copy_string(member->parkinglot, var->value,
01839                               sizeof(member->parkinglot));
01840 /*  Idea to allow for custom candidates  */
01841 /*
01842                else if (!strcasecmp(var->name, "candidate")) {
01843                   candidate = jingle_create_candidate(var->value);
01844                   if (candidate) {
01845                      candidate->next = member->ourcandidates;
01846                      member->ourcandidates = candidate;
01847                   }
01848                }
01849 */
01850                var = var->next;
01851             }
01852             ASTOBJ_UNLOCK(member);
01853             clients = ast_aji_get_clients();
01854             if (clients) {
01855                ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
01856                   ASTOBJ_WRLOCK(iterator);
01857                   ASTOBJ_WRLOCK(member);
01858                   member->connection = NULL;
01859                   iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE);
01860                   iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE);
01861                   ASTOBJ_UNLOCK(member);
01862                   ASTOBJ_UNLOCK(iterator);
01863                });
01864                ASTOBJ_CONTAINER_LINK(&jingle_list, member);
01865             } else {
01866                ASTOBJ_UNLOCK(member);
01867                ASTOBJ_UNREF(member, jingle_member_destroy);
01868             }
01869          } else {
01870             ASTOBJ_UNLOCK(member);
01871             if (jingle_create_member(cat, var, allowguest, prefs, context, member))
01872                ASTOBJ_CONTAINER_LINK(&jingle_list, member);
01873             ASTOBJ_UNREF(member, jingle_member_destroy);
01874          }
01875       }
01876       cat = ast_category_browse(cfg, cat);
01877    }
01878    jingle_free_candidates(global_candidates);
01879    return 1;
01880 }

static void jingle_member_destroy ( struct jingle obj  )  [static]

Definition at line 227 of file chan_jingle.c.

References ast_free.

Referenced by jingle_parser(), and unload_module().

00228 {
00229    ast_free(obj);
00230 }

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

Start new jingle channel.

Definition at line 803 of file chan_jingle.c.

References accountcode, 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_set_fd(), ast_codec_choose(), ast_copy_string(), AST_FORMAT_VIDEO_MASK, ast_hangup(), ast_jb_configure(), ast_log(), ast_pbx_start(), ast_random(), ast_rtp_codecs_packetization_set(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_channel::caller, jingle::callgroup, ast_channel::callgroup, jingle::callingpres, jingle_pvt::capability, jingle_pvt::cid_name, jingle_pvt::cid_num, jingle::context, ast_channel::context, ast_channel::dialed, jingle_pvt::exten, ast_channel::exten, global_capability, global_jbconf, ast_channel::hangupcause, ast_party_caller::id, jingle_tech, jingle_pvt::jointcapability, language, jingle::language, LOG_WARNING, musicclass, jingle::musicclass, ast_channel::name, 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().

00804 {
00805    struct ast_channel *tmp;
00806    int fmt;
00807    int what;
00808    const char *str;
00809 
00810    if (title)
00811       str = title;
00812    else
00813       str = i->them;
00814    tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff);
00815    if (!tmp) {
00816       ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
00817       return NULL;
00818    }
00819    tmp->tech = &jingle_tech;
00820 
00821    /* Select our native format based on codec preference until we receive
00822       something from another device to the contrary. */
00823    if (i->jointcapability)
00824       what = i->jointcapability;
00825    else if (i->capability)
00826       what = i->capability;
00827    else
00828       what = global_capability;
00829 
00830    /* Set Frame packetization */
00831    if (i->rtp)
00832       ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
00833 
00834    tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
00835    fmt = ast_best_codec(tmp->nativeformats);
00836 
00837    if (i->rtp) {
00838       ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
00839       ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
00840    }
00841    if (i->vrtp) {
00842       ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
00843       ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
00844    }
00845    if (state == AST_STATE_RING)
00846       tmp->rings = 1;
00847    tmp->adsicpe = AST_ADSI_UNAVAILABLE;
00848    tmp->writeformat = fmt;
00849    tmp->rawwriteformat = fmt;
00850    tmp->readformat = fmt;
00851    tmp->rawreadformat = fmt;
00852    tmp->tech_pvt = i;
00853 
00854    tmp->callgroup = client->callgroup;
00855    tmp->pickupgroup = client->pickupgroup;
00856    tmp->caller.id.name.presentation = client->callingpres;
00857    tmp->caller.id.number.presentation = client->callingpres;
00858    if (!ast_strlen_zero(client->accountcode))
00859       ast_string_field_set(tmp, accountcode, client->accountcode);
00860    if (client->amaflags)
00861       tmp->amaflags = client->amaflags;
00862    if (!ast_strlen_zero(client->language))
00863       ast_string_field_set(tmp, language, client->language);
00864    if (!ast_strlen_zero(client->musicclass))
00865       ast_string_field_set(tmp, musicclass, client->musicclass);
00866    i->owner = tmp;
00867    ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
00868    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
00869    /* Don't use ast_set_callerid() here because it will
00870     * generate an unnecessary NewCallerID event  */
00871    if (!ast_strlen_zero(i->cid_num)) {
00872       tmp->caller.ani.number.valid = 1;
00873       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
00874    }
00875    if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) {
00876       tmp->dialed.number.str = ast_strdup(i->exten);
00877    }
00878    tmp->priority = 1;
00879    if (i->rtp)
00880       ast_jb_configure(tmp, &global_jbconf);
00881    if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
00882       ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00883       tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
00884       ast_hangup(tmp);
00885       tmp = NULL;
00886    }
00887 
00888    return tmp;
00889 }

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

Definition at line 962 of file chan_jingle.c.

References ast_aji_get_client(), ast_copy_string(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_rtp_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, 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().

00963 {
00964    struct jingle_pvt *p, *tmp = client->p;
00965    struct ast_channel *chan;
00966    int res;
00967    iks *codec, *content, *description;
00968    char *from = NULL;
00969 
00970    /* Make sure our new call doesn't exist yet */
00971    from = iks_find_attrib(pak->x,"to");
00972    if(!from)
00973       from = client->connection->jid->full;
00974 
00975    while (tmp) {
00976       if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
00977          ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
00978          jingle_response(client, pak, "out-of-order", NULL);
00979          return -1;
00980       }
00981       tmp = tmp->next;
00982    }
00983 
00984    if (!strcasecmp(client->name, "guest")){
00985       /* the guest account is not tied to any configured XMPP client,
00986          let's set it now */
00987       client->connection = ast_aji_get_client(from);
00988       if (!client->connection) {
00989          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from);
00990          return -1;
00991       }
00992    }
00993 
00994    p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID));
00995    if (!p) {
00996       ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
00997       return -1;
00998    }
00999    chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user, NULL);
01000    if (!chan) {
01001       jingle_free_pvt(client, p);
01002       return -1;
01003    }
01004    ast_mutex_lock(&p->lock);
01005    ast_copy_string(p->them, pak->from->full, sizeof(p->them));
01006    if (iks_find_attrib(pak->query, JINGLE_SID)) {
01007       ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID),
01008             sizeof(p->sid));
01009    }
01010    
01011    /* content points to the first <content/> tag */   
01012    content = iks_child(iks_child(pak->x));
01013    while (content) {
01014       description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS);
01015       if (description) {
01016          /* audio content found */
01017          codec = iks_child(iks_child(content));
01018               ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
01019 
01020          while (codec) {
01021             ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
01022             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);
01023             codec = iks_next(codec);
01024          }
01025       }
01026       
01027       description = NULL;
01028       codec = NULL;
01029 
01030       description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS);
01031       if (description) {
01032          /* video content found */
01033          codec = iks_child(iks_child(content));
01034               ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
01035 
01036          while (codec) {
01037             ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
01038             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);
01039             codec = iks_next(codec);
01040          }
01041       }
01042       
01043       content = iks_next(content);
01044    }
01045 
01046    ast_mutex_unlock(&p->lock);
01047    ast_setstate(chan, AST_STATE_RING);
01048    res = ast_pbx_start(chan);
01049    
01050    switch (res) {
01051    case AST_PBX_FAILED:
01052       ast_log(LOG_WARNING, "Failed to start PBX :(\n");
01053       jingle_response(client, pak, "service-unavailable", NULL);
01054       break;
01055    case AST_PBX_CALL_LIMIT:
01056       ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
01057       jingle_response(client, pak, "service-unavailable", NULL);
01058       break;
01059    case AST_PBX_SUCCESS:
01060       jingle_response(client, pak, NULL, NULL);
01061       jingle_create_candidates(client, p,
01062                 iks_find_attrib(pak->query, JINGLE_SID),
01063                 iks_find_attrib(pak->x, "from"));
01064       /* nothing to do */
01065       break;
01066    }
01067 
01068    return 1;
01069 }

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

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

01627 {
01628    struct jingle *client = ASTOBJ_REF((struct jingle *) data);
01629    ast_log(LOG_NOTICE, "Filter matched\n");
01630 
01631    if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
01632       /* New call */
01633       jingle_newcall(client, pak);
01634    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
01635       ast_debug(3, "About to add candidate!\n");
01636       jingle_add_candidate(client, pak);
01637       ast_debug(3, "Candidate Added!\n");
01638    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
01639       jingle_is_answered(client, pak);
01640    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
01641       jingle_handle_dtmf(client, pak);
01642    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
01643       jingle_hangup_farend(client, pak);
01644    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
01645       jingle_hangup_farend(client, pak);
01646    }
01647    ASTOBJ_UNREF(client, jingle_member_destroy);
01648    return IKS_FILTER_EAT;
01649 }

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

Definition at line 1205 of file chan_jingle.c.

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

01206 {
01207    struct ast_frame *fr;
01208    struct jingle_pvt *p = ast->tech_pvt;
01209 
01210    ast_mutex_lock(&p->lock);
01211    fr = jingle_rtp_read(ast, p);
01212    ast_mutex_unlock(&p->lock);
01213    return fr;
01214 }

static struct ast_channel * jingle_request ( const char *  type,
format_t  format,
const struct ast_channel requestor,
void *  data,
int *  cause 
) [static]

Part of PBX interface.

Definition at line 1501 of file chan_jingle.c.

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

01502 {
01503    struct jingle_pvt *p = NULL;
01504    struct jingle *client = NULL;
01505    char *sender = NULL, *to = NULL, *s = NULL;
01506    struct ast_channel *chan = NULL;
01507 
01508    if (data) {
01509       s = ast_strdupa(data);
01510       if (s) {
01511          sender = strsep(&s, "/");
01512          if (sender && (sender[0] != '\0'))
01513             to = strsep(&s, "/");
01514          if (!to) {
01515             ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data);
01516             return NULL;
01517          }
01518       }
01519    }
01520 
01521    client = find_jingle(to, sender);
01522    if (!client) {
01523       ast_log(LOG_WARNING, "Could not find recipient.\n");
01524       return NULL;
01525    }
01526    if (!strcasecmp(client->name, "guest")){
01527       /* the guest account is not tied to any configured XMPP client,
01528          let's set it now */
01529       client->connection = ast_aji_get_client(sender);
01530       if (!client->connection) {
01531          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01532          return NULL;
01533       }
01534    }
01535        
01536    ASTOBJ_WRLOCK(client);
01537    p = jingle_alloc(client, to, NULL);
01538    if (p)
01539       chan = jingle_new(client, p, AST_STATE_DOWN, to, requestor ? requestor->linkedid : NULL);
01540    ASTOBJ_UNLOCK(client);
01541 
01542    return chan;
01543 }

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

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

00442 {
00443    iks *response = NULL, *error = NULL, *reason = NULL;
00444    int res = -1;
00445 
00446    response = iks_new("iq");
00447    if (response) {
00448       iks_insert_attrib(response, "type", "result");
00449       iks_insert_attrib(response, "from", client->connection->jid->full);
00450       iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
00451       iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
00452       if (reasonstr) {
00453          error = iks_new("error");
00454          if (error) {
00455             iks_insert_attrib(error, "type", "cancel");
00456             reason = iks_new(reasonstr);
00457             if (reason)
00458                iks_insert_node(error, reason);
00459             iks_insert_node(response, error);
00460          }
00461       }
00462       ast_aji_send(client->connection, response);
00463       res = 0;
00464    }
00465    
00466    iks_delete(reason);
00467    iks_delete(error);
00468    iks_delete(response);
00469 
00470    return res;
00471 }

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

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

00365 {
00366    struct jingle_pvt *p = data;
00367 
00368    if (p->ringrule)
00369       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00370    p->ringrule = NULL;
00371    if (p->owner)
00372       ast_queue_control(p->owner, AST_CONTROL_RINGING);
00373    return IKS_FILTER_EAT;
00374 }

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

Definition at line 1177 of file chan_jingle.c.

References ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_VOICE, ast_getformatname(), ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), f, jingle_update_stun(), ast_channel::nativeformats, jingle_pvt::owner, jingle_pvt::parent, ast_channel::readformat, jingle_pvt::rtp, and ast_channel::writeformat.

Referenced by jingle_read().

01178 {
01179    struct ast_frame *f;
01180 
01181    if (!p->rtp)
01182       return &ast_null_frame;
01183    f = ast_rtp_instance_read(p->rtp, 0);
01184    jingle_update_stun(p->parent, p);
01185    if (p->owner) {
01186       /* We already hold the channel lock */
01187       if (f->frametype == AST_FRAME_VOICE) {
01188          if (f->subclass.codec != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
01189             ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec));
01190             p->owner->nativeformats =
01191                (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass.codec;
01192             ast_set_read_format(p->owner, p->owner->readformat);
01193             ast_set_write_format(p->owner, p->owner->writeformat);
01194          }
01195 /*       if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
01196             f = ast_dsp_process(p->owner, p->vad, f);
01197             if (f && (f->frametype == AST_FRAME_DTMF))
01198                ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.codec);
01199               } */
01200       }
01201    }
01202    return f;
01203 }

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

Definition at line 1373 of file chan_jingle.c.

References ast_log(), and LOG_NOTICE.

01374 {
01375    ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
01376 
01377    return -1;
01378 }

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

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

01298 {
01299    int res = 0;
01300    struct aji_client *client = NULL;
01301    struct jingle_pvt *p = chan->tech_pvt;
01302 
01303 
01304    if (!p->parent) {
01305       ast_log(LOG_ERROR, "Parent channel not found\n");
01306       return -1;
01307    }
01308    if (!p->parent->connection) {
01309       ast_log(LOG_ERROR, "XMPP client not found\n");
01310       return -1;
01311    }
01312    client = p->parent->connection;
01313    res = ast_aji_send_chat(client, p->them, text);
01314    return res;
01315 }

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,
format_t  codecs,
int  nat_active 
) [static]

Definition at line 414 of file chan_jingle.c.

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

00415 {
00416    struct jingle_pvt *p;
00417 
00418    p = chan->tech_pvt;
00419    if (!p)
00420       return -1;
00421    ast_mutex_lock(&p->lock);
00422 
00423 /* if (rtp)
00424       ast_rtp_get_peer(rtp, &p->redirip);
00425    else
00426       memset(&p->redirip, 0, sizeof(p->redirip));
00427    p->redircodecs = codecs; */
00428 
00429    /* Reset lastrtprx timer */
00430    ast_mutex_unlock(&p->lock);
00431    return 0;
00432 }

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

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

01547 {
01548 #define FORMAT  "%-30.30s  %-30.30s  %-15.15s  %-5.5s %-5.5s \n"
01549    struct jingle_pvt *p;
01550    struct ast_channel *chan;
01551    int numchans = 0;
01552    char them[AJI_MAX_JIDLEN];
01553    char *jid = NULL;
01554    char *resource = NULL;
01555 
01556    switch (cmd) {
01557    case CLI_INIT:
01558       e->command = "jingle show channels";
01559       e->usage =
01560          "Usage: jingle show channels\n"
01561          "       Shows current state of the Jingle channels.\n";
01562       return NULL;
01563    case CLI_GENERATE:
01564       return NULL;
01565    }
01566 
01567    if (a->argc != 3)
01568       return CLI_SHOWUSAGE;
01569 
01570    ast_mutex_lock(&jinglelock);
01571    ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
01572    ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01573       ASTOBJ_WRLOCK(iterator);
01574       p = iterator->p;
01575       while(p) {
01576          chan = p->owner;
01577          ast_copy_string(them, p->them, sizeof(them));
01578          jid = them;
01579          resource = strchr(them, '/');
01580          if (!resource)
01581             resource = "None";
01582          else {
01583             *resource = '\0';
01584             resource ++;
01585          }
01586          if (chan)
01587             ast_cli(a->fd, FORMAT, 
01588                chan->name,
01589                jid,
01590                resource,
01591                ast_getformatname(chan->readformat),
01592                ast_getformatname(chan->writeformat)               
01593                );
01594          else 
01595             ast_log(LOG_WARNING, "No available channel\n");
01596          numchans ++;
01597          p = p->next;
01598       }
01599       ASTOBJ_UNLOCK(iterator);
01600    });
01601 
01602    ast_mutex_unlock(&jinglelock);
01603 
01604    ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : "");
01605    return CLI_SUCCESS;
01606 #undef FORMAT
01607 }

static int jingle_transmit_invite ( struct jingle_pvt p  )  [static]

Definition at line 1379 of file chan_jingle.c.

References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle::connection, aji_client::jid, JINGLE_AUDIO_RTP_NS, JINGLE_ICE_UDP_NS, JINGLE_INITIATE, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, and aji_client::p.

Referenced by jingle_call().

01380 {
01381    struct jingle *aux = NULL;
01382    struct aji_client *client = NULL;
01383    iks *iq, *jingle, *content, *description, *transport;
01384    iks *payload_eg711u, *payload_pcmu;
01385 
01386    aux = p->parent;
01387    client = aux->connection;
01388    iq = iks_new("iq");
01389    jingle = iks_new(JINGLE_NODE);
01390    content = iks_new("content");
01391    description = iks_new("description");
01392    transport = iks_new("transport");
01393    payload_pcmu = iks_new("payload-type");
01394    payload_eg711u = iks_new("payload-type");
01395 
01396    ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name));
01397 
01398    iks_insert_attrib(iq, "type", "set");
01399    iks_insert_attrib(iq, "to", p->them);
01400    iks_insert_attrib(iq, "from", client->jid->full);
01401    iks_insert_attrib(iq, "id", client->mid);
01402    ast_aji_increment_mid(client->mid);
01403    iks_insert_attrib(jingle, "action", JINGLE_INITIATE);
01404    iks_insert_attrib(jingle, JINGLE_SID, p->sid);
01405    iks_insert_attrib(jingle, "initiator", client->jid->full);
01406    iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01407 
01408    /* For now, we only send one audio based content */
01409    iks_insert_attrib(content, "creator", "initiator");
01410    iks_insert_attrib(content, "name", p->audio_content_name);
01411    iks_insert_attrib(content, "profile", "RTP/AVP");
01412    iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS);
01413    iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
01414    iks_insert_attrib(payload_pcmu, "id", "0");
01415    iks_insert_attrib(payload_pcmu, "name", "PCMU");
01416    iks_insert_attrib(payload_eg711u, "id", "100");
01417    iks_insert_attrib(payload_eg711u, "name", "EG711U");
01418    iks_insert_node(description, payload_pcmu);
01419    iks_insert_node(description, payload_eg711u);
01420    iks_insert_node(content, description);
01421    iks_insert_node(content, transport);
01422    iks_insert_node(jingle, content);
01423    iks_insert_node(iq, jingle);
01424 
01425    ast_aji_send(client, iq);
01426 
01427    iks_delete(iq);
01428    iks_delete(jingle);
01429    iks_delete(content);
01430    iks_delete(description);
01431    iks_delete(transport);
01432    iks_delete(payload_eg711u);
01433    iks_delete(payload_pcmu);
01434    return 0;
01435 }

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

Definition at line 1071 of file chan_jingle.c.

References ahp, 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().

01072 {
01073    struct jingle_candidate *tmp;
01074    struct hostent *hp;
01075    struct ast_hostent ahp;
01076    struct sockaddr_in sin;
01077    struct ast_sockaddr sin_tmp;
01078 
01079    if (time(NULL) == p->laststun)
01080       return 0;
01081 
01082    tmp = p->theircandidates;
01083    p->laststun = time(NULL);
01084    while (tmp) {
01085       char username[256];
01086       hp = ast_gethostbyname(tmp->ip, &ahp);
01087       sin.sin_family = AF_INET;
01088       memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01089       sin.sin_port = htons(tmp->port);
01090       snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
01091 
01092       ast_sockaddr_from_sin(&sin_tmp, &sin);
01093       ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username);
01094       tmp = tmp->next;
01095    }
01096    return 1;
01097 }

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

Send frame to media channel (rtp).

Definition at line 1217 of file chan_jingle.c.

References 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::codec, 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.

01218 {
01219    struct jingle_pvt *p = ast->tech_pvt;
01220    int res = 0;
01221    char buf[256];
01222 
01223    switch (frame->frametype) {
01224    case AST_FRAME_VOICE:
01225       if (!(frame->subclass.codec & ast->nativeformats)) {
01226          ast_log(LOG_WARNING,
01227                "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
01228                ast_getformatname(frame->subclass.codec),
01229                ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
01230                ast_getformatname(ast->readformat),
01231                ast_getformatname(ast->writeformat));
01232          return 0;
01233       }
01234       if (p) {
01235          ast_mutex_lock(&p->lock);
01236          if (p->rtp) {
01237             res = ast_rtp_instance_write(p->rtp, frame);
01238          }
01239          ast_mutex_unlock(&p->lock);
01240       }
01241       break;
01242    case AST_FRAME_VIDEO:
01243       if (p) {
01244          ast_mutex_lock(&p->lock);
01245          if (p->vrtp) {
01246             res = ast_rtp_instance_write(p->vrtp, frame);
01247          }
01248          ast_mutex_unlock(&p->lock);
01249       }
01250       break;
01251    case AST_FRAME_IMAGE:
01252       return 0;
01253       break;
01254    default:
01255       ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n",
01256             frame->frametype);
01257       return 0;
01258    }
01259 
01260    return res;
01261 }

static int load_module ( void   )  [static]

Load module into PBX, register channel.

Definition at line 1883 of file chan_jingle.c.

References __ourip, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_find_ourip(), ast_log(), ast_module_helper(), AST_MODULE_LOAD_DECLINE, ast_rtp_glue_register, ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ASTOBJ_CONTAINER_INIT, bindaddr, channel_type, free, io, io_context_create(), jingle_cli, JINGLE_CONFIG, jingle_list, jingle_load_config(), jingle_rtp_glue, jingle_tech, LOG_ERROR, LOG_WARNING, and sched_context_create().

01884 {
01885    struct ast_sockaddr ourip_tmp;
01886    struct ast_sockaddr bindaddr_tmp;
01887 
01888    char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
01889    free(jabber_loaded);
01890    if (!jabber_loaded) {
01891       /* Dependency module has a different name, if embedded */
01892       jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
01893       free(jabber_loaded);
01894       if (!jabber_loaded) {
01895          ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n");
01896          return AST_MODULE_LOAD_DECLINE;
01897       }
01898    }
01899 
01900    ASTOBJ_CONTAINER_INIT(&jingle_list);
01901    if (!jingle_load_config()) {
01902       ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
01903       return AST_MODULE_LOAD_DECLINE;
01904    }
01905 
01906    sched = sched_context_create();
01907    if (!sched) {
01908       ast_log(LOG_WARNING, "Unable to create schedule context\n");
01909    }
01910 
01911    io = io_context_create();
01912    if (!io) {
01913       ast_log(LOG_WARNING, "Unable to create I/O context\n");
01914    }
01915 
01916    ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
01917    if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp, AF_INET)) {
01918       ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
01919       return 0;
01920    }
01921    __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp));
01922 
01923    ast_rtp_glue_register(&jingle_rtp_glue);
01924    ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01925    /* Make sure we can register our channel type */
01926    if (ast_channel_register(&jingle_tech)) {
01927       ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
01928       return -1;
01929    }
01930    return 0;
01931 }

static int reload ( void   )  [static]

Reload module.

Definition at line 1934 of file chan_jingle.c.

01935 {
01936    return 0;
01937 }

static int unload_module ( void   )  [static]

Unload the jingle channel from Asterisk.

Definition at line 1940 of file chan_jingle.c.

References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_glue_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, jingle_cli, jingle_list, jingle_member_destroy(), jingle_rtp_glue, jingle_tech, jinglelock, LOG_WARNING, jingle_pvt::next, and jingle_pvt::owner.

01941 {
01942    struct jingle_pvt *privates = NULL;
01943    ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01944    /* First, take us out of the channel loop */
01945    ast_channel_unregister(&jingle_tech);
01946    ast_rtp_glue_unregister(&jingle_rtp_glue);
01947 
01948    if (!ast_mutex_lock(&jinglelock)) {
01949       /* Hangup all interfaces if they have an owner */
01950       ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01951          ASTOBJ_WRLOCK(iterator);
01952          privates = iterator->p;
01953          while(privates) {
01954             if (privates->owner)
01955                ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
01956             privates = privates->next;
01957          }
01958          iterator->p = NULL;
01959          ASTOBJ_UNLOCK(iterator);
01960       });
01961       ast_mutex_unlock(&jinglelock);
01962    } else {
01963       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01964       return -1;
01965    }
01966    ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
01967    ASTOBJ_CONTAINER_DESTROY(&jingle_list);
01968    return 0;
01969 }


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static]

Definition at line 1976 of file chan_jingle.c.

struct in_addr __ourip [static]

Definition at line 215 of file chan_jingle.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1976 of file chan_jingle.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 211 of file chan_jingle.c.

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

Definition at line 165 of file chan_jingle.c.

Referenced by load_module().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 75 of file chan_jingle.c.

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

Definition at line 164 of file chan_jingle.c.

char externip[16] [static]

Definition at line 223 of file chan_jingle.c.

format_t global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 [static]

Definition at line 167 of file chan_jingle.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 83 of file chan_jingle.c.

struct io_context* io [static]

The IO context

Definition at line 214 of file chan_jingle.c.

struct ast_cli_entry jingle_cli[] [static]

Initial value:

 {
   { .handler =  jingle_do_reload , .summary =  "Reload Jingle configuration" ,__VA_ARGS__ },
   { .handler =  jingle_show_channels , .summary =  "Show Jingle channels" ,__VA_ARGS__ },
}

Definition at line 217 of file chan_jingle.c.

Referenced by load_module(), and unload_module().

struct jingle_container jingle_list [static]

Definition at line 225 of file chan_jingle.c.

Referenced by find_jingle(), jingle_show_channels(), load_module(), and unload_module().

struct ast_rtp_glue jingle_rtp_glue [static]

Definition at line 434 of file chan_jingle.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech jingle_tech [static]

PBX interface structure for channel registration.

Definition at line 190 of file chan_jingle.c.

Referenced by jingle_new(), load_module(), and unload_module().

ast_mutex_t jinglelock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Protect the interface list (of jingle_pvt's)

Definition at line 169 of file chan_jingle.c.

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

struct sched_context* sched [static]

The scheduling context

Definition at line 213 of file chan_jingle.c.


Generated on Wed Apr 6 11:29:57 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7