Mon Oct 8 12:39:14 2012

Asterisk developer's documentation


chan_jingle.c File Reference

Jingle Channel Driver. More...

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

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 = "ac1f6a56484a8820659555499174e588" , .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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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 73 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 91 of file chan_jingle.c.

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

enum jingle_protocol

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 86 of file chan_jingle.c.

00086                      {
00087    AJI_PROTOCOL_UDP,
00088    AJI_PROTOCOL_SSLTCP,
00089 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1990 of file chan_jingle.c.

static void __unreg_module ( void   )  [static]

Definition at line 1990 of file chan_jingle.c.

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

Definition at line 259 of file chan_jingle.c.

References ast_getformatname(), and format.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 739 of file chan_jingle.c.

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

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

static int jingle_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

Definition at line 579 of file chan_jingle.c.

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

00580 {
00581    struct jingle_candidate *tmp;
00582    struct aji_client *c = client->connection;
00583    struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
00584    struct sockaddr_in sin = { 0, };
00585    struct ast_sockaddr sin_tmp;
00586    struct ast_sockaddr us_tmp;
00587    struct ast_sockaddr bindaddr_tmp;
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 
00669    for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
00670       snprintf(component, sizeof(component), "%u", tmp->component);
00671       snprintf(foundation, sizeof(foundation), "%u", tmp->foundation);
00672       snprintf(generation, sizeof(generation), "%u", tmp->generation);
00673       snprintf(network, sizeof(network), "%u", tmp->network);
00674       snprintf(port, sizeof(port), "%u", tmp->port);
00675       snprintf(priority, sizeof(priority), "%u", tmp->priority);
00676 
00677       iks_insert_attrib(iq, "from", c->jid->full);
00678       iks_insert_attrib(iq, "to", from);
00679       iks_insert_attrib(iq, "type", "set");
00680       iks_insert_attrib(iq, "id", c->mid);
00681       ast_aji_increment_mid(c->mid);
00682       iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE);
00683       iks_insert_attrib(jingle, JINGLE_SID, sid);
00684       iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from);
00685       iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00686       iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder");
00687       iks_insert_attrib(content, "name", "asterisk-audio-content");
00688       iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
00689       iks_insert_attrib(candidate, "component", component);
00690       iks_insert_attrib(candidate, "foundation", foundation);
00691       iks_insert_attrib(candidate, "generation", generation);
00692       iks_insert_attrib(candidate, "ip", tmp->ip);
00693       iks_insert_attrib(candidate, "network", network);
00694       iks_insert_attrib(candidate, "port", port);
00695       iks_insert_attrib(candidate, "priority", priority);
00696       switch (tmp->protocol) {
00697       case AJI_PROTOCOL_UDP:
00698          iks_insert_attrib(candidate, "protocol", "udp");
00699          break;
00700       case AJI_PROTOCOL_SSLTCP:
00701          iks_insert_attrib(candidate, "protocol", "ssltcp");
00702          break;
00703       }
00704       iks_insert_attrib(candidate, "pwd", tmp->password);
00705       switch (tmp->type) {
00706       case AJI_CONNECT_HOST:
00707          iks_insert_attrib(candidate, "type", "host");
00708          break;
00709       case AJI_CONNECT_PRFLX:
00710          iks_insert_attrib(candidate, "type", "prflx");
00711          break;
00712       case AJI_CONNECT_RELAY:
00713          iks_insert_attrib(candidate, "type", "relay");
00714          break;
00715       case AJI_CONNECT_SRFLX:
00716          iks_insert_attrib(candidate, "type", "srflx");
00717          break;
00718       }
00719       iks_insert_attrib(candidate, "ufrag", tmp->ufrag);
00720 
00721       ast_aji_send(c, iq);
00722    }
00723    p->laststun = 0;
00724 
00725 safeout:
00726    if (ours1)
00727       ast_free(ours1);
00728    if (ours2)
00729       ast_free(ours2);
00730    iks_delete(iq);
00731    iks_delete(jingle);
00732    iks_delete(content);
00733    iks_delete(transport);
00734    iks_delete(candidate);
00735 
00736    return 1;
00737 }

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

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

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

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

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

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

Definition at line 1370 of file chan_jingle.c.

References jingle_digit().

01371 {
01372    return jingle_digit(chan, digit, 0);
01373 }

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

Definition at line 1375 of file chan_jingle.c.

References jingle_digit().

01376 {
01377    return jingle_digit(ast, digit, duration);
01378 }

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

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

01621 {
01622    switch (cmd) {
01623    case CLI_INIT:
01624       e->command = "jingle reload";
01625       e->usage =
01626          "Usage: jingle reload\n"
01627          "       Reload jingle channel driver.\n";
01628       return NULL;
01629    case CLI_GENERATE:
01630       return NULL;
01631    }  
01632    
01633    return CLI_SUCCESS;
01634 }

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

Definition at line 1270 of file chan_jingle.c.

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

01271 {
01272    struct jingle_pvt *p = newchan->tech_pvt;
01273    ast_mutex_lock(&p->lock);
01274 
01275    if ((p->owner != oldchan)) {
01276       ast_mutex_unlock(&p->lock);
01277       return -1;
01278    }
01279    if (p->owner == oldchan)
01280       p->owner = newchan;
01281    ast_mutex_unlock(&p->lock);
01282    return 0;
01283 }

static void jingle_free_candidates ( struct jingle_candidate candidate  )  [static]

Definition at line 928 of file chan_jingle.c.

References ast_free, last, and jingle_candidate::next.

Referenced by jingle_free_pvt().

00929 {
00930    struct jingle_candidate *last;
00931    while (candidate) {
00932       last = candidate;
00933       candidate = candidate->next;
00934       ast_free(last);
00935    }
00936 }

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

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

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

static format_t jingle_get_codec ( struct ast_channel chan  )  [static]

Definition at line 409 of file chan_jingle.c.

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

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

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

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

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

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

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

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

static int jingle_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the jingle proxy channel.

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

01490 {
01491    struct jingle_pvt *p = ast->tech_pvt;
01492    struct jingle *client;
01493 
01494    ast_mutex_lock(&p->lock);
01495    client = p->parent;
01496    p->owner = NULL;
01497    ast->tech_pvt = NULL;
01498    if (!p->alreadygone)
01499       jingle_action(client, p, JINGLE_TERMINATE);
01500    ast_mutex_unlock(&p->lock);
01501 
01502    jingle_free_pvt(client, p);
01503 
01504    return 0;
01505 }

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

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

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

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

Definition at line 1285 of file chan_jingle.c.

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

01286 {
01287    int res = 0;
01288 
01289    switch (condition) {
01290    case AST_CONTROL_HOLD:
01291       ast_moh_start(ast, data, NULL);
01292       break;
01293    case AST_CONTROL_UNHOLD:
01294       ast_moh_stop(ast);
01295       break;
01296    default:
01297       ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01298       res = -1;
01299    }
01300 
01301    return res;
01302 }

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

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

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

static int jingle_load_config ( void   )  [static]

Definition at line 1767 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_STATUS_FILEINVALID, context, default_jbconf, externip, global_capability, global_jbconf, hp, JINGLE_CONFIG, LOG_WARNING, prefs, and var.

Referenced by load_module().

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

static void jingle_member_destroy ( struct jingle obj  )  [static]

Definition at line 228 of file chan_jingle.c.

References ast_free.

Referenced by jingle_parser(), and unload_module().

00229 {
00230    ast_free(obj);
00231 }

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 807 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().

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

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

Definition at line 966 of file chan_jingle.c.

References ast_aji_client_destroy(), ast_aji_get_client(), ast_copy_string(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_rtp_codecs_payloads_set_m_type(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, ASTOBJ_UNREF, jingle_pvt::audio_content_name, jingle::connection, aji_client::jid, jingle_alloc(), JINGLE_AUDIO_RTP_NS, jingle_create_candidates(), jingle_free_pvt(), jingle_new(), JINGLE_NODE, jingle_response(), JINGLE_SID, JINGLE_VIDEO_RTP_NS, jingle_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, jingle::name, jingle_pvt::next, jingle::p, jingle_pvt::rtp, jingle_pvt::sid, jingle_pvt::them, and jingle_pvt::video_content_name.

Referenced by jingle_parser().

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

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

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

01637 {
01638    struct jingle *client = ASTOBJ_REF((struct jingle *) data);
01639    ast_log(LOG_NOTICE, "Filter matched\n");
01640 
01641    if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
01642       /* New call */
01643       jingle_newcall(client, pak);
01644    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
01645       ast_debug(3, "About to add candidate!\n");
01646       jingle_add_candidate(client, pak);
01647       ast_debug(3, "Candidate Added!\n");
01648    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
01649       jingle_is_answered(client, pak);
01650    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
01651       jingle_handle_dtmf(client, pak);
01652    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
01653       jingle_hangup_farend(client, pak);
01654    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
01655       jingle_hangup_farend(client, pak);
01656    }
01657    ASTOBJ_UNREF(client, jingle_member_destroy);
01658    return IKS_FILTER_EAT;
01659 }

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

Definition at line 1212 of file chan_jingle.c.

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

01213 {
01214    struct ast_frame *fr;
01215    struct jingle_pvt *p = ast->tech_pvt;
01216 
01217    ast_mutex_lock(&p->lock);
01218    fr = jingle_rtp_read(ast, p);
01219    ast_mutex_unlock(&p->lock);
01220    return fr;
01221 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 1380 of file chan_jingle.c.

References ast_log(), and LOG_NOTICE.

01381 {
01382    ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
01383 
01384    return -1;
01385 }

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

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

01305 {
01306    int res = 0;
01307    struct aji_client *client = NULL;
01308    struct jingle_pvt *p = chan->tech_pvt;
01309 
01310 
01311    if (!p->parent) {
01312       ast_log(LOG_ERROR, "Parent channel not found\n");
01313       return -1;
01314    }
01315    if (!p->parent->connection) {
01316       ast_log(LOG_ERROR, "XMPP client not found\n");
01317       return -1;
01318    }
01319    client = p->parent->connection;
01320    res = ast_aji_send_chat(client, p->them, text);
01321    return res;
01322 }

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

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

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

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

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

static int jingle_transmit_invite ( struct jingle_pvt p  )  [static]

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

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

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

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

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

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

Send frame to media channel (rtp).

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

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

static int load_module ( void   )  [static]

Load module into PBX, register channel.

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

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

static int reload ( void   )  [static]

Reload module.

Definition at line 1948 of file chan_jingle.c.

01949 {
01950    return 0;
01951 }

static int unload_module ( void   )  [static]

Unload the jingle channel from Asterisk.

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

01955 {
01956    struct jingle_pvt *privates = NULL;
01957    ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01958    /* First, take us out of the channel loop */
01959    ast_channel_unregister(&jingle_tech);
01960    ast_rtp_glue_unregister(&jingle_rtp_glue);
01961 
01962    if (!ast_mutex_lock(&jinglelock)) {
01963       /* Hangup all interfaces if they have an owner */
01964       ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01965          ASTOBJ_WRLOCK(iterator);
01966          privates = iterator->p;
01967          while(privates) {
01968             if (privates->owner)
01969                ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
01970             privates = privates->next;
01971          }
01972          iterator->p = NULL;
01973          ASTOBJ_UNLOCK(iterator);
01974       });
01975       ast_mutex_unlock(&jinglelock);
01976    } else {
01977       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01978       return -1;
01979    }
01980    ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
01981    ASTOBJ_CONTAINER_DESTROY(&jingle_list);
01982    return 0;
01983 }


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

Definition at line 1990 of file chan_jingle.c.

struct in_addr __ourip [static]

Definition at line 216 of file chan_jingle.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1990 of file chan_jingle.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 212 of file chan_jingle.c.

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

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

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

Definition at line 165 of file chan_jingle.c.

char externip[16] [static]

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

struct ast_jb_conf global_jbconf [static]

Definition at line 84 of file chan_jingle.c.

struct io_context* io [static]

The IO context

Definition at line 215 of file chan_jingle.c.

struct ast_cli_entry jingle_cli[] [static]

Initial value:

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

Definition at line 218 of file chan_jingle.c.

Referenced by load_module(), and unload_module().

struct jingle_container jingle_list [static]

Definition at line 226 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 435 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 191 of file chan_jingle.c.

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

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

Protect the interface list (of jingle_pvt's)

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


Generated on Mon Oct 8 12:39:14 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7