Wed Aug 18 22:34:10 2010

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.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 int jingle_get_codec (struct ast_channel *chan)
static enum ast_rtp_get_result jingle_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static int jingle_handle_dtmf (struct jingle *client, ikspak *pak)
static int jingle_hangup (struct ast_channel *ast)
 Hangup a call through the jingle proxy channel.
static int jingle_hangup_farend (struct jingle *client, ikspak *pak)
static int jingle_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
static int jingle_is_answered (struct jingle *client, ikspak *pak)
static int jingle_load_config (void)
static void jingle_member_destroy (struct jingle *obj)
static struct ast_channeljingle_new (struct jingle *client, struct jingle_pvt *i, int state, const char *title)
 Start new jingle channel.
static int jingle_newcall (struct jingle *client, ikspak *pak)
static int jingle_parser (void *data, ikspak *pak)
static struct ast_framejingle_read (struct ast_channel *ast)
static struct ast_channeljingle_request (const char *request_type, int format, void *data, int *cause)
 Part of PBX interface.
static int jingle_response (struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2)
static int jingle_ringing_ack (void *data, ikspak *pak)
static struct ast_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_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *tpeer, int codecs, int nat_active)
static char * jingle_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command "jingle show channels".
static int jingle_transmit_invite (struct jingle_pvt *p)
static int jingle_update_stun (struct jingle *client, struct jingle_pvt *p)
static int jingle_write (struct ast_channel *ast, struct ast_frame *frame)
 Send frame to media channel (rtp).
static int load_module (void)
 Load module into PBX, register channel.
static int reload (void)
 Reload module.
static int unload_module (void)
 Unload the jingle channel from Asterisk.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Jingle Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr = { 0, }
static const char channel_type [] = "Jingle"
static struct ast_jb_conf default_jbconf
static const char desc [] = "Jingle Channel"
static char externip [16]
static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263
static struct ast_jb_conf global_jbconf
static struct io_contextio
static struct ast_cli_entry jingle_cli []
static struct jingle_container jingle_list
static struct ast_rtp_protocol jingle_rtp
 RTP driver interface.
static struct ast_channel_tech jingle_tech
 PBX interface structure for channel registration.
static ast_mutex_t jinglelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct sched_contextsched


Detailed Description

Jingle Channel Driver.

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

Definition in file chan_jingle.c.


Define Documentation

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

#define JINGLE_CONFIG   "jingle.conf"

Definition at line 72 of file chan_jingle.c.

Referenced by jingle_load_config(), and load_module().


Enumeration Type Documentation

enum jingle_connect_type

Enumerator:
AJI_CONNECT_HOST 
AJI_CONNECT_PRFLX 
AJI_CONNECT_RELAY 
AJI_CONNECT_SRFLX 

Definition at line 90 of file chan_jingle.c.

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

enum jingle_protocol

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 85 of file chan_jingle.c.

00085                      {
00086    AJI_PROTOCOL_UDP,
00087    AJI_PROTOCOL_SSLTCP,
00088 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1934 of file chan_jingle.c.

static void __unreg_module ( void   )  [static]

Definition at line 1934 of file chan_jingle.c.

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

Definition at line 270 of file chan_jingle.c.

References ast_getformatname(), ast_rtp_lookup_code(), format, jingle::p, and jingle_pvt::rtp.

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

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

Definition at line 244 of file chan_jingle.c.

References ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and jingle_list.

Referenced by jingle_request().

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

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

Definition at line 311 of file chan_jingle.c.

References add_codec_to_answer(), ast_aji_increment_mid(), ast_aji_send(), ast_codec_pref_index(), jingle::capability, jingle::connection, 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().

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

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

Definition at line 883 of file chan_jingle.c.

References ast_aji_increment_mid(), ast_aji_send(), jingle::connection, jingle_pvt::initiator, aji_client::jid, JINGLE_NS, JINGLE_SID, aji_client::mid, jingle_pvt::sid, and jingle_pvt::them.

Referenced by jingle_hangup().

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

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

Definition at line 1089 of file chan_jingle.c.

References AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_send(), ast_calloc, ast_copy_string(), jingle::connection, 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().

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

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

Definition at line 741 of file chan_jingle.c.

References ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_new_with_bindaddr(), ASTOBJ_CONTAINER_FIND, bindaddr, aji_client::buddies, jingle::buddy, aji_resource::cap, jingle::connection, io, 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().

00742 {
00743    struct jingle_pvt *tmp = NULL;
00744    struct aji_resource *resources = NULL;
00745    struct aji_buddy *buddy;
00746    char idroster[200];
00747 
00748    ast_debug(1, "The client is %s for alloc\n", client->name);
00749    if (!sid && !strchr(from, '/')) {   /* I started call! */
00750       if (!strcasecmp(client->name, "guest")) {
00751          buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from);
00752          if (buddy)
00753             resources = buddy->resources;
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          return NULL;
00767       }
00768    }
00769    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00770       return NULL;
00771    }
00772 
00773    memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
00774 
00775    if (sid) {
00776       ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00777       ast_copy_string(tmp->them, from, sizeof(tmp->them));
00778    } else {
00779       snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00780       ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00781       tmp->initiator = 1;
00782    }
00783    tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
00784    tmp->parent = client;
00785    if (!tmp->rtp) {
00786       ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00787       ast_free(tmp);
00788       return NULL;
00789    }
00790    ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
00791    ast_mutex_init(&tmp->lock);
00792    ast_mutex_lock(&jinglelock);
00793    tmp->next = client->p;
00794    client->p = tmp;
00795    ast_mutex_unlock(&jinglelock);
00796    return tmp;
00797 }

static int jingle_answer ( struct ast_channel ast  )  [static]

Definition at line 389 of file chan_jingle.c.

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

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

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

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

Definition at line 1424 of file chan_jingle.c.

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

01425 {
01426    struct jingle_pvt *p = ast->tech_pvt;
01427 
01428    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01429       ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name);
01430       return -1;
01431    }
01432 
01433    ast_setstate(ast, AST_STATE_RING);
01434    p->jointcapability = p->capability;
01435    if (!p->ringrule) {
01436       ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01437       p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
01438                      IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01439    } else
01440       ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01441 
01442    jingle_transmit_invite(p);
01443    jingle_create_candidates(p->parent, p, p->sid, p->them);
01444 
01445    return 0;
01446 }

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

Definition at line 583 of file chan_jingle.c.

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

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

static int jingle_create_member ( char *  label,
struct ast_variable var,
int  allowguest,
struct ast_codec_pref  prefs,
char *  context,
struct jingle member 
) [static]

Definition at line 1666 of file chan_jingle.c.

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

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

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

Definition at line 1284 of file chan_jingle.c.

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

Referenced by jingle_digit_begin(), and jingle_digit_end().

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

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

Definition at line 1330 of file chan_jingle.c.

References chan, and jingle_digit().

01331 {
01332    return jingle_digit(chan, digit, 0);
01333 }

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

Definition at line 1335 of file chan_jingle.c.

References jingle_digit().

01336 {
01337    return jingle_digit(ast, digit, duration);
01338 }

static char * jingle_do_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command "jingle reload".

Definition at line 1577 of file chan_jingle.c.

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

01578 {
01579    switch (cmd) {
01580    case CLI_INIT:
01581       e->command = "jingle reload";
01582       e->usage =
01583          "Usage: jingle reload\n"
01584          "       Reload jingle channel driver.\n";
01585       return NULL;
01586    case CLI_GENERATE:
01587       return NULL;
01588    }  
01589    
01590    return CLI_SUCCESS;
01591 }

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

Definition at line 1250 of file chan_jingle.c.

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

01251 {
01252    struct jingle_pvt *p = newchan->tech_pvt;
01253    ast_mutex_lock(&p->lock);
01254 
01255    if ((p->owner != oldchan)) {
01256       ast_mutex_unlock(&p->lock);
01257       return -1;
01258    }
01259    if (p->owner == oldchan)
01260       p->owner = newchan;
01261    ast_mutex_unlock(&p->lock);
01262    return 0;
01263 }

static void jingle_free_candidates ( struct jingle_candidate candidate  )  [static]

Definition at line 916 of file chan_jingle.c.

References ast_free, last, and jingle_candidate::next.

Referenced by jingle_free_pvt().

00917 {
00918    struct jingle_candidate *last;
00919    while (candidate) {
00920       last = candidate;
00921       candidate = candidate->next;
00922       ast_free(last);
00923    }
00924 }

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

Definition at line 926 of file chan_jingle.c.

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

Referenced by jingle_hangup(), and jingle_newcall().

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

static int jingle_get_codec ( struct ast_channel chan  )  [static]

Definition at line 420 of file chan_jingle.c.

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

00421 {
00422    struct jingle_pvt *p = chan->tech_pvt;
00423    return p->peercapability;
00424 }

static enum ast_rtp_get_result jingle_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp **  rtp 
) [static]

Definition at line 402 of file chan_jingle.c.

References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_PARTIAL, chan, jingle_pvt::lock, jingle_pvt::rtp, and ast_channel::tech_pvt.

00403 {
00404    struct jingle_pvt *p = chan->tech_pvt;
00405    enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
00406 
00407    if (!p)
00408       return res;
00409 
00410    ast_mutex_lock(&p->lock);
00411    if (p->rtp) {
00412       *rtp = p->rtp;
00413       res = AST_RTP_TRY_PARTIAL;
00414    }
00415    ast_mutex_unlock(&p->lock);
00416 
00417    return res;
00418 }

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

Definition at line 498 of file chan_jingle.c.

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

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

static int jingle_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the jingle proxy channel.

Definition at line 1449 of file chan_jingle.c.

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

01450 {
01451    struct jingle_pvt *p = ast->tech_pvt;
01452    struct jingle *client;
01453 
01454    ast_mutex_lock(&p->lock);
01455    client = p->parent;
01456    p->owner = NULL;
01457    ast->tech_pvt = NULL;
01458    if (!p->alreadygone)
01459       jingle_action(client, p, JINGLE_TERMINATE);
01460    ast_mutex_unlock(&p->lock);
01461 
01462    jingle_free_pvt(client, p);
01463 
01464    return 0;
01465 }

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

Definition at line 562 of file chan_jingle.c.

References jingle_pvt::alreadygone, ast_debug, ast_log(), ast_queue_hangup(), JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle::name, jingle_pvt::next, jingle_pvt::owner, jingle::p, and jingle_pvt::sid.

Referenced by jingle_parser().

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

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

Definition at line 1265 of file chan_jingle.c.

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

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

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

Definition at line 478 of file chan_jingle.c.

References AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_queue_control(), JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle::name, jingle_pvt::next, jingle_pvt::owner, jingle::p, and jingle_pvt::sid.

Referenced by jingle_parser().

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

static int jingle_load_config ( void   )  [static]

Definition at line 1724 of file chan_jingle.c.

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

Referenced by load_module().

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

static void jingle_member_destroy ( struct jingle obj  )  [static]

Definition at line 239 of file chan_jingle.c.

References ast_free.

Referenced by jingle_parser(), and unload_module().

00240 {
00241    ast_free(obj);
00242 }

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

Start new jingle channel.

Definition at line 800 of file chan_jingle.c.

References accountcode, jingle::accountcode, ast_channel::adsicpe, ast_channel::amaflags, jingle::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc, ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), AST_FORMAT_VIDEO_MASK, ast_hangup(), ast_jb_configure(), ast_log(), ast_pbx_start(), ast_random(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), jingle::callgroup, ast_channel::callgroup, jingle::callingpres, jingle_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, jingle_pvt::cid_name, jingle_pvt::cid_num, ast_callerid::cid_pres, jingle::context, ast_channel::context, jingle_pvt::exten, ast_channel::exten, global_capability, global_jbconf, ast_channel::hangupcause, jingle_tech, jingle_pvt::jointcapability, language, jingle::language, LOG_WARNING, musicclass, jingle::musicclass, ast_channel::name, ast_channel::nativeformats, jingle_pvt::owner, jingle::pickupgroup, ast_channel::pickupgroup, jingle_pvt::prefs, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, jingle_pvt::rtp, str, ast_channel::tech, ast_channel::tech_pvt, jingle_pvt::them, jingle_pvt::vrtp, and ast_channel::writeformat.

Referenced by jingle_newcall(), and jingle_request().

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

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

Definition at line 954 of file chan_jingle.c.

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

Referenced by jingle_parser().

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

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

Definition at line 1593 of file chan_jingle.c.

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

Referenced by jingle_create_member().

01594 {
01595    struct jingle *client = ASTOBJ_REF((struct jingle *) data);
01596    ast_log(LOG_NOTICE, "Filter matched\n");
01597 
01598    if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
01599       /* New call */
01600       jingle_newcall(client, pak);
01601    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
01602       ast_debug(3, "About to add candidate!\n");
01603       jingle_add_candidate(client, pak);
01604       ast_debug(3, "Candidate Added!\n");
01605    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
01606       jingle_is_answered(client, pak);
01607    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
01608       jingle_handle_dtmf(client, pak);
01609    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
01610       jingle_hangup_farend(client, pak);
01611    } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
01612       jingle_hangup_farend(client, pak);
01613    }
01614    ASTOBJ_UNREF(client, jingle_member_destroy);
01615    return IKS_FILTER_EAT;
01616 }

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

Definition at line 1195 of file chan_jingle.c.

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

01196 {
01197    struct ast_frame *fr;
01198    struct jingle_pvt *p = ast->tech_pvt;
01199 
01200    ast_mutex_lock(&p->lock);
01201    fr = jingle_rtp_read(ast, p);
01202    ast_mutex_unlock(&p->lock);
01203    return fr;
01204 }

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

Part of PBX interface.

Definition at line 1468 of file chan_jingle.c.

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

01469 {
01470    struct jingle_pvt *p = NULL;
01471    struct jingle *client = NULL;
01472    char *sender = NULL, *to = NULL, *s = NULL;
01473    struct ast_channel *chan = NULL;
01474 
01475    if (data) {
01476       s = ast_strdupa(data);
01477       if (s) {
01478          sender = strsep(&s, "/");
01479          if (sender && (sender[0] != '\0'))
01480             to = strsep(&s, "/");
01481          if (!to) {
01482             ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data);
01483             return NULL;
01484          }
01485       }
01486    }
01487 
01488    client = find_jingle(to, sender);
01489    if (!client) {
01490       ast_log(LOG_WARNING, "Could not find recipient.\n");
01491       return NULL;
01492    }
01493    if (!strcasecmp(client->name, "guest")){
01494       /* the guest account is not tied to any configured XMPP client,
01495          let's set it now */
01496       client->connection = ast_aji_get_client(sender);
01497       if (!client->connection) {
01498          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01499          return NULL;
01500       }
01501    }
01502        
01503    ASTOBJ_WRLOCK(client);
01504    p = jingle_alloc(client, to, NULL);
01505    if (p)
01506       chan = jingle_new(client, p, AST_STATE_DOWN, to);
01507    ASTOBJ_UNLOCK(client);
01508 
01509    return chan;
01510 }

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

Definition at line 446 of file chan_jingle.c.

References ast_aji_send(), jingle::connection, and aji_client::jid.

Referenced by jingle_handle_dtmf(), jingle_hangup_farend(), jingle_is_answered(), and jingle_newcall().

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

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

Definition at line 377 of file chan_jingle.c.

References AST_CONTROL_RINGING, ast_queue_control(), jingle::connection, aji_client::f, jingle_pvt::owner, jingle_pvt::parent, and jingle_pvt::ringrule.

Referenced by jingle_call().

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

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

Definition at line 1167 of file chan_jingle.c.

References ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_VOICE, ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), f, 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().

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

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

Definition at line 1340 of file chan_jingle.c.

References ast_log(), and LOG_NOTICE.

01341 {
01342    ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
01343 
01344    return -1;
01345 }

static int jingle_set_rtp_peer ( struct ast_channel chan,
struct ast_rtp rtp,
struct ast_rtp vrtp,
struct ast_rtp tpeer,
int  codecs,
int  nat_active 
) [static]

Definition at line 426 of file chan_jingle.c.

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

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

static char * jingle_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command "jingle show channels".

Definition at line 1513 of file chan_jingle.c.

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

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

static int jingle_transmit_invite ( struct jingle_pvt p  )  [static]

Definition at line 1346 of file chan_jingle.c.

References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle::connection, description, 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().

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

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

Definition at line 1063 of file chan_jingle.c.

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

Referenced by jingle_add_candidate(), and jingle_rtp_read().

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

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

Send frame to media channel (rtp).

Definition at line 1207 of file chan_jingle.c.

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

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

static int load_module ( void   )  [static]

Load module into PBX, register channel.

Definition at line 1849 of file chan_jingle.c.

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

01850 {
01851    char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
01852    free(jabber_loaded);
01853    if (!jabber_loaded) {
01854       /* Dependency module has a different name, if embedded */
01855       jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
01856       free(jabber_loaded);
01857       if (!jabber_loaded) {
01858          ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n");
01859          return AST_MODULE_LOAD_DECLINE;
01860       }
01861    }
01862 
01863    ASTOBJ_CONTAINER_INIT(&jingle_list);
01864    if (!jingle_load_config()) {
01865       ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
01866       return AST_MODULE_LOAD_DECLINE;
01867    }
01868 
01869    sched = sched_context_create();
01870    if (!sched) 
01871       ast_log(LOG_WARNING, "Unable to create schedule context\n");
01872 
01873    io = io_context_create();
01874    if (!io) 
01875       ast_log(LOG_WARNING, "Unable to create I/O context\n");
01876 
01877    if (ast_find_ourip(&__ourip, bindaddr)) {
01878       ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
01879       return 0;
01880    }
01881 
01882    ast_rtp_proto_register(&jingle_rtp);
01883    ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01884    /* Make sure we can register our channel type */
01885    if (ast_channel_register(&jingle_tech)) {
01886       ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
01887       return -1;
01888    }
01889    return 0;
01890 }

static int reload ( void   )  [static]

Reload module.

Definition at line 1893 of file chan_jingle.c.

01894 {
01895    return 0;
01896 }

static int unload_module ( void   )  [static]

Unload the jingle channel from Asterisk.

Definition at line 1899 of file chan_jingle.c.

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

01900 {
01901    struct jingle_pvt *privates = NULL;
01902    ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01903    /* First, take us out of the channel loop */
01904    ast_channel_unregister(&jingle_tech);
01905    ast_rtp_proto_unregister(&jingle_rtp);
01906 
01907    if (!ast_mutex_lock(&jinglelock)) {
01908       /* Hangup all interfaces if they have an owner */
01909       ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01910          ASTOBJ_WRLOCK(iterator);
01911          privates = iterator->p;
01912          while(privates) {
01913             if (privates->owner)
01914                ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
01915             privates = privates->next;
01916          }
01917          iterator->p = NULL;
01918          ASTOBJ_UNLOCK(iterator);
01919       });
01920       ast_mutex_unlock(&jinglelock);
01921    } else {
01922       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01923       return -1;
01924    }
01925    ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
01926    ASTOBJ_CONTAINER_DESTROY(&jingle_list);
01927    return 0;
01928 }


Variable Documentation

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

Definition at line 1934 of file chan_jingle.c.

struct in_addr __ourip [static]

Definition at line 218 of file chan_jingle.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1934 of file chan_jingle.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 214 of file chan_jingle.c.

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

Definition at line 165 of file chan_jingle.c.

Referenced by load_module().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 75 of file chan_jingle.c.

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

Definition at line 164 of file chan_jingle.c.

char externip[16] [static]

Definition at line 235 of file chan_jingle.c.

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

Definition at line 167 of file chan_jingle.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 83 of file chan_jingle.c.

struct io_context* io [static]

The IO context

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

Referenced by load_module(), and unload_module().

struct jingle_container jingle_list [static]

Definition at line 237 of file chan_jingle.c.

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

struct ast_rtp_protocol jingle_rtp [static]

RTP driver interface.

Definition at line 222 of file chan_jingle.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech jingle_tech [static]

PBX interface structure for channel registration.

Definition at line 194 of file chan_jingle.c.

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

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

Protect the interface list (of jingle_pvt's)

Definition at line 169 of file chan_jingle.c.

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

struct sched_context* sched [static]

The scheduling context

Definition at line 216 of file chan_jingle.c.


Generated on Wed Aug 18 22:34:10 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7