Wed Oct 28 13:32:04 2009

Asterisk developer's documentation


chan_jingle.c File Reference

Jingle Channel Driver. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include <iksemel.h>
#include <pthread.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/stringfields.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astobj.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/jabber.h"
#include "asterisk/jingle.h"

Include dependency graph for chan_jingle.c:

Go to the source code of this file.

Data Structures

struct  jingle
struct  jingle_candidate
struct  jingle_container
struct  jingle_pvt

Defines

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

Enumerations

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void add_codec_to_answer (const struct jingle_pvt *p, 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 int 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, int 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, int codecs, int nat_active)
static char * jingle_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command "jingle show channels".
static int jingle_transmit_invite (struct jingle_pvt *p)
static int jingle_update_stun (struct jingle *client, struct jingle_pvt *p)
static int jingle_write (struct ast_channel *ast, struct ast_frame *frame)
 Send frame to media channel (rtp).
static int load_module (void)
 Load module into PBX, register channel.
static int reload (void)
 Reload module.
static int unload_module (void)
 Unload the jingle channel from Asterisk.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Jingle Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static struct ast_module_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 int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263
static struct ast_jb_conf global_jbconf
static struct io_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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
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

Enumerator:
AJI_CONNECT_HOST 
AJI_CONNECT_PRFLX 
AJI_CONNECT_RELAY 
AJI_CONNECT_SRFLX 

Definition at line 89 of file chan_jingle.c.

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

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 84 of file chan_jingle.c.

00084                      {
00085    AJI_PROTOCOL_UDP,
00086    AJI_PROTOCOL_SSLTCP,
00087 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1949 of file chan_jingle.c.

static void __unreg_module ( void   )  [static]

Definition at line 1949 of file chan_jingle.c.

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

Definition at line 257 of file chan_jingle.c.

References ast_getformatname(), and format.

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

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

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

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

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

Definition at line 297 of file chan_jingle.c.

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

Referenced by jingle_answer().

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

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

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

00878 {
00879    iks *iq, *jingle = NULL;
00880    int res = -1;
00881 
00882    iq = iks_new("iq");
00883    jingle = iks_new("jingle");
00884    
00885    if (iq) {
00886       iks_insert_attrib(iq, "type", "set");
00887       iks_insert_attrib(iq, "from", client->connection->jid->full);
00888       iks_insert_attrib(iq, "to", p->them);
00889       iks_insert_attrib(iq, "id", client->connection->mid);
00890       ast_aji_increment_mid(client->connection->mid);
00891       if (jingle) {
00892          iks_insert_attrib(jingle, "action", action);
00893          iks_insert_attrib(jingle, JINGLE_SID, p->sid);
00894          iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
00895          iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00896 
00897          iks_insert_node(iq, jingle);
00898 
00899          ast_aji_send(client->connection, iq);
00900          res = 0;
00901       }
00902    }
00903    
00904    iks_delete(jingle);
00905    iks_delete(iq);
00906    
00907    return res;
00908 }

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

Definition at line 1083 of file chan_jingle.c.

References AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_send(), ast_calloc, ast_copy_string(), jingle::connection, jingle_candidate::generation, jingle_candidate::ip, aji_client::jid, JINGLE_NODE, JINGLE_SID, jingle_update_stun(), jingle_pvt::laststun, jingle_candidate::network, jingle_candidate::next, jingle_pvt::next, jingle::p, jingle_pvt::parent, jingle_candidate::password, jingle_candidate::port, jingle_candidate::protocol, jingle_pvt::theircandidates, and jingle_candidate::type.

Referenced by jingle_parser().

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

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

Definition at line 735 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(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, jingle::buddy, aji_resource::cap, jingle::connection, jingle_pvt::exten, jingle_pvt::initiator, aji_version::jingle, jinglelock, jingle_pvt::lock, LOG_ERROR, LOG_WARNING, jingle::name, jingle_pvt::next, aji_resource::next, jingle::p, jingle_pvt::parent, jingle::prefs, jingle_pvt::prefs, aji_resource::resource, aji_buddy::resources, jingle_pvt::rtp, jingle_pvt::sid, and jingle_pvt::them.

Referenced by jingle_newcall(), and jingle_request().

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

static int jingle_answer ( struct ast_channel ast  )  [static]

Definition at line 375 of file chan_jingle.c.

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

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

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 1438 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.

01439 {
01440    struct jingle_pvt *p = ast->tech_pvt;
01441 
01442    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01443       ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name);
01444       return -1;
01445    }
01446 
01447    ast_setstate(ast, AST_STATE_RING);
01448    p->jointcapability = p->capability;
01449    if (!p->ringrule) {
01450       ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01451       p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
01452                      IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01453    } else
01454       ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01455 
01456    jingle_transmit_invite(p);
01457    jingle_create_candidates(p->parent, p, p->sid, p->them);
01458 
01459    return 0;
01460 }

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

Definition at line 577 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_strlen_zero(), jingle_candidate::component, jingle::connection, jingle_candidate::foundation, jingle_candidate::generation, inet_aton(), jingle_pvt::initiator, jingle_candidate::ip, aji_client::jid, JINGLE_ICE_UDP_NS, JINGLE_NEGOTIATE, JINGLE_NODE, JINGLE_NS, JINGLE_SID, jingle_pvt::laststun, LOG_ERROR, LOG_NOTICE, LOG_WARNING, aji_client::mid, jingle_candidate::network, jingle_candidate::next, jingle_pvt::next, jingle_pvt::ourcandidates, pass, jingle_candidate::password, jingle_candidate::port, jingle_candidate::priority, jingle_candidate::protocol, jingle_pvt::rtp, jingle_pvt::sid, jingle_candidate::type, and jingle_candidate::ufrag.

Referenced by jingle_call(), and jingle_newcall().

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

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 1680 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, ast_variable::name, jingle::name, ast_variable::next, jingle_candidate::next, jingle::prefs, jingle::user, and ast_variable::value.

Referenced by jingle_load_config().

01683 {
01684    struct aji_client *client;
01685 
01686    if (!member)
01687       ast_log(LOG_WARNING, "Out of memory.\n");
01688 
01689    ast_copy_string(member->name, label, sizeof(member->name));
01690    ast_copy_string(member->user, label, sizeof(member->user));
01691    ast_copy_string(member->context, context, sizeof(member->context));
01692    member->allowguest = allowguest;
01693    member->prefs = prefs;
01694    while (var) {
01695 #if 0
01696       struct jingle_candidate *candidate = NULL;
01697 #endif
01698       if (!strcasecmp(var->name, "username"))
01699          ast_copy_string(member->user, var->value, sizeof(member->user));
01700       else if (!strcasecmp(var->name, "disallow"))
01701          ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
01702       else if (!strcasecmp(var->name, "allow"))
01703          ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
01704       else if (!strcasecmp(var->name, "context"))
01705          ast_copy_string(member->context, var->value, sizeof(member->context));
01706 #if 0
01707       else if (!strcasecmp(var->name, "candidate")) {
01708          candidate = jingle_create_candidate(var->value);
01709          if (candidate) {
01710             candidate->next = member->ourcandidates;
01711             member->ourcandidates = candidate;
01712          }
01713       }
01714 #endif
01715       else if (!strcasecmp(var->name, "connection")) {
01716          if ((client = ast_aji_get_client(var->value))) {
01717             member->connection = client;
01718             iks_filter_add_rule(client->f, jingle_parser, member,
01719                       IKS_RULE_TYPE, IKS_PAK_IQ,
01720                       IKS_RULE_FROM_PARTIAL, member->user,
01721                       IKS_RULE_NS, JINGLE_NS,
01722                       IKS_RULE_DONE);
01723          } else {
01724             ast_log(LOG_ERROR, "connection referenced not found!\n");
01725             return 0;
01726          }
01727       }
01728       var = var->next;
01729    }
01730    if (member->connection && member->user)
01731       member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
01732    else {
01733       ast_log(LOG_ERROR, "No Connection or Username!\n");
01734    }
01735    return 1;
01736 }

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

Definition at line 1298 of file chan_jingle.c.

References ast_aji_increment_mid(), ast_aji_send(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), jingle::connection, ast_channel::dtmff, ast_frame::frametype, jingle_pvt::initiator, aji_client::jid, JINGLE_DTMF_NS, JINGLE_NS, jingle_pvt::lock, LOG_ERROR, aji_client::mid, jingle_pvt::parent, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.

Referenced by jingle_digit_begin(), and jingle_digit_end().

01299 {
01300    struct jingle_pvt *p = ast->tech_pvt;
01301    struct jingle *client = p->parent;
01302    iks *iq, *jingle, *dtmf;
01303    char buffer[2] = {digit, '\0'};
01304    iq = iks_new("iq");
01305    jingle = iks_new("jingle");
01306    dtmf = iks_new("dtmf");
01307    if(!iq || !jingle || !dtmf) {
01308       iks_delete(iq);
01309       iks_delete(jingle);
01310       iks_delete(dtmf);
01311       ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
01312       return -1;
01313    }
01314 
01315    iks_insert_attrib(iq, "type", "set");
01316    iks_insert_attrib(iq, "to", p->them);
01317    iks_insert_attrib(iq, "from", client->connection->jid->full);
01318    iks_insert_attrib(iq, "id", client->connection->mid);
01319    ast_aji_increment_mid(client->connection->mid);
01320    iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01321    iks_insert_attrib(jingle, "action", "session-info");
01322    iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
01323    iks_insert_attrib(jingle, "sid", p->sid);
01324    iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS);
01325    iks_insert_attrib(dtmf, "code", buffer);
01326    iks_insert_node(iq, jingle);
01327    iks_insert_node(jingle, dtmf);
01328 
01329    ast_mutex_lock(&p->lock);
01330    if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
01331       iks_insert_attrib(dtmf, "action", "button-down");
01332    } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
01333       iks_insert_attrib(dtmf, "action", "button-up");
01334    }
01335    ast_aji_send(client->connection, iq);
01336 
01337    iks_delete(iq);
01338    iks_delete(jingle);
01339    iks_delete(dtmf);
01340    ast_mutex_unlock(&p->lock);
01341    return 0;
01342 }

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

Definition at line 1344 of file chan_jingle.c.

References jingle_digit().

01345 {
01346    return jingle_digit(chan, digit, 0);
01347 }

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

Definition at line 1349 of file chan_jingle.c.

References jingle_digit().

01350 {
01351    return jingle_digit(ast, digit, duration);
01352 }

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

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

01592 {
01593    switch (cmd) {
01594    case CLI_INIT:
01595       e->command = "jingle reload";
01596       e->usage =
01597          "Usage: jingle reload\n"
01598          "       Reload jingle channel driver.\n";
01599       return NULL;
01600    case CLI_GENERATE:
01601       return NULL;
01602    }  
01603    
01604    return CLI_SUCCESS;
01605 }

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

Definition at line 1244 of file chan_jingle.c.

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

01245 {
01246    struct jingle_pvt *p = newchan->tech_pvt;
01247    ast_mutex_lock(&p->lock);
01248 
01249    if ((p->owner != oldchan)) {
01250       ast_mutex_unlock(&p->lock);
01251       return -1;
01252    }
01253    if (p->owner == oldchan)
01254       p->owner = newchan;
01255    ast_mutex_unlock(&p->lock);
01256    return 0;
01257 }

static void jingle_free_candidates ( struct jingle_candidate candidate  )  [static]

Definition at line 910 of file chan_jingle.c.

References ast_free, last, and jingle_candidate::next.

Referenced by jingle_free_pvt(), and jingle_load_config().

00911 {
00912    struct jingle_candidate *last;
00913    while (candidate) {
00914       last = candidate;
00915       candidate = candidate->next;
00916       ast_free(last);
00917    }
00918 }

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

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

00921 {
00922    struct jingle_pvt *cur, *prev = NULL;
00923    cur = client->p;
00924    while (cur) {
00925       if (cur == p) {
00926          if (prev)
00927             prev->next = p->next;
00928          else
00929             client->p = p->next;
00930          break;
00931       }
00932       prev = cur;
00933       cur = cur->next;
00934    }
00935    if (p->ringrule)
00936       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00937    if (p->owner)
00938       ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
00939    if (p->rtp)
00940       ast_rtp_instance_destroy(p->rtp);
00941    if (p->vrtp)
00942       ast_rtp_instance_destroy(p->vrtp);
00943    jingle_free_candidates(p->theircandidates);
00944    ast_free(p);
00945 }

static int jingle_get_codec ( struct ast_channel chan  )  [static]

Definition at line 407 of file chan_jingle.c.

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

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

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

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

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

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

Definition at line 492 of file chan_jingle.c.

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

Referenced by jingle_parser().

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

static int jingle_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the jingle proxy channel.

Definition at line 1463 of file chan_jingle.c.

References jingle_pvt::alreadygone, ast_mutex_lock(), ast_mutex_unlock(), jingle_action(), jingle_free_pvt(), JINGLE_TERMINATE, jingle_pvt::lock, jingle_pvt::owner, jingle_pvt::parent, and ast_channel::tech_pvt.

01464 {
01465    struct jingle_pvt *p = ast->tech_pvt;
01466    struct jingle *client;
01467 
01468    ast_mutex_lock(&p->lock);
01469    client = p->parent;
01470    p->owner = NULL;
01471    ast->tech_pvt = NULL;
01472    if (!p->alreadygone)
01473       jingle_action(client, p, JINGLE_TERMINATE);
01474    ast_mutex_unlock(&p->lock);
01475 
01476    jingle_free_pvt(client, p);
01477 
01478    return 0;
01479 }

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

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

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

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

Definition at line 1259 of file chan_jingle.c.

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

01260 {
01261    int res = 0;
01262 
01263    switch (condition) {
01264    case AST_CONTROL_HOLD:
01265       ast_moh_start(ast, data, NULL);
01266       break;
01267    case AST_CONTROL_UNHOLD:
01268       ast_moh_stop(ast);
01269       break;
01270    default:
01271       ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01272       res = -1;
01273    }
01274 
01275    return res;
01276 }

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

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

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

static int jingle_load_config ( void   )  [static]

Definition at line 1738 of file chan_jingle.c.

References jingle::allowguest, ast_aji_get_clients(), ast_calloc, ast_category_browse(), ast_config_load, ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_parse_allow_disallow(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, jingle::capability, clients, CONFIG_STATUS_FILEINVALID, jingle::connection, jingle::context, context, global_jbconf, hp, JINGLE_CONFIG, jingle_create_member(), JINGLE_DTMF_NS, jingle_free_candidates(), jingle_list, jingle_member_destroy(), JINGLE_NS, jingle_parser(), LOG_WARNING, jingle::name, ast_variable::name, ast_variable::next, jingle::parkinglot, jingle::prefs, jingle::user, ast_variable::value, and var.

Referenced by load_module().

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

static void jingle_member_destroy ( struct jingle obj  )  [static]

Definition at line 226 of file chan_jingle.c.

References ast_free.

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

00227 {
00228    ast_free(obj);
00229 }

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

Start new jingle channel.

Definition at line 794 of file chan_jingle.c.

References accountcode, jingle::accountcode, ast_channel::adsicpe, ast_channel::amaflags, jingle::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc, ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), AST_FORMAT_VIDEO_MASK, ast_hangup(), ast_jb_configure(), ast_log(), ast_pbx_start(), ast_random(), ast_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(), jingle::callgroup, ast_channel::callgroup, jingle::callingpres, jingle_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, jingle_pvt::cid_name, jingle_pvt::cid_num, ast_callerid::cid_pres, jingle::context, ast_channel::context, jingle_pvt::exten, ast_channel::exten, global_jbconf, ast_channel::hangupcause, jingle_pvt::jointcapability, language, jingle::language, LOG_WARNING, musicclass, jingle::musicclass, ast_channel::name, ast_channel::nativeformats, jingle_pvt::owner, jingle::pickupgroup, ast_channel::pickupgroup, jingle_pvt::prefs, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, jingle_pvt::rtp, str, ast_channel::tech, ast_channel::tech_pvt, jingle_pvt::them, jingle_pvt::vrtp, and ast_channel::writeformat.

Referenced by jingle_newcall(), and jingle_request().

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

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

Definition at line 948 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, chan, 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().

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

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

Definition at line 1607 of file chan_jingle.c.

References ast_debug, ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, JINGLE_ACCEPT, jingle_add_candidate(), jingle_handle_dtmf(), jingle_hangup_farend(), JINGLE_INFO, JINGLE_INITIATE, jingle_is_answered(), jingle_member_destroy(), JINGLE_NEGOTIATE, jingle_newcall(), JINGLE_NODE, JINGLE_TERMINATE, and LOG_NOTICE.

Referenced by jingle_create_member(), and jingle_load_config().

01608 {
01609    struct jingle *client = ASTOBJ_REF((struct jingle *) data);
01610    ast_log(LOG_NOTICE, "Filter matched\n");
01611 
01612    if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
01613       /* New call */
01614       jingle_newcall(client, pak);
01615    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
01616       ast_debug(3, "About to add candidate!\n");
01617       jingle_add_candidate(client, pak);
01618       ast_debug(3, "Candidate Added!\n");
01619    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
01620       jingle_is_answered(client, pak);
01621    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
01622       jingle_handle_dtmf(client, pak);
01623    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
01624       jingle_hangup_farend(client, pak);
01625    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
01626       jingle_hangup_farend(client, pak);
01627    }
01628    ASTOBJ_UNREF(client, jingle_member_destroy);
01629    return IKS_FILTER_EAT;
01630 }

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

Definition at line 1189 of file chan_jingle.c.

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

01190 {
01191    struct ast_frame *fr;
01192    struct jingle_pvt *p = ast->tech_pvt;
01193 
01194    ast_mutex_lock(&p->lock);
01195    fr = jingle_rtp_read(ast, p);
01196    ast_mutex_unlock(&p->lock);
01197    return fr;
01198 }

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

Part of PBX interface.

Definition at line 1482 of file chan_jingle.c.

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

01483 {
01484    struct jingle_pvt *p = NULL;
01485    struct jingle *client = NULL;
01486    char *sender = NULL, *to = NULL, *s = NULL;
01487    struct ast_channel *chan = NULL;
01488 
01489    if (data) {
01490       s = ast_strdupa(data);
01491       if (s) {
01492          sender = strsep(&s, "/");
01493          if (sender && (sender[0] != '\0'))
01494             to = strsep(&s, "/");
01495          if (!to) {
01496             ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data);
01497             return NULL;
01498          }
01499       }
01500    }
01501 
01502    client = find_jingle(to, sender);
01503    if (!client) {
01504       ast_log(LOG_WARNING, "Could not find recipient.\n");
01505       return NULL;
01506    }
01507    if (!strcasecmp(client->name, "guest")){
01508       /* the guest account is not tied to any configured XMPP client,
01509          let's set it now */
01510       client->connection = ast_aji_get_client(sender);
01511       if (!client->connection) {
01512          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01513          return NULL;
01514       }
01515    }
01516        
01517    ASTOBJ_WRLOCK(client);
01518    p = jingle_alloc(client, to, NULL);
01519    if (p)
01520       chan = jingle_new(client, p, AST_STATE_DOWN, to, requestor ? requestor->linkedid : NULL);
01521    ASTOBJ_UNLOCK(client);
01522 
01523    return chan;
01524 }

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

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

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

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

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

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

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

Definition at line 1161 of file chan_jingle.c.

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

Referenced by jingle_read().

01162 {
01163    struct ast_frame *f;
01164 
01165    if (!p->rtp)
01166       return &ast_null_frame;
01167    f = ast_rtp_instance_read(p->rtp, 0);
01168    jingle_update_stun(p->parent, p);
01169    if (p->owner) {
01170       /* We already hold the channel lock */
01171       if (f->frametype == AST_FRAME_VOICE) {
01172          if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
01173             ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
01174             p->owner->nativeformats =
01175                (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
01176             ast_set_read_format(p->owner, p->owner->readformat);
01177             ast_set_write_format(p->owner, p->owner->writeformat);
01178          }
01179 /*       if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
01180             f = ast_dsp_process(p->owner, p->vad, f);
01181             if (f && (f->frametype == AST_FRAME_DTMF))
01182                ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass);
01183               } */
01184       }
01185    }
01186    return f;
01187 }

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

Definition at line 1354 of file chan_jingle.c.

References ast_log(), and LOG_NOTICE.

01355 {
01356    ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
01357 
01358    return -1;
01359 }

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

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

01279 {
01280    int res = 0;
01281    struct aji_client *client = NULL;
01282    struct jingle_pvt *p = chan->tech_pvt;
01283 
01284 
01285    if (!p->parent) {
01286       ast_log(LOG_ERROR, "Parent channel not found\n");
01287       return -1;
01288    }
01289    if (!p->parent->connection) {
01290       ast_log(LOG_ERROR, "XMPP client not found\n");
01291       return -1;
01292    }
01293    client = p->parent->connection;
01294    res = ast_aji_send_chat(client, p->them, text);
01295    return res;
01296 }

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

Definition at line 413 of file chan_jingle.c.

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

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

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

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

01528 {
01529 #define FORMAT  "%-30.30s  %-30.30s  %-15.15s  %-5.5s %-5.5s \n"
01530    struct jingle_pvt *p;
01531    struct ast_channel *chan;
01532    int numchans = 0;
01533    char them[AJI_MAX_JIDLEN];
01534    char *jid = NULL;
01535    char *resource = NULL;
01536 
01537    switch (cmd) {
01538    case CLI_INIT:
01539       e->command = "jingle show channels";
01540       e->usage =
01541          "Usage: jingle show channels\n"
01542          "       Shows current state of the Jingle channels.\n";
01543       return NULL;
01544    case CLI_GENERATE:
01545       return NULL;
01546    }
01547 
01548    if (a->argc != 3)
01549       return CLI_SHOWUSAGE;
01550 
01551    ast_mutex_lock(&jinglelock);
01552    ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
01553    ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01554       ASTOBJ_WRLOCK(iterator);
01555       p = iterator->p;
01556       while(p) {
01557          chan = p->owner;
01558          ast_copy_string(them, p->them, sizeof(them));
01559          jid = them;
01560          resource = strchr(them, '/');
01561          if (!resource)
01562             resource = "None";
01563          else {
01564             *resource = '\0';
01565             resource ++;
01566          }
01567          if (chan)
01568             ast_cli(a->fd, FORMAT, 
01569                chan->name,
01570                jid,
01571                resource,
01572                ast_getformatname(chan->readformat),
01573                ast_getformatname(chan->writeformat)               
01574                );
01575          else 
01576             ast_log(LOG_WARNING, "No available channel\n");
01577          numchans ++;
01578          p = p->next;
01579       }
01580       ASTOBJ_UNLOCK(iterator);
01581    });
01582 
01583    ast_mutex_unlock(&jinglelock);
01584 
01585    ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : "");
01586    return CLI_SUCCESS;
01587 #undef FORMAT
01588 }

static int jingle_transmit_invite ( struct jingle_pvt p  )  [static]

Definition at line 1360 of file chan_jingle.c.

References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle_pvt::audio_content_name, jingle::connection, aji_client::jid, JINGLE_AUDIO_RTP_NS, JINGLE_ICE_UDP_NS, JINGLE_INITIATE, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, jingle_pvt::parent, jingle_pvt::sid, and jingle_pvt::them.

Referenced by jingle_call().

01361 {
01362    struct jingle *aux = NULL;
01363    struct aji_client *client = NULL;
01364    iks *iq, *jingle, *content, *description, *transport;
01365    iks *payload_eg711u, *payload_pcmu;
01366 
01367    aux = p->parent;
01368    client = aux->connection;
01369    iq = iks_new("iq");
01370    jingle = iks_new(JINGLE_NODE);
01371    content = iks_new("content");
01372    description = iks_new("description");
01373    transport = iks_new("transport");
01374    payload_pcmu = iks_new("payload-type");
01375    payload_eg711u = iks_new("payload-type");
01376 
01377    ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name));
01378 
01379    iks_insert_attrib(iq, "type", "set");
01380    iks_insert_attrib(iq, "to", p->them);
01381    iks_insert_attrib(iq, "from", client->jid->full);
01382    iks_insert_attrib(iq, "id", client->mid);
01383    ast_aji_increment_mid(client->mid);
01384    iks_insert_attrib(jingle, "action", JINGLE_INITIATE);
01385    iks_insert_attrib(jingle, JINGLE_SID, p->sid);
01386    iks_insert_attrib(jingle, "initiator", client->jid->full);
01387    iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01388 
01389    /* For now, we only send one audio based content */
01390    iks_insert_attrib(content, "creator", "initiator");
01391    iks_insert_attrib(content, "name", p->audio_content_name);
01392    iks_insert_attrib(content, "profile", "RTP/AVP");
01393    iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS);
01394    iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
01395    iks_insert_attrib(payload_pcmu, "id", "0");
01396    iks_insert_attrib(payload_pcmu, "name", "PCMU");
01397    iks_insert_attrib(payload_eg711u, "id", "100");
01398    iks_insert_attrib(payload_eg711u, "name", "EG711U");
01399    iks_insert_node(description, payload_pcmu);
01400    iks_insert_node(description, payload_eg711u);
01401    iks_insert_node(content, description);
01402    iks_insert_node(content, transport);
01403    iks_insert_node(jingle, content);
01404    iks_insert_node(iq, jingle);
01405 
01406    ast_aji_send(client, iq);
01407 
01408    iks_delete(iq);
01409    iks_delete(jingle);
01410    iks_delete(content);
01411    iks_delete(description);
01412    iks_delete(transport);
01413    iks_delete(payload_eg711u);
01414    iks_delete(payload_pcmu);
01415    return 0;
01416 }

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

Definition at line 1057 of file chan_jingle.c.

References ast_gethostbyname(), ast_rtp_instance_stun_request(), hp, jingle_candidate::ip, jingle_pvt::laststun, jingle_candidate::next, jingle_pvt::ourcandidates, jingle_candidate::port, jingle_pvt::rtp, jingle_pvt::theircandidates, and jingle_candidate::ufrag.

Referenced by jingle_add_candidate(), and jingle_rtp_read().

01058 {
01059    struct jingle_candidate *tmp;
01060    struct hostent *hp;
01061    struct ast_hostent ahp;
01062    struct sockaddr_in sin;
01063 
01064    if (time(NULL) == p->laststun)
01065       return 0;
01066 
01067    tmp = p->theircandidates;
01068    p->laststun = time(NULL);
01069    while (tmp) {
01070       char username[256];
01071       hp = ast_gethostbyname(tmp->ip, &ahp);
01072       sin.sin_family = AF_INET;
01073       memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01074       sin.sin_port = htons(tmp->port);
01075       snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
01076 
01077       ast_rtp_instance_stun_request(p->rtp, &sin, username);
01078       tmp = tmp->next;
01079    }
01080    return 1;
01081 }

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

Send frame to media channel (rtp).

Definition at line 1201 of file chan_jingle.c.

References AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_instance_write(), ast_frame::frametype, jingle_pvt::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, jingle_pvt::rtp, ast_frame::subclass, ast_channel::tech_pvt, jingle_pvt::vrtp, and ast_channel::writeformat.

01202 {
01203    struct jingle_pvt *p = ast->tech_pvt;
01204    int res = 0;
01205 
01206    switch (frame->frametype) {
01207    case AST_FRAME_VOICE:
01208       if (!(frame->subclass & ast->nativeformats)) {
01209          ast_log(LOG_WARNING,
01210                "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01211                frame->subclass, ast->nativeformats, ast->readformat,
01212                ast->writeformat);
01213          return 0;
01214       }
01215       if (p) {
01216          ast_mutex_lock(&p->lock);
01217          if (p->rtp) {
01218             res = ast_rtp_instance_write(p->rtp, frame);
01219          }
01220          ast_mutex_unlock(&p->lock);
01221       }
01222       break;
01223    case AST_FRAME_VIDEO:
01224       if (p) {
01225          ast_mutex_lock(&p->lock);
01226          if (p->vrtp) {
01227             res = ast_rtp_instance_write(p->vrtp, frame);
01228          }
01229          ast_mutex_unlock(&p->lock);
01230       }
01231       break;
01232    case AST_FRAME_IMAGE:
01233       return 0;
01234       break;
01235    default:
01236       ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n",
01237             frame->frametype);
01238       return 0;
01239    }
01240 
01241    return res;
01242 }

static int load_module ( void   )  [static]

Load module into PBX, register channel.

Definition at line 1864 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, ASTOBJ_CONTAINER_INIT, free, io_context_create(), JINGLE_CONFIG, jingle_list, jingle_load_config(), LOG_ERROR, LOG_WARNING, and sched_context_create().

01865 {
01866    char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
01867    free(jabber_loaded);
01868    if (!jabber_loaded) {
01869       /* Dependency module has a different name, if embedded */
01870       jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
01871       free(jabber_loaded);
01872       if (!jabber_loaded) {
01873          ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n");
01874          return AST_MODULE_LOAD_DECLINE;
01875       }
01876    }
01877 
01878    ASTOBJ_CONTAINER_INIT(&jingle_list);
01879    if (!jingle_load_config()) {
01880       ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
01881       return AST_MODULE_LOAD_DECLINE;
01882    }
01883 
01884    sched = sched_context_create();
01885    if (!sched) 
01886       ast_log(LOG_WARNING, "Unable to create schedule context\n");
01887 
01888    io = io_context_create();
01889    if (!io) 
01890       ast_log(LOG_WARNING, "Unable to create I/O context\n");
01891 
01892    if (ast_find_ourip(&__ourip, bindaddr)) {
01893       ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
01894       return 0;
01895    }
01896 
01897    ast_rtp_glue_register(&jingle_rtp_glue);
01898    ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01899    /* Make sure we can register our channel type */
01900    if (ast_channel_register(&jingle_tech)) {
01901       ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
01902       return -1;
01903    }
01904    return 0;
01905 }

static int reload ( void   )  [static]

Reload module.

Definition at line 1908 of file chan_jingle.c.

01909 {
01910    return 0;
01911 }

static int unload_module ( void   )  [static]

Unload the jingle channel from Asterisk.

Definition at line 1914 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_list, jingle_member_destroy(), jinglelock, LOG_WARNING, jingle_pvt::next, and jingle_pvt::owner.

01915 {
01916    struct jingle_pvt *privates = NULL;
01917    ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01918    /* First, take us out of the channel loop */
01919    ast_channel_unregister(&jingle_tech);
01920    ast_rtp_glue_unregister(&jingle_rtp_glue);
01921 
01922    if (!ast_mutex_lock(&jinglelock)) {
01923       /* Hangup all interfaces if they have an owner */
01924       ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01925          ASTOBJ_WRLOCK(iterator);
01926          privates = iterator->p;
01927          while(privates) {
01928             if (privates->owner)
01929                ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
01930             privates = privates->next;
01931          }
01932          iterator->p = NULL;
01933          ASTOBJ_UNLOCK(iterator);
01934       });
01935       ast_mutex_unlock(&jinglelock);
01936    } else {
01937       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01938       return -1;
01939    }
01940    ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
01941    ASTOBJ_CONTAINER_DESTROY(&jingle_list);
01942    return 0;
01943 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Jingle Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1949 of file chan_jingle.c.

struct in_addr __ourip [static]

Definition at line 214 of file chan_jingle.c.

Definition at line 1949 of file chan_jingle.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 210 of file chan_jingle.c.

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

Definition at line 164 of file chan_jingle.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 75 of file chan_jingle.c.

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

Definition at line 163 of file chan_jingle.c.

char externip[16] [static]

Definition at line 222 of file chan_jingle.c.

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

Definition at line 166 of file chan_jingle.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 82 of file chan_jingle.c.

struct io_context* io [static]

The IO context

Definition at line 213 of file chan_jingle.c.

struct ast_cli_entry jingle_cli[] [static]

Initial value:

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

Definition at line 216 of file chan_jingle.c.

struct jingle_container jingle_list [static]

struct ast_rtp_glue jingle_rtp_glue [static]

Definition at line 433 of file chan_jingle.c.

struct ast_channel_tech jingle_tech [static]

PBX interface structure for channel registration.

Definition at line 189 of file chan_jingle.c.

ast_mutex_t jinglelock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Protect the interface list (of jingle_pvt's)

Definition at line 168 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 212 of file chan_jingle.c.


Generated on Wed Oct 28 13:32:05 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6