Wed Mar 4 19:58:27 2009

Asterisk developer's documentation


chan_gtalk.c File Reference

Gtalk Channel Driver, until google/libjingle works with jingle spec. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.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 <gcrypt.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.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"

Go to the source code of this file.

Data Structures

struct  gtalk
struct  gtalk_candidate
struct  gtalk_container
struct  gtalk_pvt

Defines

#define FORMAT   "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n"
#define GOOGLE_CONFIG   "gtalk.conf"
#define GOOGLE_NS   "http://www.google.com/session"

Enumerations

enum  gtalk_connect_type { AJI_CONNECT_STUN = 1, AJI_CONNECT_LOCAL = 2, AJI_CONNECT_RELAY = 3 }
enum  gtalk_protocol { AJI_PROTOCOL_UDP = 1, AJI_PROTOCOL_SSLTCP = 2 }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int add_codec_to_answer (const struct gtalk_pvt *p, int codec, iks *dcodecs)
static struct gtalkfind_gtalk (char *name, char *connection)
static int gtalk_action (struct gtalk *client, struct gtalk_pvt *p, const char *action)
static int gtalk_add_candidate (struct gtalk *client, ikspak *pak)
static struct gtalk_pvtgtalk_alloc (struct gtalk *client, const char *us, const char *them, const char *sid)
static int gtalk_answer (struct ast_channel *ast)
static int gtalk_call (struct ast_channel *ast, char *dest, int timeout)
 Initiate new call, part of PBX interface dest is the dial string.
static int gtalk_create_candidates (struct gtalk *client, struct gtalk_pvt *p, char *sid, char *from, char *to)
static int gtalk_create_member (char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct gtalk *member)
static int gtalk_digit (struct ast_channel *ast, char digit, unsigned int duration)
static int gtalk_digit_begin (struct ast_channel *ast, char digit)
static int gtalk_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static int gtalk_do_reload (int fd, int argc, char **argv)
 CLI command "gtalk show channels".
static int gtalk_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static void gtalk_free_candidates (struct gtalk_candidate *candidate)
static void gtalk_free_pvt (struct gtalk *client, struct gtalk_pvt *p)
static int gtalk_get_codec (struct ast_channel *chan)
static enum ast_rtp_get_result gtalk_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static int gtalk_handle_dtmf (struct gtalk *client, ikspak *pak)
static int gtalk_hangup (struct ast_channel *ast)
 Hangup a call through the gtalk proxy channel.
static int gtalk_hangup_farend (struct gtalk *client, ikspak *pak)
static int gtalk_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
static int gtalk_invite (struct gtalk_pvt *p, char *to, char *from, char *sid, int initiator)
static int gtalk_invite_response (struct gtalk_pvt *p, char *to, char *from, char *sid, int initiator)
static int gtalk_is_accepted (struct gtalk *client, ikspak *pak)
static int gtalk_is_answered (struct gtalk *client, ikspak *pak)
static int gtalk_load_config (void)
static void gtalk_member_destroy (struct gtalk *obj)
static struct ast_channelgtalk_new (struct gtalk *client, struct gtalk_pvt *i, int state, const char *title)
 Start new gtalk channel.
static int gtalk_newcall (struct gtalk *client, ikspak *pak)
static int gtalk_parser (void *data, ikspak *pak)
static struct ast_framegtalk_read (struct ast_channel *ast)
static struct ast_channelgtalk_request (const char *type, int format, void *data, int *cause)
 Part of PBX interface.
static int gtalk_response (struct gtalk *client, char *from, ikspak *pak, const char *reasonstr, const char *reasonstr2)
static int gtalk_ringing_ack (void *data, ikspak *pak)
static struct ast_framegtalk_rtp_read (struct ast_channel *ast, struct gtalk_pvt *p)
static int gtalk_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen)
static int gtalk_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
static int gtalk_show_channels (int fd, int argc, char **argv)
 CLI command "gtalk show channels".
static int gtalk_update_stun (struct gtalk *client, struct gtalk_pvt *p)
static int gtalk_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 gtalk channel from Asterisk.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Gtalk 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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static const struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr = { 0, }
static struct ast_jb_conf default_jbconf
static const char desc [] = "Gtalk Channel"
static char externip [16]
 GCRY_THREAD_OPTION_PTHREAD_IMPL
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 ast_cli_entry gtalk_cli []
static struct gtalk_container gtalk_list
static struct ast_rtp_protocol gtalk_rtp
 RTP driver interface.
static struct ast_channel_tech gtalk_tech
 PBX interface structure for channel registration.
static ast_mutex_t gtalklock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct io_contextio
static char reload_usage []
static struct sched_contextsched
static char show_channels_usage []


Detailed Description

Gtalk Channel Driver, until google/libjingle works with jingle spec.

Author:
Matt O'Gorman <mogorman@digium.com>

Definition in file chan_gtalk.c.


Define Documentation

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

#define GOOGLE_CONFIG   "gtalk.conf"

Definition at line 83 of file chan_gtalk.c.

Referenced by gtalk_load_config(), and load_module().

#define GOOGLE_NS   "http://www.google.com/session"

Definition at line 85 of file chan_gtalk.c.


Enumeration Type Documentation

enum gtalk_connect_type

Enumerator:
AJI_CONNECT_STUN 
AJI_CONNECT_LOCAL 
AJI_CONNECT_RELAY 

Definition at line 103 of file chan_gtalk.c.

00103                         {
00104    AJI_CONNECT_STUN = 1,
00105    AJI_CONNECT_LOCAL = 2,
00106    AJI_CONNECT_RELAY = 3,
00107 };

enum gtalk_protocol

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 98 of file chan_gtalk.c.

00098                     {
00099    AJI_PROTOCOL_UDP = 1,
00100    AJI_PROTOCOL_SSLTCP = 2,
00101 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 2067 of file chan_gtalk.c.

static void __unreg_module ( void   )  [static]

Definition at line 2067 of file chan_gtalk.c.

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

Definition at line 297 of file chan_gtalk.c.

References ast_getformatname(), ast_log(), ast_rtp_lookup_code(), format, LOG_WARNING, gtalk::p, and gtalk_pvt::rtp.

Referenced by gtalk_invite().

00298 {
00299    int res = 0;
00300    char *format = ast_getformatname(codec);
00301 
00302    if (!strcasecmp("ulaw", format)) {
00303       iks *payload_eg711u, *payload_pcmu;
00304       payload_pcmu = iks_new("payload-type");
00305       payload_eg711u = iks_new("payload-type");
00306    
00307       if(!payload_eg711u || !payload_pcmu) {
00308          if(payload_pcmu)
00309             iks_delete(payload_pcmu);
00310          if(payload_eg711u)
00311             iks_delete(payload_eg711u);
00312          ast_log(LOG_WARNING,"Failed to allocate iks node");
00313          return -1;
00314       }
00315       iks_insert_attrib(payload_pcmu, "id", "0");
00316       iks_insert_attrib(payload_pcmu, "name", "PCMU");
00317       iks_insert_attrib(payload_pcmu, "clockrate","8000");
00318       iks_insert_attrib(payload_pcmu, "bitrate","64000");
00319       iks_insert_attrib(payload_eg711u, "id", "100");
00320       iks_insert_attrib(payload_eg711u, "name", "EG711U");
00321       iks_insert_attrib(payload_eg711u, "clockrate","8000");
00322       iks_insert_attrib(payload_eg711u, "bitrate","64000");
00323       iks_insert_node(dcodecs, payload_pcmu);
00324       iks_insert_node(dcodecs, payload_eg711u);
00325       res ++;
00326    }
00327    if (!strcasecmp("alaw", format)) {
00328       iks *payload_eg711a, *payload_pcma;
00329       payload_pcma = iks_new("payload-type");
00330       payload_eg711a = iks_new("payload-type");
00331       if(!payload_eg711a || !payload_pcma) {
00332          if(payload_eg711a)
00333             iks_delete(payload_eg711a);
00334          if(payload_pcma)
00335             iks_delete(payload_pcma);
00336          ast_log(LOG_WARNING,"Failed to allocate iks node");
00337          return -1;
00338       }
00339       iks_insert_attrib(payload_pcma, "id", "8");
00340       iks_insert_attrib(payload_pcma, "name", "PCMA");
00341       iks_insert_attrib(payload_pcma, "clockrate","8000");
00342       iks_insert_attrib(payload_pcma, "bitrate","64000");
00343       payload_eg711a = iks_new("payload-type");
00344       iks_insert_attrib(payload_eg711a, "id", "101");
00345       iks_insert_attrib(payload_eg711a, "name", "EG711A");
00346       iks_insert_attrib(payload_eg711a, "clockrate","8000");
00347       iks_insert_attrib(payload_eg711a, "bitrate","64000");
00348       iks_insert_node(dcodecs, payload_pcma);
00349       iks_insert_node(dcodecs, payload_eg711a);
00350       res ++;
00351    }
00352    if (!strcasecmp("ilbc", format)) {
00353       iks *payload_ilbc = iks_new("payload-type");
00354       if(!payload_ilbc) {
00355          ast_log(LOG_WARNING,"Failed to allocate iks node");
00356          return -1;
00357       }
00358       iks_insert_attrib(payload_ilbc, "id", "97");
00359       iks_insert_attrib(payload_ilbc, "name", "iLBC");
00360       iks_insert_attrib(payload_ilbc, "clockrate","8000");
00361       iks_insert_attrib(payload_ilbc, "bitrate","13300");
00362       iks_insert_node(dcodecs, payload_ilbc);
00363       res ++;
00364    }
00365    if (!strcasecmp("g723", format)) {
00366       iks *payload_g723 = iks_new("payload-type");
00367       if(!payload_g723) {
00368          ast_log(LOG_WARNING,"Failed to allocate iks node");
00369          return -1;
00370       }
00371       iks_insert_attrib(payload_g723, "id", "4");
00372       iks_insert_attrib(payload_g723, "name", "G723");
00373       iks_insert_attrib(payload_g723, "clockrate","8000");
00374       iks_insert_attrib(payload_g723, "bitrate","6300");
00375       iks_insert_node(dcodecs, payload_g723);
00376       res ++;
00377    }
00378    if (!strcasecmp("speex", format)) {
00379       iks *payload_speex = iks_new("payload-type");
00380       if(!payload_speex) {
00381          ast_log(LOG_WARNING,"Failed to allocate iks node");
00382          return -1;
00383       }
00384       iks_insert_attrib(payload_speex, "id", "110");
00385       iks_insert_attrib(payload_speex, "name", "speex");
00386       iks_insert_attrib(payload_speex, "clockrate","8000");
00387       iks_insert_attrib(payload_speex, "bitrate","11000");
00388       iks_insert_node(dcodecs, payload_speex);
00389       res++;
00390    }
00391    if (!strcasecmp("gsm", format)) {
00392       iks *payload_gsm = iks_new("payload-type");
00393       if(!payload_gsm) {
00394          ast_log(LOG_WARNING,"Failed to allocate iks node");
00395          return -1;
00396       }
00397       iks_insert_attrib(payload_gsm, "id", "103");
00398       iks_insert_attrib(payload_gsm, "name", "gsm");
00399       iks_insert_node(dcodecs, payload_gsm);
00400       res++;
00401    }
00402    ast_rtp_lookup_code(p->rtp, 1, codec);
00403    return res;
00404 }

static struct gtalk* find_gtalk ( char *  name,
char *  connection 
) [static]

Definition at line 265 of file chan_gtalk.c.

References ast_strdupa, ast_verbose(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, gtalk_list, s, and gtalk::user.

Referenced by gtalk_request().

00266 {
00267    struct gtalk *gtalk = NULL;
00268    char *domain = NULL , *s = NULL;
00269 
00270    if(strchr(connection, '@')) {
00271       s = ast_strdupa(connection);
00272       domain = strsep(&s, "@");
00273       ast_verbose("OOOOH domain = %s\n", domain);
00274    }
00275    gtalk = ASTOBJ_CONTAINER_FIND(&gtalk_list, name);
00276    if (!gtalk && strchr(name, '@'))
00277       gtalk = ASTOBJ_CONTAINER_FIND_FULL(&gtalk_list, name, user,,, strcasecmp);
00278 
00279    if (!gtalk) {
00280       /* guest call */
00281       ASTOBJ_CONTAINER_TRAVERSE(&gtalk_list, 1, {
00282          ASTOBJ_RDLOCK(iterator);
00283          if (!strcasecmp(iterator->name, "guest")) {
00284             gtalk = iterator;
00285          }
00286          ASTOBJ_UNLOCK(iterator);
00287 
00288          if (gtalk)
00289             break;
00290       });
00291 
00292    }
00293    return gtalk;
00294 }

static int gtalk_action ( struct gtalk client,
struct gtalk_pvt p,
const char *  action 
) [static]

Definition at line 1073 of file chan_gtalk.c.

References ast_aji_increment_mid(), gtalk::connection, gtalk_pvt::initiator, aji_client::mid, aji_client::p, gtalk_pvt::sid, gtalk_pvt::them, and gtalk_pvt::us.

Referenced by gtalk_hangup(), and gtalk_newcall().

01074 {
01075    iks *request, *session = NULL;
01076    int res = -1;
01077 
01078    request = iks_new("iq");
01079    if (request) {
01080       iks_insert_attrib(request, "type", "set");
01081       iks_insert_attrib(request, "from", p->us);
01082       iks_insert_attrib(request, "to", p->them);
01083       iks_insert_attrib(request, "id", client->connection->mid);
01084       ast_aji_increment_mid(client->connection->mid);
01085       session = iks_new("session");
01086       if (session) {
01087          iks_insert_attrib(session, "type", action);
01088          iks_insert_attrib(session, "id", p->sid);
01089          iks_insert_attrib(session, "initiator", p->initiator ? p->us : p->them);
01090          iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
01091          iks_insert_node(request, session);
01092          iks_send(client->connection->p, request);
01093          iks_delete(session);
01094          res = 0;
01095       }
01096       iks_delete(request);
01097    }
01098    return res;
01099 }

static int gtalk_add_candidate ( struct gtalk client,
ikspak *  pak 
) [static]

Definition at line 1287 of file chan_gtalk.c.

References AJI_CONNECT_LOCAL, AJI_CONNECT_RELAY, AJI_CONNECT_STUN, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_calloc, ast_copy_string(), gtalk::connection, gtalk_update_stun(), aji_client::jid, gtalk_pvt::laststun, gtalk_pvt::next, aji_client::p, gtalk::p, gtalk_pvt::parent, gtalk_candidate::receipt, and gtalk_pvt::theircandidates.

Referenced by gtalk_parser().

01288 {
01289    struct gtalk_pvt *p = NULL, *tmp = NULL;
01290    struct aji_client *c = client->connection;
01291    struct gtalk_candidate *newcandidate = NULL;
01292    iks *traversenodes = NULL, *receipt = NULL;
01293    char *from;
01294 
01295    from = iks_find_attrib(pak->x,"to");
01296    if(!from)
01297       from = c->jid->full;
01298 
01299    for (tmp = client->p; tmp; tmp = tmp->next) {
01300       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) {
01301          p = tmp;
01302          break;
01303       }
01304    }
01305 
01306    if (!p)
01307       return -1;
01308 
01309    traversenodes = pak->query;
01310    while(traversenodes) {
01311       if(!strcasecmp(iks_name(traversenodes), "session")) {
01312          traversenodes = iks_child(traversenodes);
01313          continue;
01314       }
01315       if(!strcasecmp(iks_name(traversenodes), "transport")) {
01316          traversenodes = iks_child(traversenodes);
01317          continue;
01318       }
01319       if(!strcasecmp(iks_name(traversenodes), "candidate")) {
01320          newcandidate = ast_calloc(1, sizeof(*newcandidate));
01321          if (!newcandidate)
01322             return 0;
01323          ast_copy_string(newcandidate->name, iks_find_attrib(traversenodes, "name"),
01324                      sizeof(newcandidate->name));
01325          ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "address"),
01326                      sizeof(newcandidate->ip));
01327          newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
01328          ast_copy_string(newcandidate->username, iks_find_attrib(traversenodes, "username"),
01329                      sizeof(newcandidate->username));
01330          ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "password"),
01331                      sizeof(newcandidate->password));
01332          newcandidate->preference = atof(iks_find_attrib(traversenodes, "preference"));
01333          if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
01334             newcandidate->protocol = AJI_PROTOCOL_UDP;
01335          if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
01336             newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
01337       
01338          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "stun"))
01339             newcandidate->type = AJI_CONNECT_STUN;
01340          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "local"))
01341             newcandidate->type = AJI_CONNECT_LOCAL;
01342          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
01343             newcandidate->type = AJI_CONNECT_RELAY;
01344          ast_copy_string(newcandidate->network, iks_find_attrib(traversenodes, "network"),
01345                      sizeof(newcandidate->network));
01346          newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
01347          newcandidate->next = NULL;
01348       
01349          newcandidate->next = p->theircandidates;
01350          p->theircandidates = newcandidate;
01351          p->laststun = 0;
01352          gtalk_update_stun(p->parent, p);
01353          newcandidate = NULL;
01354       }
01355       traversenodes = iks_next(traversenodes);
01356    }
01357    
01358    receipt = iks_new("iq");
01359    iks_insert_attrib(receipt, "type", "result");
01360    iks_insert_attrib(receipt, "from", from);
01361    iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
01362    iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
01363    iks_send(c->p, receipt);
01364    iks_delete(receipt);
01365 
01366    return 1;
01367 }

static struct gtalk_pvt * gtalk_alloc ( struct gtalk client,
const char *  us,
const char *  them,
const char *  sid 
) [static]

Definition at line 916 of file chan_gtalk.c.

References ast_calloc, ast_copy_string(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_new_with_bindaddr(), ast_rtp_pt_clear(), ast_strdupa, ASTOBJ_CONTAINER_FIND, bindaddr, aji_client::buddies, gtalk::buddy, aji_resource::cap, gtalk::capability, gtalk::connection, exten, free, global_capability, gtalklock, io, aji_version::jingle, LOG_DEBUG, LOG_ERROR, LOG_WARNING, gtalk::name, aji_resource::next, option_debug, gtalk::p, aji_resource::resource, and aji_buddy::resources.

Referenced by gtalk_newcall(), and gtalk_request().

00917 {
00918    struct gtalk_pvt *tmp = NULL;
00919    struct aji_resource *resources = NULL;
00920    struct aji_buddy *buddy;
00921    char idroster[200];
00922    char *data, *exten = NULL;
00923 
00924    if (option_debug)
00925       ast_log(LOG_DEBUG, "The client is %s for alloc\n", client->name);
00926    if (!sid && !strchr(them, '/')) {   /* I started call! */
00927       if (!strcasecmp(client->name, "guest")) {
00928          buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, them);
00929          if (buddy)
00930             resources = buddy->resources;
00931       } else if (client->buddy)
00932          resources = client->buddy->resources;
00933       while (resources) {
00934          if (resources->cap->jingle) {
00935             break;
00936          }
00937          resources = resources->next;
00938       }
00939       if (resources)
00940          snprintf(idroster, sizeof(idroster), "%s/%s", them, resources->resource);
00941       else {
00942          ast_log(LOG_ERROR, "no gtalk capable clients to talk to.\n");
00943          return NULL;
00944       }
00945    }
00946    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00947       return NULL;
00948    }
00949    if (sid) {
00950       ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00951       ast_copy_string(tmp->them, them, sizeof(tmp->them));
00952       ast_copy_string(tmp->us, us, sizeof(tmp->us));
00953    } else {
00954       snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00955       ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00956       ast_copy_string(tmp->us, us, sizeof(tmp->us));
00957       tmp->initiator = 1;
00958    }
00959    /* clear codecs */
00960    tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
00961    ast_rtp_pt_clear(tmp->rtp);
00962 
00963    /* add user configured codec capabilites */
00964    if (client->capability)
00965       tmp->capability = client->capability;
00966    else if (global_capability)
00967       tmp->capability = global_capability;
00968 
00969    tmp->parent = client;
00970    if (!tmp->rtp) {
00971       ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00972       free(tmp);
00973       return NULL;
00974    }
00975 
00976    /* Set CALLERID(name) to the full JID of the remote peer */
00977    ast_copy_string(tmp->cid_name, tmp->them, sizeof(tmp->cid_name));
00978 
00979    if(strchr(tmp->us, '/')) {
00980       data = ast_strdupa(tmp->us);
00981       exten = strsep(&data, "/");
00982    } else
00983       exten = tmp->us;
00984    ast_copy_string(tmp->exten,  exten, sizeof(tmp->exten));
00985    ast_mutex_init(&tmp->lock);
00986    ast_mutex_lock(&gtalklock);
00987    tmp->next = client->p;
00988    client->p = tmp;
00989    ast_mutex_unlock(&gtalklock);
00990    return tmp;
00991 }

static int gtalk_answer ( struct ast_channel ast  )  [static]

Definition at line 529 of file chan_gtalk.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), gtalk_invite(), gtalk_pvt::lock, LOG_DEBUG, option_debug, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.

00530 {
00531    struct gtalk_pvt *p = ast->tech_pvt;
00532    int res = 0;
00533    
00534    if (option_debug)
00535       ast_log(LOG_DEBUG, "Answer!\n");
00536    ast_mutex_lock(&p->lock);
00537    gtalk_invite(p, p->them, p->us,p->sid, 0);
00538    ast_mutex_unlock(&p->lock);
00539    return res;
00540 }

static int gtalk_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 1572 of file chan_gtalk.c.

References ast_channel::_state, ast_copy_string(), ast_log(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RING, gtalk::connection, aji_client::f, gtalk_create_candidates(), gtalk_invite(), gtalk_ringing_ack(), LOG_WARNING, aji_client::mid, ast_channel::name, gtalk_pvt::parent, gtalk_pvt::ring, gtalk_pvt::ringrule, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.

01573 {
01574    struct gtalk_pvt *p = ast->tech_pvt;
01575 
01576    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01577       ast_log(LOG_WARNING, "gtalk_call called on %s, neither down nor reserved\n", ast->name);
01578       return -1;
01579    }
01580 
01581    ast_setstate(ast, AST_STATE_RING);
01582    if (!p->ringrule) {
01583       ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01584       p->ringrule = iks_filter_add_rule(p->parent->connection->f, gtalk_ringing_ack, p,
01585                      IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01586    } else
01587       ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01588 
01589    gtalk_invite(p, p->them, p->us, p->sid, 1);
01590    gtalk_create_candidates(p->parent, p, p->sid, p->them, p->us);
01591 
01592    return 0;
01593 }

static int gtalk_create_candidates ( struct gtalk client,
struct gtalk_pvt p,
char *  sid,
char *  from,
char *  to 
) [static]

Definition at line 788 of file chan_gtalk.c.

References __ourip, AJI_CONNECT_LOCAL, AJI_CONNECT_RELAY, AJI_CONNECT_STUN, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_increment_mid(), ast_calloc, ast_copy_string(), ast_find_ourip(), ast_inet_ntoa(), ast_log(), ast_random(), ast_rtp_get_us(), ast_strlen_zero(), bindaddr, gtalk::connection, externip, free, GOOGLE_NS, gtalk_pvt::initiator, gtalk_candidate::ip, gtalk_pvt::laststun, LOG_ERROR, LOG_NOTICE, aji_client::mid, gtalk_candidate::name, gtalk_candidate::next, gtalk_pvt::next, gtalk_pvt::ourcandidates, aji_client::p, gtalk_candidate::password, gtalk_candidate::port, gtalk_candidate::preference, gtalk_candidate::protocol, gtalk_pvt::rtp, gtalk_pvt::sid, gtalk_candidate::type, and gtalk_candidate::username.

Referenced by gtalk_call(), and gtalk_newcall().

00789 {
00790    struct gtalk_candidate *tmp;
00791    struct aji_client *c = client->connection;
00792    struct gtalk_candidate *ours1 = NULL, *ours2 = NULL;
00793    struct sockaddr_in sin;
00794    struct sockaddr_in dest;
00795    struct in_addr us;
00796    iks *iq, *gtalk, *candidate, *transport;
00797    char user[17], pass[17], preference[5], port[7];
00798 
00799 
00800    iq = iks_new("iq");
00801    gtalk = iks_new("session");
00802    candidate = iks_new("candidate");
00803    transport = iks_new("transport");
00804    if (!iq || !gtalk || !candidate || !transport) {
00805       ast_log(LOG_ERROR, "Memory allocation error\n");
00806       goto safeout;
00807    }
00808    ours1 = ast_calloc(1, sizeof(*ours1));
00809    ours2 = ast_calloc(1, sizeof(*ours2));
00810    if (!ours1 || !ours2)
00811       goto safeout;
00812 
00813    iks_insert_attrib(transport, "xmlns","http://www.google.com/transport/p2p");
00814    iks_insert_node(iq, gtalk);
00815    iks_insert_node(gtalk,transport);
00816    iks_insert_node(transport, candidate);
00817 
00818    for (; p; p = p->next) {
00819       if (!strcasecmp(p->sid, sid))
00820          break;
00821    }
00822 
00823    if (!p) {
00824       ast_log(LOG_NOTICE, "No matching gtalk session - SID %s!\n", sid);
00825       goto safeout;
00826    }
00827 
00828    ast_rtp_get_us(p->rtp, &sin);
00829    ast_find_ourip(&us, bindaddr);
00830 
00831    /* Setup our gtalk candidates */
00832    ast_copy_string(ours1->name, "rtp", sizeof(ours1->name));
00833    ours1->port = ntohs(sin.sin_port);
00834    ours1->preference = 1;
00835    snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00836    snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00837    ast_copy_string(ours1->username, user, sizeof(ours1->username));
00838    ast_copy_string(ours1->password, pass, sizeof(ours1->password));
00839    ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
00840    ours1->protocol = AJI_PROTOCOL_UDP;
00841    ours1->type = AJI_CONNECT_LOCAL;
00842    ours1->generation = 0;
00843    p->ourcandidates = ours1;
00844 
00845    if (!ast_strlen_zero(externip)) {
00846       /* XXX We should really stun for this one not just go with externip XXX */
00847       snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00848       snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00849       ast_copy_string(ours2->username, user, sizeof(ours2->username));
00850       ast_copy_string(ours2->password, pass, sizeof(ours2->password));
00851       ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
00852       ast_copy_string(ours2->name, "rtp", sizeof(ours1->name));
00853       ours2->port = ntohs(sin.sin_port);
00854       ours2->preference = 0.9;
00855       ours2->protocol = AJI_PROTOCOL_UDP;
00856       ours2->type = AJI_CONNECT_STUN;
00857       ours2->generation = 0;
00858       ours1->next = ours2;
00859       ours2 = NULL;
00860    }
00861    ours1 = NULL;
00862    dest.sin_addr = __ourip;
00863    dest.sin_port = sin.sin_port;
00864 
00865 
00866    for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
00867       snprintf(port, sizeof(port), "%d", tmp->port);
00868       snprintf(preference, sizeof(preference), "%.2f", tmp->preference);
00869       iks_insert_attrib(iq, "from", to);
00870       iks_insert_attrib(iq, "to", from);
00871       iks_insert_attrib(iq, "type", "set");
00872       iks_insert_attrib(iq, "id", c->mid);
00873       ast_aji_increment_mid(c->mid);
00874       iks_insert_attrib(gtalk, "type", "transport-info");
00875       iks_insert_attrib(gtalk, "id", sid);
00876       iks_insert_attrib(gtalk, "initiator", (p->initiator) ? to : from);
00877       iks_insert_attrib(gtalk, "xmlns", GOOGLE_NS);
00878       iks_insert_attrib(candidate, "name", tmp->name);
00879       iks_insert_attrib(candidate, "address", tmp->ip);
00880       iks_insert_attrib(candidate, "port", port);
00881       iks_insert_attrib(candidate, "username", tmp->username);
00882       iks_insert_attrib(candidate, "password", tmp->password);
00883       iks_insert_attrib(candidate, "preference", preference);
00884       if (tmp->protocol == AJI_PROTOCOL_UDP)
00885          iks_insert_attrib(candidate, "protocol", "udp");
00886       if (tmp->protocol == AJI_PROTOCOL_SSLTCP)
00887          iks_insert_attrib(candidate, "protocol", "ssltcp");
00888       if (tmp->type == AJI_CONNECT_STUN)
00889          iks_insert_attrib(candidate, "type", "stun");
00890       if (tmp->type == AJI_CONNECT_LOCAL)
00891          iks_insert_attrib(candidate, "type", "local");
00892       if (tmp->type == AJI_CONNECT_RELAY)
00893          iks_insert_attrib(candidate, "type", "relay");
00894       iks_insert_attrib(candidate, "network", "0");
00895       iks_insert_attrib(candidate, "generation", "0");
00896       iks_send(c->p, iq);
00897    }
00898    p->laststun = 0;
00899 
00900 safeout:
00901    if (ours1)
00902       free(ours1);
00903    if (ours2)
00904       free(ours2);
00905    if (iq)
00906       iks_delete(iq);
00907    if (gtalk)
00908       iks_delete(gtalk);
00909    if (candidate)
00910       iks_delete(candidate);
00911    if(transport)
00912       iks_delete(transport);
00913    return 1;
00914 }

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

Definition at line 1797 of file chan_gtalk.c.

References gtalk::allowguest, ast_aji_get_client(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, gtalk::buddy, gtalk::capability, gtalk::connection, gtalk::context, aji_client::f, gtalk_parser(), LOG_ERROR, LOG_WARNING, gtalk::name, gtalk_candidate::next, prefs, gtalk::prefs, gtalk::user, and var.

01800 {
01801    struct aji_client *client;
01802 
01803    if (!member)
01804       ast_log(LOG_WARNING, "Out of memory.\n");
01805 
01806    ast_copy_string(member->name, label, sizeof(member->name));
01807    ast_copy_string(member->user, label, sizeof(member->user));
01808    ast_copy_string(member->context, context, sizeof(member->context));
01809    member->allowguest = allowguest;
01810    member->prefs = prefs;
01811    while (var) {
01812 #if 0
01813       struct gtalk_candidate *candidate = NULL;
01814 #endif
01815       if (!strcasecmp(var->name, "username"))
01816          ast_copy_string(member->user, var->value, sizeof(member->user));
01817       else if (!strcasecmp(var->name, "disallow"))
01818          ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
01819       else if (!strcasecmp(var->name, "allow"))
01820          ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
01821       else if (!strcasecmp(var->name, "context"))
01822          ast_copy_string(member->context, var->value, sizeof(member->context));
01823 #if 0
01824       else if (!strcasecmp(var->name, "candidate")) {
01825          candidate = gtalk_create_candidate(var->value);
01826          if (candidate) {
01827             candidate->next = member->ourcandidates;
01828             member->ourcandidates = candidate;
01829          }
01830       }
01831 #endif
01832       else if (!strcasecmp(var->name, "connection")) {
01833          if ((client = ast_aji_get_client(var->value))) {
01834             member->connection = client;
01835             iks_filter_add_rule(client->f, gtalk_parser, member, 
01836                       IKS_RULE_TYPE, IKS_PAK_IQ, 
01837                       IKS_RULE_FROM_PARTIAL, member->user,
01838                       IKS_RULE_NS, "http://www.google.com/session",
01839                       IKS_RULE_DONE);
01840 
01841          } else {
01842             ast_log(LOG_ERROR, "connection referenced not found!\n");
01843             return 0;
01844          }
01845       }
01846       var = var->next;
01847    }
01848    if (member->connection && member->user)
01849       member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
01850    else {
01851       ast_log(LOG_ERROR, "No Connection or Username!\n");
01852    }
01853    return 1;
01854 }

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

Definition at line 1497 of file chan_gtalk.c.

References ast_aji_increment_mid(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), gtalk::connection, ast_channel::dtmff, ast_frame::frametype, gtalk_pvt::initiator, gtalk_pvt::lock, LOG_ERROR, aji_client::mid, aji_client::p, gtalk::p, gtalk_pvt::parent, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.

Referenced by gtalk_digit_begin(), and gtalk_digit_end().

01498 {
01499    struct gtalk_pvt *p = ast->tech_pvt;
01500    struct gtalk *client = p->parent;
01501    iks *iq, *gtalk, *dtmf;
01502    char buffer[2] = {digit, '\0'};
01503    iq = iks_new("iq");
01504    gtalk = iks_new("gtalk");
01505    dtmf = iks_new("dtmf");
01506    if(!iq || !gtalk || !dtmf) {
01507       if(iq)
01508          iks_delete(iq);
01509       if(gtalk)
01510          iks_delete(gtalk);
01511       if(dtmf)
01512          iks_delete(dtmf);
01513       ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
01514       return -1;
01515    }
01516 
01517    iks_insert_attrib(iq, "type", "set");
01518    iks_insert_attrib(iq, "to", p->them);
01519    iks_insert_attrib(iq, "from", p->us);
01520    iks_insert_attrib(iq, "id", client->connection->mid);
01521    ast_aji_increment_mid(client->connection->mid);
01522    iks_insert_attrib(gtalk, "xmlns", "http://jabber.org/protocol/gtalk");
01523    iks_insert_attrib(gtalk, "action", "session-info");
01524    iks_insert_attrib(gtalk, "initiator", p->initiator ? p->us: p->them);
01525    iks_insert_attrib(gtalk, "sid", p->sid);
01526    iks_insert_attrib(dtmf, "xmlns", "http://jabber.org/protocol/gtalk/info/dtmf");
01527    iks_insert_attrib(dtmf, "code", buffer);
01528    iks_insert_node(iq, gtalk);
01529    iks_insert_node(gtalk, dtmf);
01530 
01531    ast_mutex_lock(&p->lock);
01532    if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
01533       iks_insert_attrib(dtmf, "action", "button-down");
01534    } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
01535       iks_insert_attrib(dtmf, "action", "button-up");
01536    }
01537    iks_send(client->connection->p, iq);
01538    iks_delete(iq);
01539    iks_delete(gtalk);
01540    iks_delete(dtmf);
01541    ast_mutex_unlock(&p->lock);
01542    return 0;
01543 }

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

Definition at line 1487 of file chan_gtalk.c.

References gtalk_digit().

01488 {
01489    return gtalk_digit(chan, digit, 0);
01490 }

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

Definition at line 1492 of file chan_gtalk.c.

References gtalk_digit().

01493 {
01494    return gtalk_digit(chan, digit, duration);
01495 }

static int gtalk_do_reload ( int  fd,
int  argc,
char **  argv 
) [static]

CLI command "gtalk show channels".

Definition at line 1715 of file chan_gtalk.c.

References ast_verbose(), and RESULT_SUCCESS.

01716 {
01717    ast_verbose("IT DOES WORK!\n");
01718    return RESULT_SUCCESS;
01719 }

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

Definition at line 1453 of file chan_gtalk.c.

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

01454 {
01455    struct gtalk_pvt *p = newchan->tech_pvt;
01456    ast_mutex_lock(&p->lock);
01457 
01458    if ((p->owner != oldchan)) {
01459       ast_mutex_unlock(&p->lock);
01460       return -1;
01461    }
01462    if (p->owner == oldchan)
01463       p->owner = newchan;
01464    ast_mutex_unlock(&p->lock);
01465    return 0;
01466 }

static void gtalk_free_candidates ( struct gtalk_candidate candidate  )  [static]

Definition at line 1101 of file chan_gtalk.c.

References free, last, and gtalk_candidate::next.

Referenced by gtalk_free_pvt().

01102 {
01103    struct gtalk_candidate *last;
01104    while (candidate) {
01105       last = candidate;
01106       candidate = candidate->next;
01107       free(last);
01108    }
01109 }

static void gtalk_free_pvt ( struct gtalk client,
struct gtalk_pvt p 
) [static]

Definition at line 1111 of file chan_gtalk.c.

References ast_log(), ast_rtp_destroy(), gtalk::connection, aji_client::f, free, gtalk_free_candidates(), LOG_WARNING, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, gtalk_pvt::parent, gtalk_pvt::ringrule, gtalk_pvt::rtp, gtalk_pvt::theircandidates, and gtalk_pvt::vrtp.

Referenced by gtalk_hangup(), and gtalk_newcall().

01112 {
01113    struct gtalk_pvt *cur, *prev = NULL;
01114    cur = client->p;
01115    while (cur) {
01116       if (cur == p) {
01117          if (prev)
01118             prev->next = p->next;
01119          else
01120             client->p = p->next;
01121          break;
01122       }
01123       prev = cur;
01124       cur = cur->next;
01125    }
01126    if (p->ringrule)
01127       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
01128    if (p->owner)
01129       ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
01130    if (p->rtp)
01131       ast_rtp_destroy(p->rtp);
01132    if (p->vrtp)
01133       ast_rtp_destroy(p->vrtp);
01134    gtalk_free_candidates(p->theircandidates);
01135    free(p);
01136 }

static int gtalk_get_codec ( struct ast_channel chan  )  [static]

Definition at line 560 of file chan_gtalk.c.

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

00561 {
00562    struct gtalk_pvt *p = chan->tech_pvt;
00563    return p->peercapability;
00564 }

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

Definition at line 542 of file chan_gtalk.c.

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

00543 {
00544    struct gtalk_pvt *p = chan->tech_pvt;
00545    enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
00546 
00547    if (!p)
00548       return res;
00549 
00550    ast_mutex_lock(&p->lock);
00551    if (p->rtp){
00552       *rtp = p->rtp;
00553       res = AST_RTP_TRY_PARTIAL;
00554    }
00555    ast_mutex_unlock(&p->lock);
00556 
00557    return res;
00558 }

static int gtalk_handle_dtmf ( struct gtalk client,
ikspak *  pak 
) [static]

Definition at line 695 of file chan_gtalk.c.

References AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), ast_verbose(), gtalk::connection, f, gtalk_response(), aji_client::jid, LOG_NOTICE, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, and gtalk_pvt::sid.

Referenced by gtalk_parser().

00696 {
00697    struct gtalk_pvt *tmp;
00698    iks *dtmfnode = NULL, *dtmfchild = NULL;
00699    char *dtmf;
00700    char *from;
00701    /* Make sure our new call doesn't exist yet */
00702    for (tmp = client->p; tmp; tmp = tmp->next) {
00703       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || iks_find_with_attrib(pak->x, "gtalk", "sid", tmp->sid))
00704          break;
00705    }
00706    from = iks_find_attrib(pak->x, "to");
00707    if(!from)
00708       from = client->connection->jid->full;
00709 
00710 
00711    if (tmp) {
00712       if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) {
00713          gtalk_response(client, from, pak,
00714                "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
00715                "unsupported-dtmf-method xmlns='http://jabber.org/protocol/gtalk/info/dtmf#errors'");
00716          return -1;
00717       }
00718       if ((dtmfnode = iks_find(pak->x, "dtmf"))) {
00719          if((dtmf = iks_find_attrib(dtmfnode, "code"))) {
00720             if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) {
00721                struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00722                f.subclass = dtmf[0];
00723                ast_queue_frame(tmp->owner, &f);
00724                ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00725             } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) {
00726                struct ast_frame f = {AST_FRAME_DTMF_END, };
00727                f.subclass = dtmf[0];
00728                ast_queue_frame(tmp->owner, &f);
00729                ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00730             } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */
00731                struct ast_frame f = {AST_FRAME_DTMF, };
00732                f.subclass = dtmf[0];
00733                ast_queue_frame(tmp->owner, &f);
00734                ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00735             }
00736          }
00737       } else if ((dtmfnode = iks_find_with_attrib(pak->x, "gtalk", "action", "session-info"))) {
00738          if((dtmfchild = iks_find(dtmfnode, "dtmf"))) {
00739             if((dtmf = iks_find_attrib(dtmfchild, "code"))) {
00740                if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) {
00741                   struct ast_frame f = {AST_FRAME_DTMF_END, };
00742                   f.subclass = dtmf[0];
00743                   ast_queue_frame(tmp->owner, &f);
00744                   ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00745                } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) {
00746                   struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00747                   f.subclass = dtmf[0];
00748                   ast_queue_frame(tmp->owner, &f);
00749                   ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00750                }
00751             }
00752          }
00753       }
00754       gtalk_response(client, from, pak, NULL, NULL);
00755       return 1;
00756    } else
00757       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00758 
00759    gtalk_response(client, from, pak, NULL, NULL);
00760    return 1;
00761 }

static int gtalk_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the gtalk proxy channel.

Definition at line 1596 of file chan_gtalk.c.

References gtalk_pvt::alreadygone, ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), gtalk_action(), gtalk_free_pvt(), gtalk_pvt::lock, gtalk_pvt::owner, gtalk::p, gtalk_pvt::parent, and ast_channel::tech_pvt.

Referenced by gtalk_newcall().

01597 {
01598    struct gtalk_pvt *p = ast->tech_pvt;
01599    struct gtalk *client;
01600 
01601    ast_mutex_lock(&p->lock);
01602    client = p->parent;
01603    p->owner = NULL;
01604    ast->tech_pvt = NULL;
01605    if (!p->alreadygone)
01606       gtalk_action(client, p, "terminate");
01607    ast_mutex_unlock(&p->lock);
01608 
01609    gtalk_free_pvt(client, p);
01610    ast_module_unref(ast_module_info->self);
01611 
01612    return 0;
01613 }

static int gtalk_hangup_farend ( struct gtalk client,
ikspak *  pak 
) [static]

Definition at line 763 of file chan_gtalk.c.

References gtalk_pvt::alreadygone, ast_log(), ast_queue_hangup(), gtalk::connection, gtalk_response(), aji_client::jid, LOG_DEBUG, LOG_NOTICE, gtalk::name, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, and gtalk_pvt::sid.

Referenced by gtalk_parser().

00764 {
00765    struct gtalk_pvt *tmp;
00766    char *from;
00767 
00768    ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00769    /* Make sure our new call doesn't exist yet */
00770    for (tmp = client->p; tmp; tmp = tmp->next) {
00771       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00772          break;
00773    }
00774    from = iks_find_attrib(pak->x, "to");
00775    if(!from)
00776       from = client->connection->jid->full;
00777 
00778    if (tmp) {
00779       tmp->alreadygone = 1;
00780       if (tmp->owner)
00781          ast_queue_hangup(tmp->owner);
00782    } else
00783       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00784    gtalk_response(client, from, pak, NULL, NULL);
00785    return 1;
00786 }

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

Definition at line 1468 of file chan_gtalk.c.

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

01469 {
01470    int res = 0;
01471 
01472    switch (condition) {
01473    case AST_CONTROL_HOLD:
01474       ast_moh_start(ast, data, NULL);
01475       break;
01476    case AST_CONTROL_UNHOLD:
01477       ast_moh_stop(ast);
01478       break;
01479    default:
01480       ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01481       res = -1;
01482    }
01483 
01484    return res;
01485 }

static int gtalk_invite ( struct gtalk_pvt p,
char *  to,
char *  from,
char *  sid,
int  initiator 
) [static]

Definition at line 406 of file chan_gtalk.c.

References add_codec_to_answer(), ast_aji_increment_mid(), ast_codec_pref_index(), ast_log(), gtalk::capability, gtalk::connection, LOG_ERROR, aji_client::mid, aji_client::p, gtalk::p, gtalk_pvt::parent, and gtalk::prefs.

Referenced by gtalk_answer(), and gtalk_call().

00407 {
00408    struct gtalk *client = p->parent;
00409    iks *iq, *gtalk, *dcodecs, *payload_telephone, *transport;
00410    int x;
00411    int pref_codec = 0;
00412    int alreadysent = 0;
00413    int codecs_num = 0;
00414 
00415    iq = iks_new("iq");
00416    gtalk = iks_new("session");
00417    dcodecs = iks_new("description");
00418    transport = iks_new("transport");
00419    payload_telephone = iks_new("payload-type");
00420    if (!(iq && gtalk && dcodecs && transport && payload_telephone)){
00421       if(iq)
00422          iks_delete(iq);
00423       if(gtalk)
00424          iks_delete(gtalk);
00425       if(dcodecs)
00426          iks_delete(dcodecs);
00427       if(transport)
00428          iks_delete(transport);
00429       if(payload_telephone)
00430          iks_delete(payload_telephone);
00431 
00432       ast_log(LOG_ERROR, "Could not allocate iksemel nodes\n");
00433       return 0;
00434    }
00435    iks_insert_attrib(dcodecs, "xmlns", "http://www.google.com/session/phone");
00436    iks_insert_attrib(dcodecs, "xml:lang", "en");
00437 
00438    for (x = 0; x < 32; x++) {
00439       if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
00440          break;
00441       if (!(client->capability & pref_codec))
00442          continue;
00443       if (alreadysent & pref_codec)
00444          continue;
00445       codecs_num = add_codec_to_answer(p, pref_codec, dcodecs);
00446       alreadysent |= pref_codec;
00447    }
00448    
00449    if (codecs_num) {
00450       /* only propose DTMF within an audio session */
00451       iks_insert_attrib(payload_telephone, "id", "106");
00452       iks_insert_attrib(payload_telephone, "name", "telephone-event");
00453       iks_insert_attrib(payload_telephone, "clockrate", "8000");
00454    }
00455    iks_insert_attrib(transport,"xmlns","http://www.google.com/transport/p2p");
00456    
00457    iks_insert_attrib(iq, "type", "set");
00458    iks_insert_attrib(iq, "to", to);
00459    iks_insert_attrib(iq, "from", from);
00460    iks_insert_attrib(iq, "id", client->connection->mid);
00461    ast_aji_increment_mid(client->connection->mid);
00462 
00463    iks_insert_attrib(gtalk, "xmlns", "http://www.google.com/session");
00464    iks_insert_attrib(gtalk, "type",initiator ? "initiate": "accept");
00465    iks_insert_attrib(gtalk, "initiator", initiator ? from : to);
00466    iks_insert_attrib(gtalk, "id", sid);
00467    iks_insert_node(iq, gtalk);
00468    iks_insert_node(gtalk, dcodecs);
00469    iks_insert_node(gtalk, transport);
00470    iks_insert_node(dcodecs, payload_telephone);
00471 
00472    iks_send(client->connection->p, iq);
00473    iks_delete(payload_telephone);
00474    iks_delete(transport);
00475    iks_delete(dcodecs);
00476    iks_delete(gtalk);
00477    iks_delete(iq);
00478    return 1;
00479 }

static int gtalk_invite_response ( struct gtalk_pvt p,
char *  to,
char *  from,
char *  sid,
int  initiator 
) [static]

Definition at line 481 of file chan_gtalk.c.

References ast_aji_increment_mid(), ast_log(), gtalk::connection, LOG_ERROR, aji_client::mid, aji_client::p, gtalk::p, and gtalk_pvt::parent.

Referenced by gtalk_newcall().

00482 {
00483    iks *iq, *session, *transport;
00484    iq = iks_new("iq");
00485    session = iks_new("session");
00486    transport = iks_new("transport");
00487    if(!(iq && session && transport)) {
00488       if(iq)
00489          iks_delete(iq);
00490       if(session)
00491          iks_delete(session);
00492       if(transport)
00493          iks_delete(transport);
00494       ast_log(LOG_ERROR, " Unable to allocate IKS node\n");
00495       return -1;
00496    }
00497    iks_insert_attrib(iq, "from", from);
00498    iks_insert_attrib(iq, "to", to);
00499    iks_insert_attrib(iq, "type", "set");
00500    iks_insert_attrib(iq, "id",p->parent->connection->mid);
00501    ast_aji_increment_mid(p->parent->connection->mid);
00502    iks_insert_attrib(session, "type", "transport-accept");
00503    iks_insert_attrib(session, "id", sid);
00504    iks_insert_attrib(session, "initiator", initiator ? from : to);
00505    iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
00506    iks_insert_attrib(transport, "xmlns", "http://www.google.com/transport/p2p");
00507    iks_insert_node(iq,session);
00508    iks_insert_node(session,transport);
00509    iks_send(p->parent->connection->p, iq);
00510    iks_delete(transport);
00511    iks_delete(session);
00512    iks_delete(iq);
00513    return 1;
00514 
00515 }

static int gtalk_is_accepted ( struct gtalk client,
ikspak *  pak 
) [static]

Definition at line 671 of file chan_gtalk.c.

References ast_log(), gtalk::connection, gtalk_response(), aji_client::jid, LOG_DEBUG, LOG_NOTICE, gtalk::name, gtalk_pvt::next, gtalk::p, and gtalk_pvt::sid.

Referenced by gtalk_parser().

00672 {
00673    struct gtalk_pvt *tmp;
00674    char *from;
00675 
00676    ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00677    /* find corresponding call */
00678    for (tmp = client->p; tmp; tmp = tmp->next) {
00679       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00680          break;
00681    }
00682 
00683    from = iks_find_attrib(pak->x, "to");
00684    if(!from)
00685       from = client->connection->jid->full;
00686 
00687    if (!tmp)
00688       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00689 
00690    /* answer 'iq' packet to let the remote peer know that we're alive */
00691    gtalk_response(client, from, pak, NULL, NULL);
00692    return 1;
00693 }

static int gtalk_is_answered ( struct gtalk client,
ikspak *  pak 
) [static]

Definition at line 618 of file chan_gtalk.c.

References AST_CONTROL_ANSWER, ast_getformatname_multiple(), ast_log(), ast_queue_control(), ast_queue_hangup(), ast_rtp_get_current_formats(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), gtalk_pvt::capability, gtalk::connection, gtalk_response(), aji_client::jid, gtalk_pvt::jointcapability, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, gtalk::name, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, gtalk_pvt::peercapability, gtalk_pvt::rtp, and gtalk_pvt::sid.

Referenced by gtalk_parser().

00619 {
00620    struct gtalk_pvt *tmp;
00621    char *from;
00622    iks *codec;
00623    char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ];
00624    int peernoncodeccapability;
00625 
00626    ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00627    /* Make sure our new call doesn't exist yet */
00628    for (tmp = client->p; tmp; tmp = tmp->next) {
00629       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00630          break;
00631    }
00632 
00633    /* codec points to the first <payload-type/> tag */
00634    codec = iks_child(iks_child(iks_child(pak->x)));
00635    while (codec) {
00636       ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")));
00637       ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
00638       codec = iks_next(codec);
00639    }
00640    
00641    /* Now gather all of the codecs that we are asked for */
00642    ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability);
00643    
00644    /* at this point, we received an awser from the remote Gtalk client,
00645       which allows us to compare capabilities */
00646    tmp->jointcapability = tmp->capability & tmp->peercapability;
00647    if (!tmp->jointcapability) {
00648       ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->capability),
00649          ast_getformatname_multiple(s2, BUFSIZ, tmp->peercapability),
00650          ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcapability));
00651       /* close session if capabilities don't match */
00652       ast_queue_hangup(tmp->owner);
00653 
00654       return -1;
00655 
00656    }  
00657    
00658    from = iks_find_attrib(pak->x, "to");
00659    if(!from)
00660       from = client->connection->jid->full;
00661 
00662    if (tmp) {
00663       if (tmp->owner)
00664          ast_queue_control(tmp->owner, AST_CONTROL_ANSWER);
00665    } else
00666       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00667    gtalk_response(client, from, pak, NULL, NULL);
00668    return 1;
00669 }

static int gtalk_load_config ( void   )  [static]

Definition at line 1856 of file chan_gtalk.c.

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

Referenced by load_module().

01857 {
01858    char *cat = NULL;
01859    struct ast_config *cfg = NULL;
01860    char context[AST_MAX_CONTEXT];
01861    int allowguest = 1;
01862    struct ast_variable *var;
01863    struct gtalk *member;
01864    struct ast_codec_pref prefs;
01865    struct aji_client_container *clients;
01866    struct gtalk_candidate *global_candidates = NULL;
01867    struct hostent *hp;
01868    struct ast_hostent ahp;
01869 
01870    cfg = ast_config_load(GOOGLE_CONFIG);
01871    if (!cfg)
01872       return 0;
01873 
01874    /* Copy the default jb config over global_jbconf */
01875    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01876 
01877    cat = ast_category_browse(cfg, NULL);
01878    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
01879       /* handle jb conf */
01880       if (!ast_jb_read_conf(&global_jbconf, var->name, var->value))
01881          continue;
01882 
01883       if (!strcasecmp(var->name, "allowguest"))
01884          allowguest =
01885             (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
01886       else if (!strcasecmp(var->name, "disallow"))
01887          ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0);
01888       else if (!strcasecmp(var->name, "allow"))
01889          ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
01890       else if (!strcasecmp(var->name, "context"))
01891          ast_copy_string(context, var->value, sizeof(context));
01892       else if (!strcasecmp(var->name, "bindaddr")) {
01893          if (!(hp = ast_gethostbyname(var->value, &ahp))) {
01894             ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
01895          } else {
01896             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
01897          }
01898       }
01899 /*  Idea to allow for custom candidates  */
01900 /*
01901       else if (!strcasecmp(var->name, "candidate")) {
01902          candidate = gtalk_create_candidate(var->value);
01903          if (candidate) {
01904             candidate->next = global_candidates;
01905             global_candidates = candidate;
01906          }
01907       }
01908 */
01909    }
01910    while (cat) {
01911       if (strcasecmp(cat, "general")) {
01912          var = ast_variable_browse(cfg, cat);
01913          member = (struct gtalk *) malloc(sizeof(struct gtalk));
01914          memset(member, 0, sizeof(struct gtalk));
01915          ASTOBJ_INIT(member);
01916          ASTOBJ_WRLOCK(member);
01917          if (!strcasecmp(cat, "guest")) {
01918             ast_copy_string(member->name, "guest", sizeof(member->name));
01919             ast_copy_string(member->user, "guest", sizeof(member->user));
01920             ast_copy_string(member->context, context, sizeof(member->context));
01921             member->allowguest = allowguest;
01922             member->prefs = prefs;
01923             while (var) {
01924                if (!strcasecmp(var->name, "disallow"))
01925                   ast_parse_allow_disallow(&member->prefs, &member->capability,
01926                                      var->value, 0);
01927                else if (!strcasecmp(var->name, "allow"))
01928                   ast_parse_allow_disallow(&member->prefs, &member->capability,
01929                                      var->value, 1);
01930                else if (!strcasecmp(var->name, "context"))
01931                   ast_copy_string(member->context, var->value,
01932                               sizeof(member->context));
01933 /*  Idea to allow for custom candidates  */
01934 /*
01935                else if (!strcasecmp(var->name, "candidate")) {
01936                   candidate = gtalk_create_candidate(var->value);
01937                   if (candidate) {
01938                      candidate->next = member->ourcandidates;
01939                      member->ourcandidates = candidate;
01940                   }
01941                }
01942 */
01943                var = var->next;
01944             }
01945             ASTOBJ_UNLOCK(member);
01946             clients = ast_aji_get_clients();
01947             if (clients) {
01948                ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
01949                   ASTOBJ_WRLOCK(iterator);
01950                   ASTOBJ_WRLOCK(member);
01951                   member->connection = NULL;
01952                   iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://www.google.com/session", IKS_RULE_DONE);
01953                   iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://jabber.org/protocol/gtalk", IKS_RULE_DONE);
01954                   ASTOBJ_UNLOCK(member);
01955                   ASTOBJ_UNLOCK(iterator);
01956                });
01957                ASTOBJ_CONTAINER_LINK(&gtalk_list, member);
01958                ASTOBJ_UNREF(member, gtalk_member_destroy);
01959             } else {
01960                ASTOBJ_UNLOCK(member);
01961                ASTOBJ_UNREF(member, gtalk_member_destroy);
01962             }
01963          } else {
01964             ASTOBJ_UNLOCK(member);
01965             if (gtalk_create_member(cat, var, allowguest, prefs, context, member))
01966                ASTOBJ_CONTAINER_LINK(&gtalk_list, member);
01967             ASTOBJ_UNREF(member, gtalk_member_destroy);
01968          }
01969       }
01970       cat = ast_category_browse(cfg, cat);
01971    }
01972    gtalk_free_candidates(global_candidates);
01973    return 1;
01974 }

static void gtalk_member_destroy ( struct gtalk obj  )  [static]

Definition at line 260 of file chan_gtalk.c.

References free.

Referenced by gtalk_parser(), gtalk_request(), and unload_module().

00261 {
00262    free(obj);
00263 }

static struct ast_channel* gtalk_new ( struct gtalk client,
struct gtalk_pvt i,
int  state,
const char *  title 
) [static]

Start new gtalk channel.

Definition at line 994 of file chan_gtalk.c.

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

Referenced by gtalk_newcall(), and gtalk_request().

00995 {
00996    struct ast_channel *tmp;
00997    int fmt;
00998    int what;
00999    const char *n2;
01000 
01001    if (title)
01002       n2 = title;
01003    else
01004       n2 = i->us;
01005    tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, client->accountcode, i->exten, client->context, client->amaflags, "Gtalk/%s-%04lx", n2, ast_random() & 0xffff);
01006    if (!tmp) {
01007       ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n");
01008       return NULL;
01009    }
01010    tmp->tech = &gtalk_tech;
01011 
01012    /* Select our native format based on codec preference until we receive
01013       something from another device to the contrary. */
01014    if (i->jointcapability)
01015       what = i->jointcapability;
01016    else if (i->capability)
01017       what = i->capability;
01018    else
01019       what = global_capability;
01020    tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
01021    fmt = ast_best_codec(tmp->nativeformats);
01022 
01023    if (i->rtp) {
01024       ast_rtp_setstun(i->rtp, 1);
01025       tmp->fds[0] = ast_rtp_fd(i->rtp);
01026       tmp->fds[1] = ast_rtcp_fd(i->rtp);
01027    }
01028    if (i->vrtp) {
01029       ast_rtp_setstun(i->rtp, 1);
01030       tmp->fds[2] = ast_rtp_fd(i->vrtp);
01031       tmp->fds[3] = ast_rtcp_fd(i->vrtp);
01032    }
01033    if (state == AST_STATE_RING)
01034       tmp->rings = 1;
01035    tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01036    tmp->writeformat = fmt;
01037    tmp->rawwriteformat = fmt;
01038    tmp->readformat = fmt;
01039    tmp->rawreadformat = fmt;
01040    tmp->tech_pvt = i;
01041 
01042    tmp->callgroup = client->callgroup;
01043    tmp->pickupgroup = client->pickupgroup;
01044    tmp->cid.cid_pres = client->callingpres;
01045    if (!ast_strlen_zero(client->accountcode))
01046       ast_string_field_set(tmp, accountcode, client->accountcode);
01047    if (client->amaflags)
01048       tmp->amaflags = client->amaflags;
01049    if (!ast_strlen_zero(client->language))
01050       ast_string_field_set(tmp, language, client->language);
01051    if (!ast_strlen_zero(client->musicclass))
01052       ast_string_field_set(tmp, musicclass, client->musicclass);
01053    i->owner = tmp;
01054    ast_module_ref(ast_module_info->self);
01055    ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
01056    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01057 
01058    if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
01059       tmp->cid.cid_dnid = ast_strdup(i->exten);
01060    tmp->priority = 1;
01061    if (i->rtp)
01062       ast_jb_configure(tmp, &global_jbconf);
01063    if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
01064       ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01065       tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
01066       ast_hangup(tmp);
01067       tmp = NULL;
01068    }
01069 
01070    return tmp;
01071 }

static int gtalk_newcall ( struct gtalk client,
ikspak *  pak 
) [static]

Definition at line 1139 of file chan_gtalk.c.

References gtalk_pvt::alreadygone, ast_aji_get_client(), ast_channel_free(), ast_copy_string(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_rtp_get_current_formats(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, gtalk_pvt::capability, gtalk::connection, gtalk_action(), gtalk_alloc(), gtalk_create_candidates(), gtalk_free_pvt(), gtalk_hangup(), gtalk_invite_response(), gtalk_new(), gtalk_response(), aji_client::jid, gtalk_pvt::jointcapability, gtalk_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, gtalk::name, gtalk_pvt::next, gtalk::p, gtalk_pvt::peercapability, gtalk_pvt::rtp, gtalk_pvt::sid, gtalk_pvt::them, and gtalk_pvt::us.

Referenced by gtalk_parser().

01140 {
01141    struct gtalk_pvt *p, *tmp = client->p;
01142    struct ast_channel *chan;
01143    int res;
01144    iks *codec;
01145    char *from = NULL;
01146    char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ];
01147    int peernoncodeccapability;
01148 
01149    /* Make sure our new call doesn't exist yet */
01150    from = iks_find_attrib(pak->x,"to");
01151    if(!from)
01152       from = client->connection->jid->full;
01153    
01154    while (tmp) {
01155       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) {
01156          ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
01157          gtalk_response(client, from, pak, "out-of-order", NULL);
01158          return -1;
01159       }
01160       tmp = tmp->next;
01161    }
01162 
01163    if (!strcasecmp(client->name, "guest")){
01164       /* the guest account is not tied to any configured XMPP client,
01165          let's set it now */
01166       client->connection = ast_aji_get_client(from);
01167       if (!client->connection) {
01168          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from);
01169          return -1;
01170       }
01171    }
01172 
01173    p = gtalk_alloc(client, from, pak->from->full, iks_find_attrib(pak->query, "id"));
01174    if (!p) {
01175       ast_log(LOG_WARNING, "Unable to allocate gtalk structure!\n");
01176       return -1;
01177    }
01178 
01179    chan = gtalk_new(client, p, AST_STATE_DOWN, pak->from->user);
01180    if (!chan) {
01181       gtalk_free_pvt(client, p);
01182       return -1;
01183    }
01184 
01185    ast_mutex_lock(&p->lock);
01186    ast_copy_string(p->them, pak->from->full, sizeof(p->them));
01187    if (iks_find_attrib(pak->query, "id")) {
01188       ast_copy_string(p->sid, iks_find_attrib(pak->query, "id"),
01189             sizeof(p->sid));
01190    }
01191 
01192    /* codec points to the first <payload-type/> tag */   
01193    codec = iks_child(iks_child(iks_child(pak->x)));
01194    
01195    while (codec) {
01196       ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
01197       ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
01198       codec = iks_next(codec);
01199    }
01200    
01201    /* Now gather all of the codecs that we are asked for */
01202    ast_rtp_get_current_formats(p->rtp, &p->peercapability, &peernoncodeccapability);
01203    p->jointcapability = p->capability & p->peercapability;
01204    ast_mutex_unlock(&p->lock);
01205       
01206    ast_setstate(chan, AST_STATE_RING);
01207    if (!p->jointcapability) {
01208       ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->capability),
01209          ast_getformatname_multiple(s2, BUFSIZ, p->peercapability),
01210          ast_getformatname_multiple(s3, BUFSIZ, p->jointcapability));
01211       /* close session if capabilities don't match */
01212       gtalk_action(client, p, "reject");
01213       p->alreadygone = 1;
01214       gtalk_hangup(chan);
01215       ast_channel_free(chan);
01216       return -1;
01217    }  
01218 
01219    res = ast_pbx_start(chan);
01220    
01221    switch (res) {
01222    case AST_PBX_FAILED:
01223       ast_log(LOG_WARNING, "Failed to start PBX :(\n");
01224       gtalk_response(client, from, pak, "service-unavailable", NULL);
01225       break;
01226    case AST_PBX_CALL_LIMIT:
01227       ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
01228       gtalk_response(client, from, pak, "service-unavailable", NULL);
01229       break;
01230    case AST_PBX_SUCCESS:
01231       gtalk_response(client, from, pak, NULL, NULL);
01232       gtalk_invite_response(p, p->them, p->us,p->sid, 0);
01233       gtalk_create_candidates(client, p, p->sid, p->them, p->us);
01234       /* nothing to do */
01235       break;
01236    }
01237 
01238    return 1;
01239 }

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

Definition at line 1721 of file chan_gtalk.c.

References ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, gtalk_add_candidate(), gtalk_handle_dtmf(), gtalk_hangup_farend(), gtalk_is_accepted(), gtalk_is_answered(), gtalk_member_destroy(), gtalk_newcall(), LOG_DEBUG, and option_debug.

Referenced by gtalk_create_member().

01722 {
01723    struct gtalk *client = ASTOBJ_REF((struct gtalk *) data);
01724 
01725    if (iks_find_with_attrib(pak->x, "session", "type", "initiate")) {
01726       /* New call */
01727       gtalk_newcall(client, pak);
01728    } else if (iks_find_with_attrib(pak->x, "session", "type", "candidates") || iks_find_with_attrib(pak->x, "session", "type", "transport-info")) {
01729       if (option_debug > 2)
01730          ast_log(LOG_DEBUG, "About to add candidate!\n");
01731       gtalk_add_candidate(client, pak);
01732       if (option_debug > 2)
01733          ast_log(LOG_DEBUG, "Candidate Added!\n");
01734    } else if (iks_find_with_attrib(pak->x, "session", "type", "accept")) {
01735       gtalk_is_answered(client, pak);
01736    } else if (iks_find_with_attrib(pak->x, "session", "type", "transport-accept")) {
01737       gtalk_is_accepted(client, pak);
01738    } else if (iks_find_with_attrib(pak->x, "session", "type", "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) {
01739       gtalk_handle_dtmf(client, pak);
01740    } else if (iks_find_with_attrib(pak->x, "session", "type", "terminate")) {
01741       gtalk_hangup_farend(client, pak);
01742    } else if (iks_find_with_attrib(pak->x, "session", "type", "reject")) {
01743       gtalk_hangup_farend(client, pak);
01744    }
01745    ASTOBJ_UNREF(client, gtalk_member_destroy);
01746    return IKS_FILTER_EAT;
01747 }

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

Definition at line 1398 of file chan_gtalk.c.

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

01399 {
01400    struct ast_frame *fr;
01401    struct gtalk_pvt *p = ast->tech_pvt;
01402 
01403    ast_mutex_lock(&p->lock);
01404    fr = gtalk_rtp_read(ast, p);
01405    ast_mutex_unlock(&p->lock);
01406    return fr;
01407 }

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

Part of PBX interface.

Definition at line 1616 of file chan_gtalk.c.

References ast_aji_get_client(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, gtalk::connection, find_gtalk(), gtalk_alloc(), gtalk_member_destroy(), gtalk_new(), aji_client::jid, LOG_ERROR, LOG_WARNING, gtalk::name, s, and gtalk::user.

01617 {
01618    struct gtalk_pvt *p = NULL;
01619    struct gtalk *client = NULL;
01620    char *sender = NULL, *to = NULL, *s = NULL;
01621    struct ast_channel *chan = NULL;
01622 
01623    if (data) {
01624       s = ast_strdupa(data);
01625       if (s) {
01626          sender = strsep(&s, "/");
01627          if (sender && (sender[0] != '\0'))
01628             to = strsep(&s, "/");
01629          if (!to) {
01630             ast_log(LOG_ERROR, "Bad arguments in Gtalk Dialstring: %s\n", (char*) data);
01631             return NULL;
01632          }
01633       }
01634    }
01635 
01636    client = find_gtalk(to, sender);
01637    if (!client) {
01638       ast_log(LOG_WARNING, "Could not find recipient.\n");
01639       return NULL;
01640    }
01641    if (!strcasecmp(client->name, "guest")){
01642       /* the guest account is not tied to any configured XMPP client,
01643          let's set it now */
01644       client->connection = ast_aji_get_client(sender);
01645       if (!client->connection) {
01646          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01647          ASTOBJ_UNREF(client, gtalk_member_destroy);
01648          return NULL;
01649       }
01650    }
01651 
01652    ASTOBJ_WRLOCK(client);
01653    p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL);
01654    if (p)
01655       chan = gtalk_new(client, p, AST_STATE_DOWN, to);
01656 
01657    ASTOBJ_UNLOCK(client);
01658    return chan;
01659 }

static int gtalk_response ( struct gtalk client,
char *  from,
ikspak *  pak,
const char *  reasonstr,
const char *  reasonstr2 
) [static]

Definition at line 586 of file chan_gtalk.c.

References gtalk::connection, and aji_client::p.

Referenced by gtalk_handle_dtmf(), gtalk_hangup_farend(), gtalk_is_accepted(), gtalk_is_answered(), and gtalk_newcall().

00587 {
00588    iks *response = NULL, *error = NULL, *reason = NULL;
00589    int res = -1;
00590 
00591    response = iks_new("iq");
00592    if (response) {
00593       iks_insert_attrib(response, "type", "result");
00594       iks_insert_attrib(response, "from", from);
00595       iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
00596       iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
00597       if (reasonstr) {
00598          error = iks_new("error");
00599          if (error) {
00600             iks_insert_attrib(error, "type", "cancel");
00601             reason = iks_new(reasonstr);
00602             if (reason)
00603                iks_insert_node(error, reason);
00604             iks_insert_node(response, error);
00605          }
00606       }
00607       iks_send(client->connection->p, response);
00608       if (reason)
00609          iks_delete(reason);
00610       if (error)
00611          iks_delete(error);
00612       iks_delete(response);
00613       res = 0;
00614    }
00615    return res;
00616 }

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

Definition at line 517 of file chan_gtalk.c.

References AST_CONTROL_RINGING, ast_queue_control(), gtalk::connection, aji_client::f, gtalk_pvt::owner, gtalk_pvt::parent, and gtalk_pvt::ringrule.

Referenced by gtalk_call().

00518 {
00519    struct gtalk_pvt *p = data;
00520 
00521    if (p->ringrule)
00522       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00523    p->ringrule = NULL;
00524    if (p->owner)
00525       ast_queue_control(p->owner, AST_CONTROL_RINGING);
00526    return IKS_FILTER_EAT;
00527 }

static struct ast_frame* gtalk_rtp_read ( struct ast_channel ast,
struct gtalk_pvt p 
) [static]

Definition at line 1369 of file chan_gtalk.c.

References AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_VOICE, ast_log(), ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), f, gtalk_update_stun(), LOG_DEBUG, ast_channel::nativeformats, option_debug, gtalk_pvt::owner, gtalk_pvt::parent, ast_channel::readformat, gtalk_pvt::rtp, and ast_channel::writeformat.

Referenced by gtalk_read().

01370 {
01371    struct ast_frame *f;
01372 
01373    if (!p->rtp)
01374       return &ast_null_frame;
01375    f = ast_rtp_read(p->rtp);
01376    gtalk_update_stun(p->parent, p);
01377    if (p->owner) {
01378       /* We already hold the channel lock */
01379       if (f->frametype == AST_FRAME_VOICE) {
01380          if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
01381             if (option_debug)
01382                ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
01383             p->owner->nativeformats =
01384                (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
01385             ast_set_read_format(p->owner, p->owner->readformat);
01386             ast_set_write_format(p->owner, p->owner->writeformat);
01387          }
01388 /*       if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
01389             f = ast_dsp_process(p->owner, p->vad, f);
01390             if (option_debug && f && (f->frametype == AST_FRAME_DTMF))
01391                ast_log(LOG_DEBUG, "* Detected inband DTMF '%c'\n", f->subclass);
01392               } */
01393       }
01394    }
01395    return f;
01396 }

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

Definition at line 1545 of file chan_gtalk.c.

References ast_log(), and LOG_NOTICE.

01546 {
01547    ast_log(LOG_NOTICE, "XXX Implement gtalk sendhtml XXX\n");
01548 
01549    return -1;
01550 }

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

Definition at line 566 of file chan_gtalk.c.

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

00567 {
00568    struct gtalk_pvt *p;
00569 
00570    p = chan->tech_pvt;
00571    if (!p)
00572       return -1;
00573    ast_mutex_lock(&p->lock);
00574 
00575 /* if (rtp)
00576       ast_rtp_get_peer(rtp, &p->redirip);
00577    else
00578       memset(&p->redirip, 0, sizeof(p->redirip));
00579    p->redircodecs = codecs; */
00580 
00581    /* Reset lastrtprx timer */
00582    ast_mutex_unlock(&p->lock);
00583    return 0;
00584 }

static int gtalk_show_channels ( int  fd,
int  argc,
char **  argv 
) [static]

CLI command "gtalk show channels".

Definition at line 1662 of file chan_gtalk.c.

References AJI_MAX_JIDLEN, ast_cli(), ast_copy_string(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, FORMAT, gtalk_list, gtalklock, LOG_WARNING, ast_channel::name, gtalk_pvt::next, gtalk_pvt::owner, ast_channel::readformat, RESULT_SHOWUSAGE, RESULT_SUCCESS, gtalk_pvt::them, and ast_channel::writeformat.

01663 {
01664 #define FORMAT  "%-30.30s  %-30.30s  %-15.15s  %-5.5s %-5.5s \n"
01665    struct gtalk_pvt *p;
01666    struct ast_channel *chan;
01667    int numchans = 0;
01668    char them[AJI_MAX_JIDLEN];
01669    char *jid = NULL;
01670    char *resource = NULL;
01671 
01672    if (argc != 3)
01673       return RESULT_SHOWUSAGE;
01674 
01675    ast_mutex_lock(&gtalklock);
01676    ast_cli(fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
01677    ASTOBJ_CONTAINER_TRAVERSE(&gtalk_list, 1, {
01678       ASTOBJ_WRLOCK(iterator);
01679       p = iterator->p;
01680       while(p) {
01681          chan = p->owner;
01682          ast_copy_string(them, p->them, sizeof(them));
01683          jid = them;
01684          resource = strchr(them, '/');
01685          if (!resource)
01686             resource = "None";
01687          else {
01688             *resource = '\0';
01689             resource ++;
01690          }
01691          if (chan)
01692             ast_cli(fd, FORMAT, 
01693                chan->name,
01694                jid,
01695                resource,
01696                ast_getformatname(chan->readformat),
01697                ast_getformatname(chan->writeformat)               
01698                );
01699          else 
01700             ast_log(LOG_WARNING, "No available channel\n");
01701          numchans ++;
01702          p = p->next;
01703       }
01704       ASTOBJ_UNLOCK(iterator);
01705    });
01706 
01707    ast_mutex_unlock(&gtalklock);
01708 
01709    ast_cli(fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : "");
01710    return RESULT_SUCCESS;
01711 #undef FORMAT
01712 }

static int gtalk_update_stun ( struct gtalk client,
struct gtalk_pvt p 
) [static]

Definition at line 1241 of file chan_gtalk.c.

References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_stun_request(), hp, gtalk_candidate::ip, gtalk_pvt::laststun, LOG_DEBUG, gtalk_candidate::next, option_debug, gtalk_pvt::ourcandidates, gtalk_candidate::port, gtalk_pvt::rtp, gtalk_pvt::theircandidates, gtalk_candidate::username, and username.

Referenced by gtalk_add_candidate(), and gtalk_rtp_read().

01242 {
01243    struct gtalk_candidate *tmp;
01244    struct hostent *hp;
01245    struct ast_hostent ahp;
01246    struct sockaddr_in sin;
01247    struct sockaddr_in aux;
01248 
01249    if (time(NULL) == p->laststun)
01250       return 0;
01251 
01252    tmp = p->theircandidates;
01253    p->laststun = time(NULL);
01254    while (tmp) {
01255       char username[256];
01256 
01257       /* Find the IP address of the host */
01258       hp = ast_gethostbyname(tmp->ip, &ahp);
01259       sin.sin_family = AF_INET;
01260       memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01261       sin.sin_port = htons(tmp->port);
01262       snprintf(username, sizeof(username), "%s%s", tmp->username,
01263           p->ourcandidates->username);
01264       
01265       /* Find out the result of the STUN */
01266       ast_rtp_get_peer(p->rtp, &aux);
01267 
01268       /* If the STUN result is different from the IP of the hostname,
01269          lock on the stun IP of the hostname advertised by the
01270          remote client */
01271       if (aux.sin_addr.s_addr && 
01272           aux.sin_addr.s_addr != sin.sin_addr.s_addr)
01273          ast_rtp_stun_request(p->rtp, &aux, username);
01274       else 
01275          ast_rtp_stun_request(p->rtp, &sin, username);
01276       
01277       if (aux.sin_addr.s_addr && option_debug > 3) {
01278          ast_log(LOG_DEBUG, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip);
01279          ast_log(LOG_DEBUG, "Sending STUN request to %s\n", tmp->ip);
01280       }
01281 
01282       tmp = tmp->next;
01283    }
01284    return 1;
01285 }

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

Send frame to media channel (rtp).

Definition at line 1410 of file chan_gtalk.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, gtalk_pvt::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, gtalk_pvt::rtp, ast_frame::subclass, ast_channel::tech_pvt, gtalk_pvt::vrtp, and ast_channel::writeformat.

01411 {
01412    struct gtalk_pvt *p = ast->tech_pvt;
01413    int res = 0;
01414 
01415    switch (frame->frametype) {
01416    case AST_FRAME_VOICE:
01417       if (!(frame->subclass & ast->nativeformats)) {
01418          ast_log(LOG_WARNING,
01419                "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01420                frame->subclass, ast->nativeformats, ast->readformat,
01421                ast->writeformat);
01422          return 0;
01423       }
01424       if (p) {
01425          ast_mutex_lock(&p->lock);
01426          if (p->rtp) {
01427             res = ast_rtp_write(p->rtp, frame);
01428          }
01429          ast_mutex_unlock(&p->lock);
01430       }
01431       break;
01432    case AST_FRAME_VIDEO:
01433       if (p) {
01434          ast_mutex_lock(&p->lock);
01435          if (p->vrtp) {
01436             res = ast_rtp_write(p->vrtp, frame);
01437          }
01438          ast_mutex_unlock(&p->lock);
01439       }
01440       break;
01441    case AST_FRAME_IMAGE:
01442       return 0;
01443       break;
01444    default:
01445       ast_log(LOG_WARNING, "Can't send %d type frames with Gtalk write\n",
01446             frame->frametype);
01447       return 0;
01448    }
01449 
01450    return res;
01451 }

static int load_module ( void   )  [static]

Load module into PBX, register channel.

Definition at line 1977 of file chan_gtalk.c.

References __ourip, 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, free, GOOGLE_CONFIG, gtalk_cli, gtalk_list, gtalk_load_config(), gtalk_rtp, gtalk_tech, io, io_context_create(), LOG_ERROR, LOG_WARNING, sched_context_create(), and ast_channel_tech::type.

01978 {
01979    char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
01980    free(jabber_loaded);
01981    if (!jabber_loaded) {
01982       /* If embedded, check for a different module name */
01983       jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
01984       free(jabber_loaded);
01985       if (!jabber_loaded) {
01986          ast_log(LOG_ERROR, "chan_gtalk.so depends upon res_jabber.so\n");
01987          return AST_MODULE_LOAD_DECLINE;
01988       }
01989    }
01990 
01991 #ifdef HAVE_GNUTLS   
01992         gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
01993 #endif /* HAVE_GNUTLS */
01994 
01995    ASTOBJ_CONTAINER_INIT(&gtalk_list);
01996    if (!gtalk_load_config()) {
01997       ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", GOOGLE_CONFIG);
01998       return 0;
01999    }
02000 
02001    sched = sched_context_create();
02002    if (!sched) 
02003       ast_log(LOG_WARNING, "Unable to create schedule context\n");
02004 
02005    io = io_context_create();
02006    if (!io) 
02007       ast_log(LOG_WARNING, "Unable to create I/O context\n");
02008 
02009    if (ast_find_ourip(&__ourip, bindaddr)) {
02010       ast_log(LOG_WARNING, "Unable to get own IP address, Gtalk disabled\n");
02011       return 0;
02012    }
02013 
02014    ast_rtp_proto_register(&gtalk_rtp);
02015    ast_cli_register_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0]));
02016 
02017    /* Make sure we can register our channel type */
02018    if (ast_channel_register(&gtalk_tech)) {
02019       ast_log(LOG_ERROR, "Unable to register channel class %s\n", gtalk_tech.type);
02020       return -1;
02021    }
02022    return 0;
02023 }

static int reload ( void   )  [static]

Reload module.

Definition at line 2026 of file chan_gtalk.c.

02027 {
02028    return 0;
02029 }

static int unload_module ( void   )  [static]

Unload the gtalk channel from Asterisk.

Definition at line 2032 of file chan_gtalk.c.

References 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, gtalk_cli, gtalk_list, gtalk_member_destroy(), gtalk_rtp, gtalk_tech, gtalklock, LOG_WARNING, gtalk_pvt::next, and gtalk_pvt::owner.

02033 {
02034    struct gtalk_pvt *privates = NULL;
02035    ast_cli_unregister_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0]));
02036    /* First, take us out of the channel loop */
02037    ast_channel_unregister(&gtalk_tech);
02038    ast_rtp_proto_unregister(&gtalk_rtp);
02039 
02040    if (!ast_mutex_lock(&gtalklock)) {
02041       /* Hangup all interfaces if they have an owner */
02042       ASTOBJ_CONTAINER_TRAVERSE(&gtalk_list, 1, {
02043          ASTOBJ_WRLOCK(iterator);
02044          privates = iterator->p;
02045          while(privates) {
02046             if (privates->owner)
02047                ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
02048             privates = privates->next;
02049          }
02050          iterator->p = NULL;
02051          ASTOBJ_UNLOCK(iterator);
02052       });
02053       ast_mutex_unlock(&gtalklock);
02054    } else {
02055       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
02056       return -1;
02057    }
02058    ASTOBJ_CONTAINER_DESTROYALL(&gtalk_list, gtalk_member_destroy);
02059    ASTOBJ_CONTAINER_DESTROY(&gtalk_list);
02060    return 0;
02061 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Gtalk 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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 2067 of file chan_gtalk.c.

struct in_addr __ourip [static]

Definition at line 229 of file chan_gtalk.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 2067 of file chan_gtalk.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 225 of file chan_gtalk.c.

Referenced by gtalk_alloc(), gtalk_create_candidates(), gtalk_load_config(), load_module(), reload_config(), sip_alloc(), sip_show_settings(), start_rtp(), and transmit_register().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 89 of file chan_gtalk.c.

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

Definition at line 173 of file chan_gtalk.c.

Referenced by ast_cause2str(), ast_codec2str(), load_rpt_vars(), misdn_cfg_get_desc(), and show_config_description().

char externip[16] [static]

Definition at line 256 of file chan_gtalk.c.

Referenced by gtalk_create_candidates().

GCRY_THREAD_OPTION_PTHREAD_IMPL

Definition at line 55 of file chan_gtalk.c.

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

Definition at line 175 of file chan_gtalk.c.

Referenced by gtalk_alloc(), gtalk_load_config(), and gtalk_new().

struct ast_jb_conf global_jbconf [static]

Definition at line 96 of file chan_gtalk.c.

struct ast_cli_entry gtalk_cli[] [static]

Initial value:

 {
   {{ "gtalk", "reload", NULL}, gtalk_do_reload, "Reload GoogleTalk configuration", reload_usage },
   {{ "gtalk", "show", "channels", NULL}, gtalk_show_channels, "Show GoogleTalk channels", show_channels_usage },
 }

Definition at line 249 of file chan_gtalk.c.

Referenced by load_module(), and unload_module().

struct gtalk_container gtalk_list [static]

Definition at line 258 of file chan_gtalk.c.

Referenced by find_gtalk(), gtalk_show_channels(), load_module(), and unload_module().

struct ast_rtp_protocol gtalk_rtp [static]

RTP driver interface.

Definition at line 233 of file chan_gtalk.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech gtalk_tech [static]

PBX interface structure for channel registration.

Definition at line 205 of file chan_gtalk.c.

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

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

Protect the interface list (of gtalk_pvt's)

Definition at line 177 of file chan_gtalk.c.

Referenced by gtalk_alloc(), gtalk_show_channels(), and unload_module().

struct io_context* io [static]

The IO context

Definition at line 228 of file chan_gtalk.c.

Referenced by __oh323_rtp_create(), ast_expr(), ast_rtp_new(), ast_udptl_new(), ast_udptl_new_with_bindaddr(), do_monitor(), gtalk_alloc(), load_module(), network_thread(), peer_set_srcaddr(), reload(), reload_config(), set_config(), sip_alloc(), start_rtp(), and unload_module().

char reload_usage[] [static]

Initial value:

 
"Usage: gtalk reload\n" 
"       Reload gtalk channel driver.\n"

Definition at line 244 of file chan_gtalk.c.

struct sched_context* sched [static]

The scheduling context

Definition at line 227 of file chan_gtalk.c.

char show_channels_usage[] [static]

Initial value:

 
"Usage: gtalk show channels\n" 
"       Shows current state of the Gtalk channels.\n"

Definition at line 240 of file chan_gtalk.c.


Generated on Wed Mar 4 19:58:27 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7