Wed Oct 28 11:51:55 2009

Asterisk developer's documentation


chan_jingle.c File Reference

Jingle Channel Driver. More...

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

Include dependency graph for chan_jingle.c:

Go to the source code of this file.

Data Structures

struct  jingle
struct  jingle_candidate
struct  jingle_container
struct  jingle_pvt

Defines

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

Enumerations

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void add_codec_to_answer (const struct jingle_pvt *p, int codec, iks *dcodecs)
static struct jinglefind_jingle (char *name, char *connection)
static int jingle_accept_call (struct jingle *client, struct jingle_pvt *p)
static int jingle_action (struct jingle *client, struct jingle_pvt *p, const char *action)
static int jingle_add_candidate (struct jingle *client, ikspak *pak)
static struct jingle_pvtjingle_alloc (struct jingle *client, const char *from, const char *sid)
static int jingle_answer (struct ast_channel *ast)
static int jingle_call (struct ast_channel *ast, char *dest, int timeout)
 Initiate new call, part of PBX interface dest is the dial string.
static int jingle_create_candidates (struct jingle *client, struct jingle_pvt *p, char *sid, char *from)
static int jingle_create_member (char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct jingle *member)
static int jingle_digit (struct ast_channel *ast, char digit, unsigned int duration)
static int jingle_digit_begin (struct ast_channel *ast, char digit)
static int jingle_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static char * jingle_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command "jingle reload".
static int jingle_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static void jingle_free_candidates (struct jingle_candidate *candidate)
static void jingle_free_pvt (struct jingle *client, struct jingle_pvt *p)
static int jingle_get_codec (struct ast_channel *chan)
static enum ast_rtp_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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr = { 0, }
static const char channel_type [] = "Jingle"
static struct ast_jb_conf default_jbconf
static const char desc [] = "Jingle Channel"
static char externip [16]
static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263
static struct ast_jb_conf global_jbconf
static struct io_contextio
static struct ast_cli_entry jingle_cli []
static struct jingle_container jingle_list
static struct ast_rtp_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_MUTEX_INITIALIZER )
static struct sched_contextsched


Detailed Description

Jingle Channel Driver.

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

Definition in file chan_jingle.c.


Define Documentation

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

#define JINGLE_CONFIG   "jingle.conf"

Definition at line 72 of file chan_jingle.c.

Referenced by jingle_load_config(), and load_module().


Enumeration Type Documentation

Enumerator:
AJI_CONNECT_HOST 
AJI_CONNECT_PRFLX 
AJI_CONNECT_RELAY 
AJI_CONNECT_SRFLX 

Definition at line 89 of file chan_jingle.c.

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

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 84 of file chan_jingle.c.

00084                      {
00085    AJI_PROTOCOL_UDP,
00086    AJI_PROTOCOL_SSLTCP,
00087 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1933 of file chan_jingle.c.

static void __unreg_module ( void   )  [static]

Definition at line 1933 of file chan_jingle.c.

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

Definition at line 269 of file chan_jingle.c.

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

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

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

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

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

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

Definition at line 310 of file chan_jingle.c.

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

Referenced by jingle_answer().

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

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

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

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

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

Definition at line 1088 of file chan_jingle.c.

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

Referenced by jingle_parser().

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

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

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

Referenced by jingle_newcall(), and jingle_request().

00741 {
00742    struct jingle_pvt *tmp = NULL;
00743    struct aji_resource *resources = NULL;
00744    struct aji_buddy *buddy;
00745    char idroster[200];
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       } else if (client->buddy)
00754          resources = client->buddy->resources;
00755       while (resources) {
00756          if (resources->cap->jingle) {
00757             break;
00758          }
00759          resources = resources->next;
00760       }
00761       if (resources)
00762          snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource);
00763       else {
00764          ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n");
00765          return NULL;
00766       }
00767    }
00768    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00769       return NULL;
00770    }
00771 
00772    memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
00773 
00774    if (sid) {
00775       ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00776       ast_copy_string(tmp->them, from, sizeof(tmp->them));
00777    } else {
00778       snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00779       ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00780       tmp->initiator = 1;
00781    }
00782    tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
00783    tmp->parent = client;
00784    if (!tmp->rtp) {
00785       ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00786       ast_free(tmp);
00787       return NULL;
00788    }
00789    ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
00790    ast_mutex_init(&tmp->lock);
00791    ast_mutex_lock(&jinglelock);
00792    tmp->next = client->p;
00793    client->p = tmp;
00794    ast_mutex_unlock(&jinglelock);
00795    return tmp;
00796 }

static int jingle_answer ( struct ast_channel ast  )  [static]

Definition at line 388 of file chan_jingle.c.

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

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

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

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

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

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

Referenced by jingle_call(), and jingle_newcall().

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

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

References jingle::allowguest, ast_aji_get_client(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, jingle::buddy, jingle::capability, jingle::connection, jingle::context, aji_client::f, JINGLE_NS, jingle_parser(), LOG_ERROR, LOG_WARNING, ast_variable::name, jingle::name, ast_variable::next, jingle_candidate::next, jingle::prefs, jingle::user, and ast_variable::value.

Referenced by jingle_load_config().

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

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

Definition at line 1283 of file chan_jingle.c.

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

Referenced by jingle_digit_begin(), and jingle_digit_end().

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

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

Definition at line 1329 of file chan_jingle.c.

References jingle_digit().

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

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

Definition at line 1334 of file chan_jingle.c.

References jingle_digit().

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

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

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

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

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

Definition at line 1249 of file chan_jingle.c.

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

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

static void jingle_free_candidates ( struct jingle_candidate candidate  )  [static]

Definition at line 915 of file chan_jingle.c.

References ast_free, last, and jingle_candidate::next.

Referenced by jingle_free_pvt(), and jingle_load_config().

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

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

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

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

static int jingle_get_codec ( struct ast_channel chan  )  [static]

Definition at line 419 of file chan_jingle.c.

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

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

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

Definition at line 401 of file chan_jingle.c.

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

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

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

Definition at line 497 of file chan_jingle.c.

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

Referenced by jingle_parser().

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

static int jingle_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the jingle proxy channel.

Definition at line 1448 of file chan_jingle.c.

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

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

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

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

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

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

Definition at line 1264 of file chan_jingle.c.

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

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

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

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

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

static int jingle_load_config ( void   )  [static]

Definition at line 1723 of file chan_jingle.c.

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

Referenced by load_module().

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

static void jingle_member_destroy ( struct jingle obj  )  [static]

Definition at line 238 of file chan_jingle.c.

References ast_free.

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

00239 {
00240    ast_free(obj);
00241 }

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

Start new jingle channel.

Definition at line 799 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_jbconf, ast_channel::hangupcause, jingle_pvt::jointcapability, language, jingle::language, LOG_WARNING, musicclass, jingle::musicclass, ast_channel::name, ast_channel::nativeformats, jingle_pvt::owner, jingle::pickupgroup, ast_channel::pickupgroup, jingle_pvt::prefs, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, jingle_pvt::rtp, str, ast_channel::tech, ast_channel::tech_pvt, jingle_pvt::them, jingle_pvt::vrtp, and ast_channel::writeformat.

Referenced by jingle_newcall(), and jingle_request().

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

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

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

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

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

Definition at line 1592 of file chan_jingle.c.

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

Referenced by jingle_create_member(), and jingle_load_config().

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

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

Definition at line 1194 of file chan_jingle.c.

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

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

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

Part of PBX interface.

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

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

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

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

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

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

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

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

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

Definition at line 1166 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, ast_frame::frametype, jingle_update_stun(), ast_channel::nativeformats, jingle_pvt::owner, jingle_pvt::parent, ast_channel::readformat, jingle_pvt::rtp, ast_frame::subclass, and ast_channel::writeformat.

Referenced by jingle_read().

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

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

Definition at line 1339 of file chan_jingle.c.

References ast_log(), and LOG_NOTICE.

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

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

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

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

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

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

static int jingle_transmit_invite ( struct jingle_pvt p  )  [static]

Definition at line 1345 of file chan_jingle.c.

References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle_pvt::audio_content_name, 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, jingle_pvt::parent, jingle_pvt::sid, and jingle_pvt::them.

Referenced by jingle_call().

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

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

Definition at line 1062 of file chan_jingle.c.

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

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

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

Send frame to media channel (rtp).

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

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

static int load_module ( void   )  [static]

Load module into PBX, register channel.

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

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

static int reload ( void   )  [static]

Reload module.

Definition at line 1892 of file chan_jingle.c.

01893 {
01894    return 0;
01895 }

static int unload_module ( void   )  [static]

Unload the jingle channel from Asterisk.

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

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


Variable Documentation

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

Definition at line 1933 of file chan_jingle.c.

struct in_addr __ourip [static]

Definition at line 217 of file chan_jingle.c.

Definition at line 1933 of file chan_jingle.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 213 of file chan_jingle.c.

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

Definition at line 164 of file chan_jingle.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 75 of file chan_jingle.c.

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

Definition at line 163 of file chan_jingle.c.

char externip[16] [static]

Definition at line 234 of file chan_jingle.c.

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

Definition at line 166 of file chan_jingle.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 82 of file chan_jingle.c.

struct io_context* io [static]

The IO context

Definition at line 216 of file chan_jingle.c.

struct ast_cli_entry jingle_cli[] [static]

Initial value:

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

Definition at line 228 of file chan_jingle.c.

struct jingle_container jingle_list [static]

struct ast_rtp_protocol jingle_rtp [static]

RTP driver interface.

Definition at line 221 of file chan_jingle.c.

struct ast_channel_tech jingle_tech [static]

PBX interface structure for channel registration.

Definition at line 193 of file chan_jingle.c.

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

Protect the interface list (of jingle_pvt's)

Definition at line 168 of file chan_jingle.c.

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

struct sched_context* sched [static]

The scheduling context

Definition at line 215 of file chan_jingle.c.


Generated on Wed Oct 28 11:51:55 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6