Sat Aug 6 00:39:43 2011

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 <ctype.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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 84 of file chan_gtalk.c.

Referenced by gtalk_load_config(), and load_module().

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

Definition at line 86 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 104 of file chan_gtalk.c.

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

enum gtalk_protocol

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 99 of file chan_gtalk.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 2109 of file chan_gtalk.c.

static void __unreg_module ( void   )  [static]

Definition at line 2109 of file chan_gtalk.c.

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

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

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

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

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

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

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

Definition at line 1099 of file chan_gtalk.c.

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

Referenced by gtalk_hangup(), and gtalk_newcall().

01100 {
01101    iks *request, *session = NULL;
01102    int res = -1;
01103    char *lowerthem = NULL;
01104 
01105    request = iks_new("iq");
01106    if (request) {
01107       iks_insert_attrib(request, "type", "set");
01108       iks_insert_attrib(request, "from", p->us);
01109       iks_insert_attrib(request, "to", p->them);
01110       iks_insert_attrib(request, "id", client->connection->mid);
01111       ast_aji_increment_mid(client->connection->mid);
01112       session = iks_new("session");
01113       if (session) {
01114          iks_insert_attrib(session, "type", action);
01115          iks_insert_attrib(session, "id", p->sid);
01116          /* put the initiator attribute to lower case if we receive the call 
01117           * otherwise GoogleTalk won't establish the session */
01118          if (!p->initiator) {
01119                  char c;
01120             char *t = lowerthem = ast_strdupa(p->them);
01121             while (((c = *t) != '/') && (*t++ = tolower(c)));
01122          }
01123          iks_insert_attrib(session, "initiator", p->initiator ? p->us : lowerthem);
01124          iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
01125          iks_insert_node(request, session);
01126          iks_send(client->connection->p, request);
01127          iks_delete(session);
01128          res = 0;
01129       }
01130       iks_delete(request);
01131    }
01132    return res;
01133 }

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

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

01322 {
01323    struct gtalk_pvt *p = NULL, *tmp = NULL;
01324    struct aji_client *c = client->connection;
01325    struct gtalk_candidate *newcandidate = NULL;
01326    iks *traversenodes = NULL, *receipt = NULL;
01327    char *from;
01328 
01329    from = iks_find_attrib(pak->x,"to");
01330    if(!from)
01331       from = c->jid->full;
01332 
01333    for (tmp = client->p; tmp; tmp = tmp->next) {
01334       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) {
01335          p = tmp;
01336          break;
01337       }
01338    }
01339 
01340    if (!p)
01341       return -1;
01342 
01343    traversenodes = pak->query;
01344    while(traversenodes) {
01345       if(!strcasecmp(iks_name(traversenodes), "session")) {
01346          traversenodes = iks_first_tag(traversenodes);
01347          continue;
01348       }
01349       if(!strcasecmp(iks_name(traversenodes), "transport")) {
01350          traversenodes = iks_first_tag(traversenodes);
01351          continue;
01352       }
01353       if(!strcasecmp(iks_name(traversenodes), "candidate")) {
01354          newcandidate = ast_calloc(1, sizeof(*newcandidate));
01355          if (!newcandidate)
01356             return 0;
01357          ast_copy_string(newcandidate->name, iks_find_attrib(traversenodes, "name"),
01358                      sizeof(newcandidate->name));
01359          ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "address"),
01360                      sizeof(newcandidate->ip));
01361          newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
01362          ast_copy_string(newcandidate->username, iks_find_attrib(traversenodes, "username"),
01363                      sizeof(newcandidate->username));
01364          ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "password"),
01365                      sizeof(newcandidate->password));
01366          newcandidate->preference = atof(iks_find_attrib(traversenodes, "preference"));
01367          if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
01368             newcandidate->protocol = AJI_PROTOCOL_UDP;
01369          if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
01370             newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
01371       
01372          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "stun"))
01373             newcandidate->type = AJI_CONNECT_STUN;
01374          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "local"))
01375             newcandidate->type = AJI_CONNECT_LOCAL;
01376          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
01377             newcandidate->type = AJI_CONNECT_RELAY;
01378          ast_copy_string(newcandidate->network, iks_find_attrib(traversenodes, "network"),
01379                      sizeof(newcandidate->network));
01380          newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
01381          newcandidate->next = NULL;
01382       
01383          newcandidate->next = p->theircandidates;
01384          p->theircandidates = newcandidate;
01385          p->laststun = 0;
01386          gtalk_update_stun(p->parent, p);
01387          newcandidate = NULL;
01388       }
01389       traversenodes = iks_next_tag(traversenodes);
01390    }
01391    
01392    receipt = iks_new("iq");
01393    iks_insert_attrib(receipt, "type", "result");
01394    iks_insert_attrib(receipt, "from", from);
01395    iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
01396    iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
01397    iks_send(c->p, receipt);
01398    iks_delete(receipt);
01399 
01400    return 1;
01401 }

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

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

00943 {
00944    struct gtalk_pvt *tmp = NULL;
00945    struct aji_resource *resources = NULL;
00946    struct aji_buddy *buddy;
00947    char idroster[200];
00948    char *data, *exten = NULL;
00949 
00950    if (option_debug)
00951       ast_log(LOG_DEBUG, "The client is %s for alloc\n", client->name);
00952    if (!sid && !strchr(them, '/')) {   /* I started call! */
00953       if (!strcasecmp(client->name, "guest")) {
00954          buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, them);
00955          if (buddy)
00956             resources = buddy->resources;
00957       } else if (client->buddy)
00958          resources = client->buddy->resources;
00959       while (resources) {
00960          if (resources->cap->jingle) {
00961             break;
00962          }
00963          resources = resources->next;
00964       }
00965       if (resources)
00966          snprintf(idroster, sizeof(idroster), "%s/%s", them, resources->resource);
00967       else {
00968          ast_log(LOG_ERROR, "no gtalk capable clients to talk to.\n");
00969          return NULL;
00970       }
00971    }
00972    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00973       return NULL;
00974    }
00975    if (sid) {
00976       ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00977       ast_copy_string(tmp->them, them, sizeof(tmp->them));
00978       ast_copy_string(tmp->us, us, sizeof(tmp->us));
00979    } else {
00980       snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00981       ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00982       ast_copy_string(tmp->us, us, sizeof(tmp->us));
00983       tmp->initiator = 1;
00984    }
00985    /* clear codecs */
00986    tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
00987    ast_rtp_pt_clear(tmp->rtp);
00988 
00989    /* add user configured codec capabilites */
00990    if (client->capability)
00991       tmp->capability = client->capability;
00992    else if (global_capability)
00993       tmp->capability = global_capability;
00994 
00995    tmp->parent = client;
00996    if (!tmp->rtp) {
00997       ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00998       free(tmp);
00999       return NULL;
01000    }
01001 
01002    /* Set CALLERID(name) to the full JID of the remote peer */
01003    ast_copy_string(tmp->cid_name, tmp->them, sizeof(tmp->cid_name));
01004 
01005    if(strchr(tmp->us, '/')) {
01006       data = ast_strdupa(tmp->us);
01007       exten = strsep(&data, "/");
01008    } else
01009       exten = tmp->us;
01010    ast_copy_string(tmp->exten,  exten, sizeof(tmp->exten));
01011    ast_mutex_init(&tmp->lock);
01012    ast_mutex_lock(&gtalklock);
01013    tmp->next = client->p;
01014    client->p = tmp;
01015    ast_mutex_unlock(&gtalklock);
01016    return tmp;
01017 }

static int gtalk_answer ( struct ast_channel ast  )  [static]

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

00548 {
00549    struct gtalk_pvt *p = ast->tech_pvt;
00550    int res = 0;
00551    
00552    if (option_debug)
00553       ast_log(LOG_DEBUG, "Answer!\n");
00554    ast_mutex_lock(&p->lock);
00555    gtalk_invite(p, p->them, p->us,p->sid, 0);
00556    ast_mutex_unlock(&p->lock);
00557    return res;
00558 }

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

01615 {
01616    struct gtalk_pvt *p = ast->tech_pvt;
01617 
01618    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01619       ast_log(LOG_WARNING, "gtalk_call called on %s, neither down nor reserved\n", ast->name);
01620       return -1;
01621    }
01622 
01623    ast_setstate(ast, AST_STATE_RING);
01624    if (!p->ringrule) {
01625       ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01626       p->ringrule = iks_filter_add_rule(p->parent->connection->f, gtalk_ringing_ack, p,
01627                      IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01628    } else
01629       ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01630 
01631    gtalk_invite(p, p->them, p->us, p->sid, 1);
01632    gtalk_create_candidates(p->parent, p, p->sid, p->them, p->us);
01633 
01634    return 0;
01635 }

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

Definition at line 806 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_strdupa, 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, t, gtalk_candidate::type, and gtalk_candidate::username.

Referenced by gtalk_call(), and gtalk_newcall().

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

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

01842 {
01843    struct aji_client *client;
01844 
01845    if (!member)
01846       ast_log(LOG_WARNING, "Out of memory.\n");
01847 
01848    ast_copy_string(member->name, label, sizeof(member->name));
01849    ast_copy_string(member->user, label, sizeof(member->user));
01850    ast_copy_string(member->context, context, sizeof(member->context));
01851    member->allowguest = allowguest;
01852    member->prefs = prefs;
01853    while (var) {
01854 #if 0
01855       struct gtalk_candidate *candidate = NULL;
01856 #endif
01857       if (!strcasecmp(var->name, "username"))
01858          ast_copy_string(member->user, var->value, sizeof(member->user));
01859       else if (!strcasecmp(var->name, "disallow"))
01860          ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
01861       else if (!strcasecmp(var->name, "allow"))
01862          ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
01863       else if (!strcasecmp(var->name, "context"))
01864          ast_copy_string(member->context, var->value, sizeof(member->context));
01865 #if 0
01866       else if (!strcasecmp(var->name, "candidate")) {
01867          candidate = gtalk_create_candidate(var->value);
01868          if (candidate) {
01869             candidate->next = member->ourcandidates;
01870             member->ourcandidates = candidate;
01871          }
01872       }
01873 #endif
01874       else if (!strcasecmp(var->name, "connection")) {
01875          if ((client = ast_aji_get_client(var->value))) {
01876             member->connection = client;
01877             iks_filter_add_rule(client->f, gtalk_parser, member, 
01878                       IKS_RULE_TYPE, IKS_PAK_IQ, 
01879                       IKS_RULE_FROM_PARTIAL, member->user,
01880                       IKS_RULE_NS, "http://www.google.com/session",
01881                       IKS_RULE_DONE);
01882 
01883          } else {
01884             ast_log(LOG_ERROR, "connection referenced not found!\n");
01885             return 0;
01886          }
01887       }
01888       var = var->next;
01889    }
01890    if (member->connection && member->user)
01891       member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
01892    else {
01893       ast_log(LOG_ERROR, "No Connection or Username!\n");
01894    }
01895    return 1;
01896 }

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

Definition at line 1531 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(), ast_strdupa, 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, t, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.

Referenced by gtalk_digit_begin(), and gtalk_digit_end().

01532 {
01533    struct gtalk_pvt *p = ast->tech_pvt;
01534    struct gtalk *client = p->parent;
01535    iks *iq, *gtalk, *dtmf;
01536    char buffer[2] = {digit, '\0'};
01537    char *lowerthem = NULL;
01538    iq = iks_new("iq");
01539    gtalk = iks_new("gtalk");
01540    dtmf = iks_new("dtmf");
01541    if(!iq || !gtalk || !dtmf) {
01542       if(iq)
01543          iks_delete(iq);
01544       if(gtalk)
01545          iks_delete(gtalk);
01546       if(dtmf)
01547          iks_delete(dtmf);
01548       ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
01549       return -1;
01550    }
01551 
01552    iks_insert_attrib(iq, "type", "set");
01553    iks_insert_attrib(iq, "to", p->them);
01554    iks_insert_attrib(iq, "from", p->us);
01555    iks_insert_attrib(iq, "id", client->connection->mid);
01556    ast_aji_increment_mid(client->connection->mid);
01557    iks_insert_attrib(gtalk, "xmlns", "http://jabber.org/protocol/gtalk");
01558    iks_insert_attrib(gtalk, "action", "session-info");
01559    /* put the initiator attribute to lower case if we receive the call 
01560     * otherwise GoogleTalk won't establish the session */
01561    if (!p->initiator) {
01562            char c;
01563            char *t = lowerthem = ast_strdupa(p->them);
01564            while (((c = *t) != '/') && (*t++ = tolower(c)));
01565    }
01566    iks_insert_attrib(gtalk, "initiator", p->initiator ? p->us: lowerthem);
01567    iks_insert_attrib(gtalk, "sid", p->sid);
01568    iks_insert_attrib(dtmf, "xmlns", "http://jabber.org/protocol/gtalk/info/dtmf");
01569    iks_insert_attrib(dtmf, "code", buffer);
01570    iks_insert_node(iq, gtalk);
01571    iks_insert_node(gtalk, dtmf);
01572 
01573    ast_mutex_lock(&p->lock);
01574    if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
01575       iks_insert_attrib(dtmf, "action", "button-down");
01576    } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
01577       iks_insert_attrib(dtmf, "action", "button-up");
01578    }
01579    iks_send(client->connection->p, iq);
01580    iks_delete(iq);
01581    iks_delete(gtalk);
01582    iks_delete(dtmf);
01583    ast_mutex_unlock(&p->lock);
01584    return 0;
01585 }

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

Definition at line 1521 of file chan_gtalk.c.

References gtalk_digit().

01522 {
01523    return gtalk_digit(chan, digit, 0);
01524 }

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

Definition at line 1526 of file chan_gtalk.c.

References gtalk_digit().

01527 {
01528    return gtalk_digit(chan, digit, duration);
01529 }

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

CLI command "gtalk show channels".

Definition at line 1757 of file chan_gtalk.c.

References ast_verbose(), and RESULT_SUCCESS.

01758 {
01759    ast_verbose("IT DOES WORK!\n");
01760    return RESULT_SUCCESS;
01761 }

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

Definition at line 1487 of file chan_gtalk.c.

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

01488 {
01489    struct gtalk_pvt *p = newchan->tech_pvt;
01490    ast_mutex_lock(&p->lock);
01491 
01492    if ((p->owner != oldchan)) {
01493       ast_mutex_unlock(&p->lock);
01494       return -1;
01495    }
01496    if (p->owner == oldchan)
01497       p->owner = newchan;
01498    ast_mutex_unlock(&p->lock);
01499    return 0;
01500 }

static void gtalk_free_candidates ( struct gtalk_candidate candidate  )  [static]

Definition at line 1135 of file chan_gtalk.c.

References free, last, and gtalk_candidate::next.

Referenced by gtalk_free_pvt().

01136 {
01137    struct gtalk_candidate *last;
01138    while (candidate) {
01139       last = candidate;
01140       candidate = candidate->next;
01141       free(last);
01142    }
01143 }

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

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

01146 {
01147    struct gtalk_pvt *cur, *prev = NULL;
01148    cur = client->p;
01149    while (cur) {
01150       if (cur == p) {
01151          if (prev)
01152             prev->next = p->next;
01153          else
01154             client->p = p->next;
01155          break;
01156       }
01157       prev = cur;
01158       cur = cur->next;
01159    }
01160    if (p->ringrule)
01161       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
01162    if (p->owner)
01163       ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
01164    if (p->rtp)
01165       ast_rtp_destroy(p->rtp);
01166    if (p->vrtp)
01167       ast_rtp_destroy(p->vrtp);
01168    gtalk_free_candidates(p->theircandidates);
01169    free(p);
01170 }

static int gtalk_get_codec ( struct ast_channel chan  )  [static]

Definition at line 578 of file chan_gtalk.c.

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

00579 {
00580    struct gtalk_pvt *p = chan->tech_pvt;
00581    return p->peercapability;
00582 }

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

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

00561 {
00562    struct gtalk_pvt *p = chan->tech_pvt;
00563    enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
00564 
00565    if (!p)
00566       return res;
00567 
00568    ast_mutex_lock(&p->lock);
00569    if (p->rtp){
00570       *rtp = p->rtp;
00571       res = AST_RTP_TRY_PARTIAL;
00572    }
00573    ast_mutex_unlock(&p->lock);
00574 
00575    return res;
00576 }

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

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

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

static int gtalk_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the gtalk proxy channel.

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

01639 {
01640    struct gtalk_pvt *p = ast->tech_pvt;
01641    struct gtalk *client;
01642 
01643    ast_mutex_lock(&p->lock);
01644    client = p->parent;
01645    p->owner = NULL;
01646    ast->tech_pvt = NULL;
01647    if (!p->alreadygone)
01648       gtalk_action(client, p, "terminate");
01649    ast_mutex_unlock(&p->lock);
01650 
01651    gtalk_free_pvt(client, p);
01652    ast_module_unref(ast_module_info->self);
01653 
01654    return 0;
01655 }

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

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

00782 {
00783    struct gtalk_pvt *tmp;
00784    char *from;
00785 
00786    ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00787    /* Make sure our new call doesn't exist yet */
00788    for (tmp = client->p; tmp; tmp = tmp->next) {
00789       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00790          break;
00791    }
00792    from = iks_find_attrib(pak->x, "to");
00793    if(!from)
00794       from = client->connection->jid->full;
00795 
00796    if (tmp) {
00797       tmp->alreadygone = 1;
00798       if (tmp->owner)
00799          ast_queue_hangup(tmp->owner);
00800    } else
00801       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00802    gtalk_response(client, from, pak, NULL, NULL);
00803    return 1;
00804 }

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

Definition at line 1502 of file chan_gtalk.c.

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

01503 {
01504    int res = 0;
01505 
01506    switch (condition) {
01507    case AST_CONTROL_HOLD:
01508       ast_moh_start(ast, data, NULL);
01509       break;
01510    case AST_CONTROL_UNHOLD:
01511       ast_moh_stop(ast);
01512       break;
01513    default:
01514       ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01515       res = -1;
01516    }
01517 
01518    return res;
01519 }

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

Definition at line 407 of file chan_gtalk.c.

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

Referenced by gtalk_answer(), and gtalk_call().

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

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

Definition at line 490 of file chan_gtalk.c.

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

Referenced by gtalk_newcall().

00491 {
00492    iks *iq, *session, *transport;
00493    char *lowerto = NULL;
00494 
00495    iq = iks_new("iq");
00496    session = iks_new("session");
00497    transport = iks_new("transport");
00498    if(!(iq && session && transport)) {
00499       if(iq)
00500          iks_delete(iq);
00501       if(session)
00502          iks_delete(session);
00503       if(transport)
00504          iks_delete(transport);
00505       ast_log(LOG_ERROR, " Unable to allocate IKS node\n");
00506       return -1;
00507    }
00508    iks_insert_attrib(iq, "from", from);
00509    iks_insert_attrib(iq, "to", to);
00510    iks_insert_attrib(iq, "type", "set");
00511    iks_insert_attrib(iq, "id",p->parent->connection->mid);
00512    ast_aji_increment_mid(p->parent->connection->mid);
00513    iks_insert_attrib(session, "type", "transport-accept");
00514    iks_insert_attrib(session, "id", sid);
00515    /* put the initiator attribute to lower case if we receive the call 
00516     * otherwise GoogleTalk won't establish the session */
00517    if (!initiator) {
00518            char c;
00519       char *t = lowerto = ast_strdupa(to);
00520       while (((c = *t) != '/') && (*t++ = tolower(c)));
00521    }
00522    iks_insert_attrib(session, "initiator", initiator ? from : lowerto);
00523    iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
00524    iks_insert_attrib(transport, "xmlns", "http://www.google.com/transport/p2p");
00525    iks_insert_node(iq,session);
00526    iks_insert_node(session,transport);
00527    iks_send(p->parent->connection->p, iq);
00528    iks_delete(transport);
00529    iks_delete(session);
00530    iks_delete(iq);
00531    return 1;
00532 
00533 }

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

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

00690 {
00691    struct gtalk_pvt *tmp;
00692    char *from;
00693 
00694    ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00695    /* find corresponding call */
00696    for (tmp = client->p; tmp; tmp = tmp->next) {
00697       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00698          break;
00699    }
00700 
00701    from = iks_find_attrib(pak->x, "to");
00702    if(!from)
00703       from = client->connection->jid->full;
00704 
00705    if (!tmp)
00706       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00707 
00708    /* answer 'iq' packet to let the remote peer know that we're alive */
00709    gtalk_response(client, from, pak, NULL, NULL);
00710    return 1;
00711 }

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

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

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

static int gtalk_load_config ( void   )  [static]

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

01899 {
01900    char *cat = NULL;
01901    struct ast_config *cfg = NULL;
01902    char context[AST_MAX_CONTEXT];
01903    int allowguest = 1;
01904    struct ast_variable *var;
01905    struct gtalk *member;
01906    struct ast_codec_pref prefs;
01907    struct aji_client_container *clients;
01908    struct gtalk_candidate *global_candidates = NULL;
01909    struct hostent *hp;
01910    struct ast_hostent ahp;
01911 
01912    cfg = ast_config_load(GOOGLE_CONFIG);
01913    if (!cfg)
01914       return 0;
01915 
01916    /* Copy the default jb config over global_jbconf */
01917    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01918 
01919    cat = ast_category_browse(cfg, NULL);
01920    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
01921       /* handle jb conf */
01922       if (!ast_jb_read_conf(&global_jbconf, var->name, var->value))
01923          continue;
01924 
01925       if (!strcasecmp(var->name, "allowguest"))
01926          allowguest =
01927             (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
01928       else if (!strcasecmp(var->name, "disallow"))
01929          ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0);
01930       else if (!strcasecmp(var->name, "allow"))
01931          ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
01932       else if (!strcasecmp(var->name, "context"))
01933          ast_copy_string(context, var->value, sizeof(context));
01934       else if (!strcasecmp(var->name, "bindaddr")) {
01935          if (!(hp = ast_gethostbyname(var->value, &ahp))) {
01936             ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
01937          } else {
01938             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
01939          }
01940       }
01941 /*  Idea to allow for custom candidates  */
01942 /*
01943       else if (!strcasecmp(var->name, "candidate")) {
01944          candidate = gtalk_create_candidate(var->value);
01945          if (candidate) {
01946             candidate->next = global_candidates;
01947             global_candidates = candidate;
01948          }
01949       }
01950 */
01951    }
01952    while (cat) {
01953       if (strcasecmp(cat, "general")) {
01954          var = ast_variable_browse(cfg, cat);
01955          member = (struct gtalk *) malloc(sizeof(struct gtalk));
01956          memset(member, 0, sizeof(struct gtalk));
01957          ASTOBJ_INIT(member);
01958          ASTOBJ_WRLOCK(member);
01959          if (!strcasecmp(cat, "guest")) {
01960             ast_copy_string(member->name, "guest", sizeof(member->name));
01961             ast_copy_string(member->user, "guest", sizeof(member->user));
01962             ast_copy_string(member->context, context, sizeof(member->context));
01963             member->allowguest = allowguest;
01964             member->prefs = prefs;
01965             while (var) {
01966                if (!strcasecmp(var->name, "disallow"))
01967                   ast_parse_allow_disallow(&member->prefs, &member->capability,
01968                                      var->value, 0);
01969                else if (!strcasecmp(var->name, "allow"))
01970                   ast_parse_allow_disallow(&member->prefs, &member->capability,
01971                                      var->value, 1);
01972                else if (!strcasecmp(var->name, "context"))
01973                   ast_copy_string(member->context, var->value,
01974                               sizeof(member->context));
01975 /*  Idea to allow for custom candidates  */
01976 /*
01977                else if (!strcasecmp(var->name, "candidate")) {
01978                   candidate = gtalk_create_candidate(var->value);
01979                   if (candidate) {
01980                      candidate->next = member->ourcandidates;
01981                      member->ourcandidates = candidate;
01982                   }
01983                }
01984 */
01985                var = var->next;
01986             }
01987             ASTOBJ_UNLOCK(member);
01988             clients = ast_aji_get_clients();
01989             if (clients) {
01990                ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
01991                   ASTOBJ_WRLOCK(iterator);
01992                   ASTOBJ_WRLOCK(member);
01993                   member->connection = NULL;
01994                   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);
01995                   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);
01996                   ASTOBJ_UNLOCK(member);
01997                   ASTOBJ_UNLOCK(iterator);
01998                });
01999                ASTOBJ_CONTAINER_LINK(&gtalk_list, member);
02000                ASTOBJ_UNREF(member, gtalk_member_destroy);
02001             } else {
02002                ASTOBJ_UNLOCK(member);
02003                ASTOBJ_UNREF(member, gtalk_member_destroy);
02004             }
02005          } else {
02006             ASTOBJ_UNLOCK(member);
02007             if (gtalk_create_member(cat, var, allowguest, prefs, context, member))
02008                ASTOBJ_CONTAINER_LINK(&gtalk_list, member);
02009             ASTOBJ_UNREF(member, gtalk_member_destroy);
02010          }
02011       }
02012       cat = ast_category_browse(cfg, cat);
02013    }
02014    gtalk_free_candidates(global_candidates);
02015    return 1;
02016 }

static void gtalk_member_destroy ( struct gtalk obj  )  [static]

Definition at line 261 of file chan_gtalk.c.

References free.

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

00262 {
00263    free(obj);
00264 }

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

01021 {
01022    struct ast_channel *tmp;
01023    int fmt;
01024    int what;
01025    const char *n2;
01026 
01027    if (title)
01028       n2 = title;
01029    else
01030       n2 = i->us;
01031    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);
01032    if (!tmp) {
01033       ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n");
01034       return NULL;
01035    }
01036    tmp->tech = &gtalk_tech;
01037 
01038    /* Select our native format based on codec preference until we receive
01039       something from another device to the contrary. */
01040    if (i->jointcapability)
01041       what = i->jointcapability;
01042    else if (i->capability)
01043       what = i->capability;
01044    else
01045       what = global_capability;
01046    tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
01047    fmt = ast_best_codec(tmp->nativeformats);
01048 
01049    if (i->rtp) {
01050       ast_rtp_setstun(i->rtp, 1);
01051       tmp->fds[0] = ast_rtp_fd(i->rtp);
01052       tmp->fds[1] = ast_rtcp_fd(i->rtp);
01053    }
01054    if (i->vrtp) {
01055       ast_rtp_setstun(i->rtp, 1);
01056       tmp->fds[2] = ast_rtp_fd(i->vrtp);
01057       tmp->fds[3] = ast_rtcp_fd(i->vrtp);
01058    }
01059    if (state == AST_STATE_RING)
01060       tmp->rings = 1;
01061    tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01062    tmp->writeformat = fmt;
01063    tmp->rawwriteformat = fmt;
01064    tmp->readformat = fmt;
01065    tmp->rawreadformat = fmt;
01066    tmp->tech_pvt = i;
01067 
01068    tmp->callgroup = client->callgroup;
01069    tmp->pickupgroup = client->pickupgroup;
01070    tmp->cid.cid_pres = client->callingpres;
01071    if (!ast_strlen_zero(client->accountcode))
01072       ast_string_field_set(tmp, accountcode, client->accountcode);
01073    if (client->amaflags)
01074       tmp->amaflags = client->amaflags;
01075    if (!ast_strlen_zero(client->language))
01076       ast_string_field_set(tmp, language, client->language);
01077    if (!ast_strlen_zero(client->musicclass))
01078       ast_string_field_set(tmp, musicclass, client->musicclass);
01079    i->owner = tmp;
01080    ast_module_ref(ast_module_info->self);
01081    ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
01082    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01083 
01084    if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
01085       tmp->cid.cid_dnid = ast_strdup(i->exten);
01086    tmp->priority = 1;
01087    if (i->rtp)
01088       ast_jb_configure(tmp, &global_jbconf);
01089    if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
01090       ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01091       tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
01092       ast_hangup(tmp);
01093       tmp = NULL;
01094    }
01095 
01096    return tmp;
01097 }

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

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

01174 {
01175    struct gtalk_pvt *p, *tmp = client->p;
01176    struct ast_channel *chan;
01177    int res;
01178    iks *codec;
01179    char *from = NULL;
01180    char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ];
01181    int peernoncodeccapability;
01182 
01183    /* Make sure our new call doesn't exist yet */
01184    from = iks_find_attrib(pak->x,"to");
01185    if(!from)
01186       from = client->connection->jid->full;
01187    
01188    while (tmp) {
01189       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) {
01190          ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
01191          gtalk_response(client, from, pak, "out-of-order", NULL);
01192          return -1;
01193       }
01194       tmp = tmp->next;
01195    }
01196 
01197    if (!strcasecmp(client->name, "guest")){
01198       /* the guest account is not tied to any configured XMPP client,
01199          let's set it now */
01200       client->connection = ast_aji_get_client(from);
01201       if (!client->connection) {
01202          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from);
01203          return -1;
01204       }
01205    }
01206 
01207    p = gtalk_alloc(client, from, pak->from->full, iks_find_attrib(pak->query, "id"));
01208    if (!p) {
01209       ast_log(LOG_WARNING, "Unable to allocate gtalk structure!\n");
01210       return -1;
01211    }
01212 
01213    chan = gtalk_new(client, p, AST_STATE_DOWN, pak->from->user);
01214    if (!chan) {
01215       gtalk_free_pvt(client, p);
01216       return -1;
01217    }
01218 
01219    ast_mutex_lock(&p->lock);
01220    ast_copy_string(p->them, pak->from->full, sizeof(p->them));
01221    if (iks_find_attrib(pak->query, "id")) {
01222       ast_copy_string(p->sid, iks_find_attrib(pak->query, "id"),
01223             sizeof(p->sid));
01224    }
01225 
01226    /* codec points to the first <payload-type/> tag */   
01227    codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
01228    
01229    while (codec) {
01230       ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
01231       ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
01232       codec = iks_next_tag(codec);
01233    }
01234    
01235    /* Now gather all of the codecs that we are asked for */
01236    ast_rtp_get_current_formats(p->rtp, &p->peercapability, &peernoncodeccapability);
01237    p->jointcapability = p->capability & p->peercapability;
01238    ast_mutex_unlock(&p->lock);
01239       
01240    ast_setstate(chan, AST_STATE_RING);
01241    if (!p->jointcapability) {
01242       ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->capability),
01243          ast_getformatname_multiple(s2, BUFSIZ, p->peercapability),
01244          ast_getformatname_multiple(s3, BUFSIZ, p->jointcapability));
01245       /* close session if capabilities don't match */
01246       gtalk_action(client, p, "reject");
01247       p->alreadygone = 1;
01248       gtalk_hangup(chan);
01249       ast_channel_free(chan);
01250       return -1;
01251    }  
01252 
01253    res = ast_pbx_start(chan);
01254    
01255    switch (res) {
01256    case AST_PBX_FAILED:
01257       ast_log(LOG_WARNING, "Failed to start PBX :(\n");
01258       gtalk_response(client, from, pak, "service-unavailable", NULL);
01259       break;
01260    case AST_PBX_CALL_LIMIT:
01261       ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
01262       gtalk_response(client, from, pak, "service-unavailable", NULL);
01263       break;
01264    case AST_PBX_SUCCESS:
01265       gtalk_response(client, from, pak, NULL, NULL);
01266       gtalk_invite_response(p, p->them, p->us,p->sid, 0);
01267       gtalk_create_candidates(client, p, p->sid, p->them, p->us);
01268       /* nothing to do */
01269       break;
01270    }
01271 
01272    return 1;
01273 }

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

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

01764 {
01765    struct gtalk *client = ASTOBJ_REF((struct gtalk *) data);
01766 
01767    if (iks_find_with_attrib(pak->x, "session", "type", "initiate")) {
01768       /* New call */
01769       gtalk_newcall(client, pak);
01770    } else if (iks_find_with_attrib(pak->x, "session", "type", "candidates") || iks_find_with_attrib(pak->x, "session", "type", "transport-info")) {
01771       if (option_debug > 2)
01772          ast_log(LOG_DEBUG, "About to add candidate!\n");
01773       gtalk_add_candidate(client, pak);
01774       if (option_debug > 2)
01775          ast_log(LOG_DEBUG, "Candidate Added!\n");
01776    } else if (iks_find_with_attrib(pak->x, "session", "type", "accept")) {
01777       gtalk_is_answered(client, pak);
01778    } else if (iks_find_with_attrib(pak->x, "session", "type", "transport-accept")) {
01779       gtalk_is_accepted(client, pak);
01780    } else if (iks_find_with_attrib(pak->x, "session", "type", "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) {
01781       gtalk_handle_dtmf(client, pak);
01782    } else if (iks_find_with_attrib(pak->x, "session", "type", "terminate")) {
01783       gtalk_hangup_farend(client, pak);
01784    } else if (iks_find_with_attrib(pak->x, "session", "type", "reject")) {
01785       gtalk_hangup_farend(client, pak);
01786    }
01787    ASTOBJ_UNREF(client, gtalk_member_destroy);
01788    return IKS_FILTER_EAT;
01789 }

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

Definition at line 1432 of file chan_gtalk.c.

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

01433 {
01434    struct ast_frame *fr;
01435    struct gtalk_pvt *p = ast->tech_pvt;
01436 
01437    ast_mutex_lock(&p->lock);
01438    fr = gtalk_rtp_read(ast, p);
01439    ast_mutex_unlock(&p->lock);
01440    return fr;
01441 }

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

Part of PBX interface.

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

01659 {
01660    struct gtalk_pvt *p = NULL;
01661    struct gtalk *client = NULL;
01662    char *sender = NULL, *to = NULL, *s = NULL;
01663    struct ast_channel *chan = NULL;
01664 
01665    if (data) {
01666       s = ast_strdupa(data);
01667       if (s) {
01668          sender = strsep(&s, "/");
01669          if (sender && (sender[0] != '\0'))
01670             to = strsep(&s, "/");
01671          if (!to) {
01672             ast_log(LOG_ERROR, "Bad arguments in Gtalk Dialstring: %s\n", (char*) data);
01673             return NULL;
01674          }
01675       }
01676    }
01677 
01678    client = find_gtalk(to, sender);
01679    if (!client) {
01680       ast_log(LOG_WARNING, "Could not find recipient.\n");
01681       return NULL;
01682    }
01683    if (!strcasecmp(client->name, "guest")){
01684       /* the guest account is not tied to any configured XMPP client,
01685          let's set it now */
01686       client->connection = ast_aji_get_client(sender);
01687       if (!client->connection) {
01688          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01689          ASTOBJ_UNREF(client, gtalk_member_destroy);
01690          return NULL;
01691       }
01692    }
01693 
01694    ASTOBJ_WRLOCK(client);
01695    p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL);
01696    if (p)
01697       chan = gtalk_new(client, p, AST_STATE_DOWN, to);
01698 
01699    ASTOBJ_UNLOCK(client);
01700    return chan;
01701 }

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

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

00605 {
00606    iks *response = NULL, *error = NULL, *reason = NULL;
00607    int res = -1;
00608 
00609    response = iks_new("iq");
00610    if (response) {
00611       iks_insert_attrib(response, "type", "result");
00612       iks_insert_attrib(response, "from", from);
00613       iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
00614       iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
00615       if (reasonstr) {
00616          error = iks_new("error");
00617          if (error) {
00618             iks_insert_attrib(error, "type", "cancel");
00619             reason = iks_new(reasonstr);
00620             if (reason)
00621                iks_insert_node(error, reason);
00622             iks_insert_node(response, error);
00623          }
00624       }
00625       iks_send(client->connection->p, response);
00626       if (reason)
00627          iks_delete(reason);
00628       if (error)
00629          iks_delete(error);
00630       iks_delete(response);
00631       res = 0;
00632    }
00633    return res;
00634 }

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

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

00536 {
00537    struct gtalk_pvt *p = data;
00538 
00539    if (p->ringrule)
00540       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00541    p->ringrule = NULL;
00542    if (p->owner)
00543       ast_queue_control(p->owner, AST_CONTROL_RINGING);
00544    return IKS_FILTER_EAT;
00545 }

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

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

01404 {
01405    struct ast_frame *f;
01406 
01407    if (!p->rtp)
01408       return &ast_null_frame;
01409    f = ast_rtp_read(p->rtp);
01410    gtalk_update_stun(p->parent, p);
01411    if (p->owner) {
01412       /* We already hold the channel lock */
01413       if (f->frametype == AST_FRAME_VOICE) {
01414          if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
01415             if (option_debug)
01416                ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
01417             p->owner->nativeformats =
01418                (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
01419             ast_set_read_format(p->owner, p->owner->readformat);
01420             ast_set_write_format(p->owner, p->owner->writeformat);
01421          }
01422 /*       if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
01423             f = ast_dsp_process(p->owner, p->vad, f);
01424             if (option_debug && f && (f->frametype == AST_FRAME_DTMF))
01425                ast_log(LOG_DEBUG, "* Detected inband DTMF '%c'\n", f->subclass);
01426               } */
01427       }
01428    }
01429    return f;
01430 }

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

Definition at line 1587 of file chan_gtalk.c.

References ast_log(), and LOG_NOTICE.

01588 {
01589    ast_log(LOG_NOTICE, "XXX Implement gtalk sendhtml XXX\n");
01590 
01591    return -1;
01592 }

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 584 of file chan_gtalk.c.

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

00585 {
00586    struct gtalk_pvt *p;
00587 
00588    p = chan->tech_pvt;
00589    if (!p)
00590       return -1;
00591    ast_mutex_lock(&p->lock);
00592 
00593 /* if (rtp)
00594       ast_rtp_get_peer(rtp, &p->redirip);
00595    else
00596       memset(&p->redirip, 0, sizeof(p->redirip));
00597    p->redircodecs = codecs; */
00598 
00599    /* Reset lastrtprx timer */
00600    ast_mutex_unlock(&p->lock);
00601    return 0;
00602 }

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

CLI command "gtalk show channels".

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

01705 {
01706 #define FORMAT  "%-30.30s  %-30.30s  %-15.15s  %-5.5s %-5.5s \n"
01707    struct gtalk_pvt *p;
01708    struct ast_channel *chan;
01709    int numchans = 0;
01710    char them[AJI_MAX_JIDLEN];
01711    char *jid = NULL;
01712    char *resource = NULL;
01713 
01714    if (argc != 3)
01715       return RESULT_SHOWUSAGE;
01716 
01717    ast_mutex_lock(&gtalklock);
01718    ast_cli(fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
01719    ASTOBJ_CONTAINER_TRAVERSE(&gtalk_list, 1, {
01720       ASTOBJ_WRLOCK(iterator);
01721       p = iterator->p;
01722       while(p) {
01723          chan = p->owner;
01724          ast_copy_string(them, p->them, sizeof(them));
01725          jid = them;
01726          resource = strchr(them, '/');
01727          if (!resource)
01728             resource = "None";
01729          else {
01730             *resource = '\0';
01731             resource ++;
01732          }
01733          if (chan)
01734             ast_cli(fd, FORMAT, 
01735                chan->name,
01736                jid,
01737                resource,
01738                ast_getformatname(chan->readformat),
01739                ast_getformatname(chan->writeformat)               
01740                );
01741          else 
01742             ast_log(LOG_WARNING, "No available channel\n");
01743          numchans ++;
01744          p = p->next;
01745       }
01746       ASTOBJ_UNLOCK(iterator);
01747    });
01748 
01749    ast_mutex_unlock(&gtalklock);
01750 
01751    ast_cli(fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : "");
01752    return RESULT_SUCCESS;
01753 #undef FORMAT
01754 }

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

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

01276 {
01277    struct gtalk_candidate *tmp;
01278    struct hostent *hp;
01279    struct ast_hostent ahp;
01280    struct sockaddr_in sin;
01281    struct sockaddr_in aux;
01282 
01283    if (time(NULL) == p->laststun)
01284       return 0;
01285 
01286    tmp = p->theircandidates;
01287    p->laststun = time(NULL);
01288    while (tmp) {
01289       char username[256];
01290 
01291       /* Find the IP address of the host */
01292       hp = ast_gethostbyname(tmp->ip, &ahp);
01293       sin.sin_family = AF_INET;
01294       memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01295       sin.sin_port = htons(tmp->port);
01296       snprintf(username, sizeof(username), "%s%s", tmp->username,
01297           p->ourcandidates->username);
01298       
01299       /* Find out the result of the STUN */
01300       ast_rtp_get_peer(p->rtp, &aux);
01301 
01302       /* If the STUN result is different from the IP of the hostname,
01303          lock on the stun IP of the hostname advertised by the
01304          remote client */
01305       if (aux.sin_addr.s_addr && 
01306           aux.sin_addr.s_addr != sin.sin_addr.s_addr)
01307          ast_rtp_stun_request(p->rtp, &aux, username);
01308       else 
01309          ast_rtp_stun_request(p->rtp, &sin, username);
01310       
01311       if (aux.sin_addr.s_addr && option_debug > 3) {
01312          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);
01313          ast_log(LOG_DEBUG, "Sending STUN request to %s\n", tmp->ip);
01314       }
01315 
01316       tmp = tmp->next;
01317    }
01318    return 1;
01319 }

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

Send frame to media channel (rtp).

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

01445 {
01446    struct gtalk_pvt *p = ast->tech_pvt;
01447    int res = 0;
01448 
01449    switch (frame->frametype) {
01450    case AST_FRAME_VOICE:
01451       if (!(frame->subclass & ast->nativeformats)) {
01452          ast_log(LOG_WARNING,
01453                "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01454                frame->subclass, ast->nativeformats, ast->readformat,
01455                ast->writeformat);
01456          return 0;
01457       }
01458       if (p) {
01459          ast_mutex_lock(&p->lock);
01460          if (p->rtp) {
01461             res = ast_rtp_write(p->rtp, frame);
01462          }
01463          ast_mutex_unlock(&p->lock);
01464       }
01465       break;
01466    case AST_FRAME_VIDEO:
01467       if (p) {
01468          ast_mutex_lock(&p->lock);
01469          if (p->vrtp) {
01470             res = ast_rtp_write(p->vrtp, frame);
01471          }
01472          ast_mutex_unlock(&p->lock);
01473       }
01474       break;
01475    case AST_FRAME_IMAGE:
01476       return 0;
01477       break;
01478    default:
01479       ast_log(LOG_WARNING, "Can't send %d type frames with Gtalk write\n",
01480             frame->frametype);
01481       return 0;
01482    }
01483 
01484    return res;
01485 }

static int load_module ( void   )  [static]

Load module into PBX, register channel.

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

02020 {
02021    char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
02022    free(jabber_loaded);
02023    if (!jabber_loaded) {
02024       /* If embedded, check for a different module name */
02025       jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
02026       free(jabber_loaded);
02027       if (!jabber_loaded) {
02028          ast_log(LOG_ERROR, "chan_gtalk.so depends upon res_jabber.so\n");
02029          return AST_MODULE_LOAD_DECLINE;
02030       }
02031    }
02032 
02033 #ifdef HAVE_GNUTLS   
02034         gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
02035 #endif /* HAVE_GNUTLS */
02036 
02037    ASTOBJ_CONTAINER_INIT(&gtalk_list);
02038    if (!gtalk_load_config()) {
02039       ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", GOOGLE_CONFIG);
02040       return 0;
02041    }
02042 
02043    sched = sched_context_create();
02044    if (!sched) 
02045       ast_log(LOG_WARNING, "Unable to create schedule context\n");
02046 
02047    io = io_context_create();
02048    if (!io) 
02049       ast_log(LOG_WARNING, "Unable to create I/O context\n");
02050 
02051    if (ast_find_ourip(&__ourip, bindaddr)) {
02052       ast_log(LOG_WARNING, "Unable to get own IP address, Gtalk disabled\n");
02053       return 0;
02054    }
02055 
02056    ast_rtp_proto_register(&gtalk_rtp);
02057    ast_cli_register_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0]));
02058 
02059    /* Make sure we can register our channel type */
02060    if (ast_channel_register(&gtalk_tech)) {
02061       ast_log(LOG_ERROR, "Unable to register channel class %s\n", gtalk_tech.type);
02062       return -1;
02063    }
02064    return 0;
02065 }

static int reload ( void   )  [static]

Reload module.

Definition at line 2068 of file chan_gtalk.c.

02069 {
02070    return 0;
02071 }

static int unload_module ( void   )  [static]

Unload the gtalk channel from Asterisk.

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

02075 {
02076    struct gtalk_pvt *privates = NULL;
02077    ast_cli_unregister_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0]));
02078    /* First, take us out of the channel loop */
02079    ast_channel_unregister(&gtalk_tech);
02080    ast_rtp_proto_unregister(&gtalk_rtp);
02081 
02082    if (!ast_mutex_lock(&gtalklock)) {
02083       /* Hangup all interfaces if they have an owner */
02084       ASTOBJ_CONTAINER_TRAVERSE(&gtalk_list, 1, {
02085          ASTOBJ_WRLOCK(iterator);
02086          privates = iterator->p;
02087          while(privates) {
02088             if (privates->owner)
02089                ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
02090             privates = privates->next;
02091          }
02092          iterator->p = NULL;
02093          ASTOBJ_UNLOCK(iterator);
02094       });
02095       ast_mutex_unlock(&gtalklock);
02096    } else {
02097       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
02098       return -1;
02099    }
02100    ASTOBJ_CONTAINER_DESTROYALL(&gtalk_list, gtalk_member_destroy);
02101    ASTOBJ_CONTAINER_DESTROY(&gtalk_list);
02102    return 0;
02103 }


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

Definition at line 2109 of file chan_gtalk.c.

struct in_addr __ourip [static]

Definition at line 230 of file chan_gtalk.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 2109 of file chan_gtalk.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 226 of file chan_gtalk.c.

Referenced by ast_sip_ouraddrfor(), 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 90 of file chan_gtalk.c.

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

Definition at line 174 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 257 of file chan_gtalk.c.

Referenced by gtalk_create_candidates().

GCRY_THREAD_OPTION_PTHREAD_IMPL

Definition at line 56 of file chan_gtalk.c.

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

Definition at line 176 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 97 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 250 of file chan_gtalk.c.

Referenced by load_module(), and unload_module().

struct gtalk_container gtalk_list [static]

Definition at line 259 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 234 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 206 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 178 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 229 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 245 of file chan_gtalk.c.

struct sched_context* sched [static]

The scheduling context

Definition at line 228 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 241 of file chan_gtalk.c.


Generated on Sat Aug 6 00:39:43 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7