Fri Jun 19 12:10:12 2009

Asterisk developer's documentation


chan_gtalk.c File Reference

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

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

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 char * gtalk_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command "gtalk reload".
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, struct ast_rtp *trtp, int codecs, int nat_active)
static char * gtalk_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 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 , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr = { 0, }
static struct ast_jb_conf default_jbconf
static const char desc [] = "Gtalk Channel"
static char externip [16]
static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263
static struct ast_jb_conf global_jbconf
static struct 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_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct io_contextio
static struct sched_contextsched


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

Referenced by gtalk_load_config(), and load_module().

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

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

00089                         {
00090    AJI_CONNECT_STUN = 1,
00091    AJI_CONNECT_LOCAL = 2,
00092    AJI_CONNECT_RELAY = 3,
00093 };

enum gtalk_protocol

Enumerator:
AJI_PROTOCOL_UDP 
AJI_PROTOCOL_SSLTCP 

Definition at line 84 of file chan_gtalk.c.

00084                     {
00085    AJI_PROTOCOL_UDP = 1,
00086    AJI_PROTOCOL_SSLTCP = 2,
00087 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 2067 of file chan_gtalk.c.

static void __unreg_module ( void   )  [static]

Definition at line 2067 of file chan_gtalk.c.

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

Definition at line 272 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(), and jingle_accept_call().

00273 {
00274    int res = 0;
00275    char *format = ast_getformatname(codec);
00276 
00277    if (!strcasecmp("ulaw", format)) {
00278       iks *payload_eg711u, *payload_pcmu;
00279       payload_pcmu = iks_new("payload-type");
00280       payload_eg711u = iks_new("payload-type");
00281    
00282       if(!payload_eg711u || !payload_pcmu) {
00283          iks_delete(payload_pcmu);
00284          iks_delete(payload_eg711u);
00285          ast_log(LOG_WARNING,"Failed to allocate iks node");
00286          return -1;
00287       }
00288       iks_insert_attrib(payload_pcmu, "id", "0");
00289       iks_insert_attrib(payload_pcmu, "name", "PCMU");
00290       iks_insert_attrib(payload_pcmu, "clockrate","8000");
00291       iks_insert_attrib(payload_pcmu, "bitrate","64000");
00292       iks_insert_attrib(payload_eg711u, "id", "100");
00293       iks_insert_attrib(payload_eg711u, "name", "EG711U");
00294       iks_insert_attrib(payload_eg711u, "clockrate","8000");
00295       iks_insert_attrib(payload_eg711u, "bitrate","64000");
00296       iks_insert_node(dcodecs, payload_pcmu);
00297       iks_insert_node(dcodecs, payload_eg711u);
00298       res ++;
00299    }
00300    if (!strcasecmp("alaw", format)) {
00301       iks *payload_eg711a, *payload_pcma;
00302       payload_pcma = iks_new("payload-type");
00303       payload_eg711a = iks_new("payload-type");
00304       if(!payload_eg711a || !payload_pcma) {
00305          iks_delete(payload_eg711a);
00306          iks_delete(payload_pcma);
00307          ast_log(LOG_WARNING,"Failed to allocate iks node");
00308          return -1;
00309       }
00310       iks_insert_attrib(payload_pcma, "id", "8");
00311       iks_insert_attrib(payload_pcma, "name", "PCMA");
00312       iks_insert_attrib(payload_pcma, "clockrate","8000");
00313       iks_insert_attrib(payload_pcma, "bitrate","64000");
00314       payload_eg711a = iks_new("payload-type");
00315       iks_insert_attrib(payload_eg711a, "id", "101");
00316       iks_insert_attrib(payload_eg711a, "name", "EG711A");
00317       iks_insert_attrib(payload_eg711a, "clockrate","8000");
00318       iks_insert_attrib(payload_eg711a, "bitrate","64000");
00319       iks_insert_node(dcodecs, payload_pcma);
00320       iks_insert_node(dcodecs, payload_eg711a);
00321       res ++;
00322    }
00323    if (!strcasecmp("ilbc", format)) {
00324       iks *payload_ilbc = iks_new("payload-type");
00325       if(!payload_ilbc) {
00326          ast_log(LOG_WARNING,"Failed to allocate iks node");
00327          return -1;
00328       }
00329       iks_insert_attrib(payload_ilbc, "id", "97");
00330       iks_insert_attrib(payload_ilbc, "name", "iLBC");
00331       iks_insert_attrib(payload_ilbc, "clockrate","8000");
00332       iks_insert_attrib(payload_ilbc, "bitrate","13300");
00333       iks_insert_node(dcodecs, payload_ilbc);
00334       res ++;
00335    }
00336    if (!strcasecmp("g723", format)) {
00337       iks *payload_g723 = iks_new("payload-type");
00338       if(!payload_g723) {
00339          ast_log(LOG_WARNING,"Failed to allocate iks node");
00340          return -1;
00341       }
00342       iks_insert_attrib(payload_g723, "id", "4");
00343       iks_insert_attrib(payload_g723, "name", "G723");
00344       iks_insert_attrib(payload_g723, "clockrate","8000");
00345       iks_insert_attrib(payload_g723, "bitrate","6300");
00346       iks_insert_node(dcodecs, payload_g723);
00347       res ++;
00348    }
00349    if (!strcasecmp("speex", format)) {
00350       iks *payload_speex = iks_new("payload-type");
00351       if(!payload_speex) {
00352          ast_log(LOG_WARNING,"Failed to allocate iks node");
00353          return -1;
00354       }
00355       iks_insert_attrib(payload_speex, "id", "110");
00356       iks_insert_attrib(payload_speex, "name", "speex");
00357       iks_insert_attrib(payload_speex, "clockrate","8000");
00358       iks_insert_attrib(payload_speex, "bitrate","11000");
00359       iks_insert_node(dcodecs, payload_speex);
00360       res++;
00361    }
00362    if (!strcasecmp("gsm", format)) {
00363       iks *payload_gsm = iks_new("payload-type");
00364       if(!payload_gsm) {
00365          ast_log(LOG_WARNING,"Failed to allocate iks node");
00366          return -1;
00367       }
00368       iks_insert_attrib(payload_gsm, "id", "103");
00369       iks_insert_attrib(payload_gsm, "name", "gsm");
00370       iks_insert_node(dcodecs, payload_gsm);
00371       res++;
00372    }
00373    ast_rtp_lookup_code(p->rtp, 1, codec);
00374    return res;
00375 }

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

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

Referenced by gtalk_request().

00241 {
00242    struct gtalk *gtalk = NULL;
00243    char *domain = NULL , *s = NULL;
00244 
00245    if (strchr(connection, '@')) {
00246       s = ast_strdupa(connection);
00247       domain = strsep(&s, "@");
00248       ast_verbose("OOOOH domain = %s\n", domain);
00249    }
00250    gtalk = ASTOBJ_CONTAINER_FIND(&gtalk_list, name);
00251    if (!gtalk && strchr(name, '@'))
00252       gtalk = ASTOBJ_CONTAINER_FIND_FULL(&gtalk_list, name, user,,, strcasecmp);
00253 
00254    if (!gtalk) {           
00255       /* guest call */
00256       ASTOBJ_CONTAINER_TRAVERSE(&gtalk_list, 1, {
00257          ASTOBJ_RDLOCK(iterator);
00258          if (!strcasecmp(iterator->name, "guest")) {
00259             gtalk = iterator;
00260          }
00261          ASTOBJ_UNLOCK(iterator);
00262 
00263          if (gtalk)
00264             break;
00265       });
00266 
00267    }
00268    return gtalk;
00269 }

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

Definition at line 1048 of file chan_gtalk.c.

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

Referenced by gtalk_hangup(), and gtalk_newcall().

01049 {
01050    iks *request, *session = NULL;
01051    int res = -1;
01052 
01053    request = iks_new("iq");
01054    if (request) {
01055       iks_insert_attrib(request, "type", "set");
01056       iks_insert_attrib(request, "from", p->us);
01057       iks_insert_attrib(request, "to", p->them);
01058       iks_insert_attrib(request, "id", client->connection->mid);
01059       ast_aji_increment_mid(client->connection->mid);
01060       session = iks_new("session");
01061       if (session) {
01062          iks_insert_attrib(session, "type", action);
01063          iks_insert_attrib(session, "id", p->sid);
01064          iks_insert_attrib(session, "initiator", p->initiator ? p->us : p->them);
01065          iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
01066          iks_insert_node(request, session);
01067          ast_aji_send(client->connection, request);
01068          res = 0;
01069       }
01070    }
01071 
01072    iks_delete(session);
01073    iks_delete(request);
01074 
01075    return res;
01076 }

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

Definition at line 1264 of file chan_gtalk.c.

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

Referenced by gtalk_parser().

01265 {
01266    struct gtalk_pvt *p = NULL, *tmp = NULL;
01267    struct aji_client *c = client->connection;
01268    struct gtalk_candidate *newcandidate = NULL;
01269    iks *traversenodes = NULL, *receipt = NULL;
01270    char *from;
01271 
01272    from = iks_find_attrib(pak->x,"to");
01273    if(!from)
01274       from = c->jid->full;
01275 
01276    for (tmp = client->p; tmp; tmp = tmp->next) {
01277       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) {
01278          p = tmp;
01279          break;
01280       }
01281    }
01282 
01283    if (!p)
01284       return -1;
01285 
01286    traversenodes = pak->query;
01287    while(traversenodes) {
01288       if(!strcasecmp(iks_name(traversenodes), "session")) {
01289          traversenodes = iks_first_tag(traversenodes);
01290          continue;
01291       }
01292       if(!strcasecmp(iks_name(traversenodes), "transport")) {
01293          traversenodes = iks_first_tag(traversenodes);
01294          continue;
01295       }
01296       if(!strcasecmp(iks_name(traversenodes), "candidate")) {
01297          newcandidate = ast_calloc(1, sizeof(*newcandidate));
01298          if (!newcandidate)
01299             return 0;
01300          ast_copy_string(newcandidate->name, iks_find_attrib(traversenodes, "name"),
01301                      sizeof(newcandidate->name));
01302          ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "address"),
01303                      sizeof(newcandidate->ip));
01304          newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
01305          ast_copy_string(newcandidate->username, iks_find_attrib(traversenodes, "username"),
01306                      sizeof(newcandidate->username));
01307          ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "password"),
01308                      sizeof(newcandidate->password));
01309          newcandidate->preference = atof(iks_find_attrib(traversenodes, "preference"));
01310          if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
01311             newcandidate->protocol = AJI_PROTOCOL_UDP;
01312          if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
01313             newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
01314       
01315          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "stun"))
01316             newcandidate->type = AJI_CONNECT_STUN;
01317          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "local"))
01318             newcandidate->type = AJI_CONNECT_LOCAL;
01319          if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
01320             newcandidate->type = AJI_CONNECT_RELAY;
01321          ast_copy_string(newcandidate->network, iks_find_attrib(traversenodes, "network"),
01322                      sizeof(newcandidate->network));
01323          newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
01324          newcandidate->next = NULL;
01325       
01326          newcandidate->next = p->theircandidates;
01327          p->theircandidates = newcandidate;
01328          p->laststun = 0;
01329          gtalk_update_stun(p->parent, p);
01330          newcandidate = NULL;
01331       }
01332       traversenodes = iks_next_tag(traversenodes);
01333    }
01334    
01335    receipt = iks_new("iq");
01336    iks_insert_attrib(receipt, "type", "result");
01337    iks_insert_attrib(receipt, "from", from);
01338    iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
01339    iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
01340    ast_aji_send(c, receipt);
01341 
01342    iks_delete(receipt);
01343 
01344    return 1;
01345 }

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

Definition at line 879 of file chan_gtalk.c.

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

Referenced by gtalk_newcall(), and gtalk_request().

00880 {
00881    struct gtalk_pvt *tmp = NULL;
00882    struct aji_resource *resources = NULL;
00883    struct aji_buddy *buddy;
00884    char idroster[200];
00885    char *data, *exten = NULL;
00886 
00887    ast_debug(1, "The client is %s for alloc\n", client->name);
00888    if (!sid && !strchr(them, '/')) {   /* I started call! */
00889       if (!strcasecmp(client->name, "guest")) {
00890          buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, them);
00891          if (buddy)
00892             resources = buddy->resources;
00893       } else if (client->buddy)
00894          resources = client->buddy->resources;
00895       while (resources) {
00896          if (resources->cap->jingle) {
00897             break;
00898          }
00899          resources = resources->next;
00900       }
00901       if (resources)
00902          snprintf(idroster, sizeof(idroster), "%s/%s", them, resources->resource);
00903       else {
00904          ast_log(LOG_ERROR, "no gtalk capable clients to talk to.\n");
00905          return NULL;
00906       }
00907    }
00908    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00909       return NULL;
00910    }
00911 
00912    memcpy(&tmp->prefs, &client->prefs, sizeof(struct ast_codec_pref));
00913 
00914    if (sid) {
00915       ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00916       ast_copy_string(tmp->them, them, sizeof(tmp->them));
00917       ast_copy_string(tmp->us, us, sizeof(tmp->us));
00918    } else {
00919       snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00920       ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00921       ast_copy_string(tmp->us, us, sizeof(tmp->us));
00922       tmp->initiator = 1;
00923    }
00924    /* clear codecs */
00925    tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
00926    ast_rtp_pt_clear(tmp->rtp);
00927 
00928    /* add user configured codec capabilites */
00929    if (client->capability)
00930       tmp->capability = client->capability;
00931    else if (global_capability)
00932       tmp->capability = global_capability;
00933 
00934    tmp->parent = client;
00935    if (!tmp->rtp) {
00936       ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00937       ast_free(tmp);
00938       return NULL;
00939    }
00940 
00941    /* Set CALLERID(name) to the full JID of the remote peer */
00942    ast_copy_string(tmp->cid_name, tmp->them, sizeof(tmp->cid_name));
00943 
00944    if(strchr(tmp->us, '/')) {
00945       data = ast_strdupa(tmp->us);
00946       exten = strsep(&data, "/");
00947    } else
00948       exten = tmp->us;
00949    ast_copy_string(tmp->exten,  exten, sizeof(tmp->exten));
00950    ast_mutex_init(&tmp->lock);
00951    ast_mutex_lock(&gtalklock);
00952    tmp->next = client->p;
00953    client->p = tmp;
00954    ast_mutex_unlock(&gtalklock);
00955    return tmp;
00956 }

static int gtalk_answer ( struct ast_channel ast  )  [static]

Definition at line 494 of file chan_gtalk.c.

References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), EVENT_FLAG_SYSTEM, gtalk_invite(), gtalk_pvt::lock, manager_event, ast_channel::name, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.

00495 {
00496    struct gtalk_pvt *p = ast->tech_pvt;
00497    int res = 0;
00498    
00499    ast_debug(1, "Answer!\n");
00500    ast_mutex_lock(&p->lock);
00501    gtalk_invite(p, p->them, p->us,p->sid, 0);
00502    manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n",
00503       ast->name, "GTALK", p->sid);
00504    ast_mutex_unlock(&p->lock);
00505    return res;
00506 }

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

01548 {
01549    struct gtalk_pvt *p = ast->tech_pvt;
01550 
01551    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01552       ast_log(LOG_WARNING, "gtalk_call called on %s, neither down nor reserved\n", ast->name);
01553       return -1;
01554    }
01555 
01556    ast_setstate(ast, AST_STATE_RING);
01557    if (!p->ringrule) {
01558       ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01559       p->ringrule = iks_filter_add_rule(p->parent->connection->f, gtalk_ringing_ack, p,
01560                      IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01561    } else
01562       ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01563 
01564    gtalk_invite(p, p->them, p->us, p->sid, 1);
01565    gtalk_create_candidates(p->parent, p, p->sid, p->them, p->us);
01566 
01567    return 0;
01568 }

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

Definition at line 754 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_aji_send(), ast_calloc, ast_copy_string(), ast_find_ourip(), ast_free, ast_inet_ntoa(), ast_log(), ast_random(), ast_rtp_get_us(), ast_strlen_zero(), bindaddr, gtalk::connection, externip, 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, pass, gtalk_candidate::password, gtalk_candidate::port, gtalk_candidate::preference, gtalk_candidate::protocol, gtalk_pvt::rtp, gtalk_pvt::sid, gtalk_candidate::type, and gtalk_candidate::username.

Referenced by gtalk_call(), and gtalk_newcall().

00755 {
00756    struct gtalk_candidate *tmp;
00757    struct aji_client *c = client->connection;
00758    struct gtalk_candidate *ours1 = NULL, *ours2 = NULL;
00759    struct sockaddr_in sin;
00760    struct sockaddr_in dest;
00761    struct in_addr us;
00762    iks *iq, *gtalk, *candidate, *transport;
00763    char user[17], pass[17], preference[5], port[7];
00764 
00765 
00766    iq = iks_new("iq");
00767    gtalk = iks_new("session");
00768    candidate = iks_new("candidate");
00769    transport = iks_new("transport");
00770    if (!iq || !gtalk || !candidate || !transport) {
00771       ast_log(LOG_ERROR, "Memory allocation error\n");
00772       goto safeout;
00773    }
00774    ours1 = ast_calloc(1, sizeof(*ours1));
00775    ours2 = ast_calloc(1, sizeof(*ours2));
00776    if (!ours1 || !ours2)
00777       goto safeout;
00778 
00779    iks_insert_attrib(transport, "xmlns","http://www.google.com/transport/p2p");
00780    iks_insert_node(iq, gtalk);
00781    iks_insert_node(gtalk,transport);
00782    iks_insert_node(transport, candidate);
00783 
00784    for (; p; p = p->next) {
00785       if (!strcasecmp(p->sid, sid))
00786          break;
00787    }
00788 
00789    if (!p) {
00790       ast_log(LOG_NOTICE, "No matching gtalk session - SID %s!\n", sid);
00791       goto safeout;
00792    }
00793 
00794    ast_rtp_get_us(p->rtp, &sin);
00795    ast_find_ourip(&us, bindaddr);
00796 
00797    /* Setup our gtalk candidates */
00798    ast_copy_string(ours1->name, "rtp", sizeof(ours1->name));
00799    ours1->port = ntohs(sin.sin_port);
00800    ours1->preference = 1;
00801    snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00802    snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00803    ast_copy_string(ours1->username, user, sizeof(ours1->username));
00804    ast_copy_string(ours1->password, pass, sizeof(ours1->password));
00805    ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
00806    ours1->protocol = AJI_PROTOCOL_UDP;
00807    ours1->type = AJI_CONNECT_LOCAL;
00808    ours1->generation = 0;
00809    p->ourcandidates = ours1;
00810 
00811    if (!ast_strlen_zero(externip)) {
00812       /* XXX We should really stun for this one not just go with externip XXX */
00813       snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00814       snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00815       ast_copy_string(ours2->username, user, sizeof(ours2->username));
00816       ast_copy_string(ours2->password, pass, sizeof(ours2->password));
00817       ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
00818       ast_copy_string(ours2->name, "rtp", sizeof(ours1->name));
00819       ours2->port = ntohs(sin.sin_port);
00820       ours2->preference = 0.9;
00821       ours2->protocol = AJI_PROTOCOL_UDP;
00822       ours2->type = AJI_CONNECT_STUN;
00823       ours2->generation = 0;
00824       ours1->next = ours2;
00825       ours2 = NULL;
00826    }
00827    ours1 = NULL;
00828    dest.sin_addr = __ourip;
00829    dest.sin_port = sin.sin_port;
00830 
00831 
00832    for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
00833       snprintf(port, sizeof(port), "%d", tmp->port);
00834       snprintf(preference, sizeof(preference), "%.2f", tmp->preference);
00835       iks_insert_attrib(iq, "from", to);
00836       iks_insert_attrib(iq, "to", from);
00837       iks_insert_attrib(iq, "type", "set");
00838       iks_insert_attrib(iq, "id", c->mid);
00839       ast_aji_increment_mid(c->mid);
00840       iks_insert_attrib(gtalk, "type", "transport-info");
00841       iks_insert_attrib(gtalk, "id", sid);
00842       iks_insert_attrib(gtalk, "initiator", (p->initiator) ? to : from);
00843       iks_insert_attrib(gtalk, "xmlns", GOOGLE_NS);
00844       iks_insert_attrib(candidate, "name", tmp->name);
00845       iks_insert_attrib(candidate, "address", tmp->ip);
00846       iks_insert_attrib(candidate, "port", port);
00847       iks_insert_attrib(candidate, "username", tmp->username);
00848       iks_insert_attrib(candidate, "password", tmp->password);
00849       iks_insert_attrib(candidate, "preference", preference);
00850       if (tmp->protocol == AJI_PROTOCOL_UDP)
00851          iks_insert_attrib(candidate, "protocol", "udp");
00852       if (tmp->protocol == AJI_PROTOCOL_SSLTCP)
00853          iks_insert_attrib(candidate, "protocol", "ssltcp");
00854       if (tmp->type == AJI_CONNECT_STUN)
00855          iks_insert_attrib(candidate, "type", "stun");
00856       if (tmp->type == AJI_CONNECT_LOCAL)
00857          iks_insert_attrib(candidate, "type", "local");
00858       if (tmp->type == AJI_CONNECT_RELAY)
00859          iks_insert_attrib(candidate, "type", "relay");
00860       iks_insert_attrib(candidate, "network", "0");
00861       iks_insert_attrib(candidate, "generation", "0");
00862       ast_aji_send(c, iq);
00863    }
00864    p->laststun = 0;
00865 
00866 safeout:
00867    if (ours1)
00868       ast_free(ours1);
00869    if (ours2)
00870       ast_free(ours2);
00871    iks_delete(iq);
00872    iks_delete(gtalk);
00873    iks_delete(candidate);
00874    iks_delete(transport);
00875 
00876    return 1;
00877 }

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 1793 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, gtalk::parkinglot, prefs, gtalk::prefs, gtalk::user, and var.

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

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

Definition at line 1474 of file chan_gtalk.c.

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

Referenced by gtalk_digit_begin(), and gtalk_digit_end().

01475 {
01476    struct gtalk_pvt *p = ast->tech_pvt;
01477    struct gtalk *client = p->parent;
01478    iks *iq, *gtalk, *dtmf;
01479    char buffer[2] = {digit, '\0'};
01480    iq = iks_new("iq");
01481    gtalk = iks_new("gtalk");
01482    dtmf = iks_new("dtmf");
01483    if(!iq || !gtalk || !dtmf) {
01484       iks_delete(iq);
01485       iks_delete(gtalk);
01486       iks_delete(dtmf);
01487       ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
01488       return -1;
01489    }
01490 
01491    iks_insert_attrib(iq, "type", "set");
01492    iks_insert_attrib(iq, "to", p->them);
01493    iks_insert_attrib(iq, "from", p->us);
01494    iks_insert_attrib(iq, "id", client->connection->mid);
01495    ast_aji_increment_mid(client->connection->mid);
01496    iks_insert_attrib(gtalk, "xmlns", "http://jabber.org/protocol/gtalk");
01497    iks_insert_attrib(gtalk, "action", "session-info");
01498    iks_insert_attrib(gtalk, "initiator", p->initiator ? p->us: p->them);
01499    iks_insert_attrib(gtalk, "sid", p->sid);
01500    iks_insert_attrib(dtmf, "xmlns", "http://jabber.org/protocol/gtalk/info/dtmf");
01501    iks_insert_attrib(dtmf, "code", buffer);
01502    iks_insert_node(iq, gtalk);
01503    iks_insert_node(gtalk, dtmf);
01504 
01505    ast_mutex_lock(&p->lock);
01506    if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
01507       iks_insert_attrib(dtmf, "action", "button-down");
01508    } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
01509       iks_insert_attrib(dtmf, "action", "button-up");
01510    }
01511    ast_aji_send(client->connection, iq);
01512 
01513    iks_delete(iq);
01514    iks_delete(gtalk);
01515    iks_delete(dtmf);
01516    ast_mutex_unlock(&p->lock);
01517    return 0;
01518 }

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

Definition at line 1464 of file chan_gtalk.c.

References chan, and gtalk_digit().

01465 {
01466    return gtalk_digit(chan, digit, 0);
01467 }

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

Definition at line 1469 of file chan_gtalk.c.

References chan, and gtalk_digit().

01470 {
01471    return gtalk_digit(chan, digit, duration);
01472 }

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

CLI command "gtalk reload".

Definition at line 1700 of file chan_gtalk.c.

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

01701 {
01702    switch (cmd) {
01703    case CLI_INIT:
01704       e->command = "gtalk reload";
01705       e->usage =
01706          "Usage: gtalk reload\n"
01707          "       Reload gtalk channel driver.\n";
01708       return NULL;
01709    case CLI_GENERATE:
01710       return NULL;
01711    }  
01712    
01713    ast_verbose("IT DOES WORK!\n");
01714    return CLI_SUCCESS;
01715 }

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

Definition at line 1430 of file chan_gtalk.c.

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

01431 {
01432    struct gtalk_pvt *p = newchan->tech_pvt;
01433    ast_mutex_lock(&p->lock);
01434 
01435    if ((p->owner != oldchan)) {
01436       ast_mutex_unlock(&p->lock);
01437       return -1;
01438    }
01439    if (p->owner == oldchan)
01440       p->owner = newchan;
01441    ast_mutex_unlock(&p->lock);
01442    return 0;
01443 }

static void gtalk_free_candidates ( struct gtalk_candidate candidate  )  [static]

Definition at line 1078 of file chan_gtalk.c.

References ast_free, last, and gtalk_candidate::next.

Referenced by gtalk_free_pvt().

01079 {
01080    struct gtalk_candidate *last;
01081    while (candidate) {
01082       last = candidate;
01083       candidate = candidate->next;
01084       ast_free(last);
01085    }
01086 }

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

Definition at line 1088 of file chan_gtalk.c.

References ast_free, ast_log(), ast_rtp_destroy(), gtalk::connection, aji_client::f, 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().

01089 {
01090    struct gtalk_pvt *cur, *prev = NULL;
01091    cur = client->p;
01092    while (cur) {
01093       if (cur == p) {
01094          if (prev)
01095             prev->next = p->next;
01096          else
01097             client->p = p->next;
01098          break;
01099       }
01100       prev = cur;
01101       cur = cur->next;
01102    }
01103    if (p->ringrule)
01104       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
01105    if (p->owner)
01106       ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
01107    if (p->rtp)
01108       ast_rtp_destroy(p->rtp);
01109    if (p->vrtp)
01110       ast_rtp_destroy(p->vrtp);
01111    gtalk_free_candidates(p->theircandidates);
01112    ast_free(p);
01113 }

static int gtalk_get_codec ( struct ast_channel chan  )  [static]

Definition at line 526 of file chan_gtalk.c.

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

00527 {
00528    struct gtalk_pvt *p = chan->tech_pvt;
00529    return p->peercapability;
00530 }

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

Definition at line 508 of file chan_gtalk.c.

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

00509 {
00510    struct gtalk_pvt *p = chan->tech_pvt;
00511    enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
00512 
00513    if (!p)
00514       return res;
00515 
00516    ast_mutex_lock(&p->lock);
00517    if (p->rtp){
00518       *rtp = p->rtp;
00519       res = AST_RTP_TRY_PARTIAL;
00520    }
00521    ast_mutex_unlock(&p->lock);
00522 
00523    return res;
00524 }

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

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

00662 {
00663    struct gtalk_pvt *tmp;
00664    iks *dtmfnode = NULL, *dtmfchild = NULL;
00665    char *dtmf;
00666    char *from;
00667    /* Make sure our new call doesn't exist yet */
00668    for (tmp = client->p; tmp; tmp = tmp->next) {
00669       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || iks_find_with_attrib(pak->x, "gtalk", "sid", tmp->sid))
00670          break;
00671    }
00672    from = iks_find_attrib(pak->x, "to");
00673    if(!from)
00674       from = client->connection->jid->full;
00675 
00676 
00677    if (tmp) {
00678       if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) {
00679          gtalk_response(client, from, pak,
00680                "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
00681                "unsupported-dtmf-method xmlns='http://jabber.org/protocol/gtalk/info/dtmf#errors'");
00682          return -1;
00683       }
00684       if ((dtmfnode = iks_find(pak->x, "dtmf"))) {
00685          if((dtmf = iks_find_attrib(dtmfnode, "code"))) {
00686             if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) {
00687                struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00688                f.subclass = dtmf[0];
00689                ast_queue_frame(tmp->owner, &f);
00690                ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00691             } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) {
00692                struct ast_frame f = {AST_FRAME_DTMF_END, };
00693                f.subclass = dtmf[0];
00694                ast_queue_frame(tmp->owner, &f);
00695                ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00696             } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */
00697                struct ast_frame f = {AST_FRAME_DTMF, };
00698                f.subclass = dtmf[0];
00699                ast_queue_frame(tmp->owner, &f);
00700                ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00701             }
00702          }
00703       } else if ((dtmfnode = iks_find_with_attrib(pak->x, "gtalk", "action", "session-info"))) {
00704          if((dtmfchild = iks_find(dtmfnode, "dtmf"))) {
00705             if((dtmf = iks_find_attrib(dtmfchild, "code"))) {
00706                if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) {
00707                   struct ast_frame f = {AST_FRAME_DTMF_END, };
00708                   f.subclass = dtmf[0];
00709                   ast_queue_frame(tmp->owner, &f);
00710                   ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00711                } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) {
00712                   struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00713                   f.subclass = dtmf[0];
00714                   ast_queue_frame(tmp->owner, &f);
00715                   ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00716                }
00717             }
00718          }
00719       }
00720       gtalk_response(client, from, pak, NULL, NULL);
00721       return 1;
00722    } else
00723       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00724 
00725    gtalk_response(client, from, pak, NULL, NULL);
00726    return 1;
00727 }

static int gtalk_hangup ( struct ast_channel ast  )  [static]

Hangup a call through the gtalk proxy channel.

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

01572 {
01573    struct gtalk_pvt *p = ast->tech_pvt;
01574    struct gtalk *client;
01575 
01576    ast_mutex_lock(&p->lock);
01577    client = p->parent;
01578    p->owner = NULL;
01579    ast->tech_pvt = NULL;
01580    if (!p->alreadygone)
01581       gtalk_action(client, p, "terminate");
01582    ast_mutex_unlock(&p->lock);
01583 
01584    gtalk_free_pvt(client, p);
01585    ast_module_unref(ast_module_info->self);
01586 
01587    return 0;
01588 }

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

Definition at line 729 of file chan_gtalk.c.

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

Referenced by gtalk_parser().

00730 {
00731    struct gtalk_pvt *tmp;
00732    char *from;
00733 
00734    ast_debug(1, "The client is %s\n", client->name);
00735    /* Make sure our new call doesn't exist yet */
00736    for (tmp = client->p; tmp; tmp = tmp->next) {
00737       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00738          break;
00739    }
00740    from = iks_find_attrib(pak->x, "to");
00741    if(!from)
00742       from = client->connection->jid->full;
00743 
00744    if (tmp) {
00745       tmp->alreadygone = 1;
00746       if (tmp->owner)
00747          ast_queue_hangup(tmp->owner);
00748    } else
00749       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00750    gtalk_response(client, from, pak, NULL, NULL);
00751    return 1;
00752 }

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

Definition at line 1445 of file chan_gtalk.c.

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

01446 {
01447    int res = 0;
01448 
01449    switch (condition) {
01450    case AST_CONTROL_HOLD:
01451       ast_moh_start(ast, data, NULL);
01452       break;
01453    case AST_CONTROL_UNHOLD:
01454       ast_moh_stop(ast);
01455       break;
01456    default:
01457       ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01458       res = -1;
01459    }
01460 
01461    return res;
01462 }

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

Definition at line 377 of file chan_gtalk.c.

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

Referenced by gtalk_answer(), and gtalk_call().

00378 {
00379    struct gtalk *client = p->parent;
00380    iks *iq, *gtalk, *dcodecs, *payload_telephone, *transport;
00381    int x;
00382    int pref_codec = 0;
00383    int alreadysent = 0;
00384    int codecs_num = 0;
00385 
00386    iq = iks_new("iq");
00387    gtalk = iks_new("session");
00388    dcodecs = iks_new("description");
00389    transport = iks_new("transport");
00390    payload_telephone = iks_new("payload-type");
00391    if (!(iq && gtalk && dcodecs && transport && payload_telephone)){
00392       iks_delete(iq);
00393       iks_delete(gtalk);
00394       iks_delete(dcodecs);
00395       iks_delete(transport);
00396       iks_delete(payload_telephone);
00397       
00398       ast_log(LOG_ERROR, "Could not allocate iksemel nodes\n");
00399       return 0;
00400    }
00401    iks_insert_attrib(dcodecs, "xmlns", "http://www.google.com/session/phone");
00402    iks_insert_attrib(dcodecs, "xml:lang", "en");
00403 
00404    for (x = 0; x < 32; x++) {
00405       if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
00406          break;
00407       if (!(client->capability & pref_codec))
00408          continue;
00409       if (alreadysent & pref_codec)
00410          continue;
00411       codecs_num = add_codec_to_answer(p, pref_codec, dcodecs);
00412       alreadysent |= pref_codec;
00413    }
00414    
00415    if (codecs_num) {
00416       /* only propose DTMF within an audio session */
00417       iks_insert_attrib(payload_telephone, "id", "106");
00418       iks_insert_attrib(payload_telephone, "name", "telephone-event");
00419       iks_insert_attrib(payload_telephone, "clockrate", "8000");
00420    }
00421    iks_insert_attrib(transport,"xmlns","http://www.google.com/transport/p2p");
00422    
00423    iks_insert_attrib(iq, "type", "set");
00424    iks_insert_attrib(iq, "to", to);
00425    iks_insert_attrib(iq, "from", from);
00426    iks_insert_attrib(iq, "id", client->connection->mid);
00427    ast_aji_increment_mid(client->connection->mid);
00428 
00429    iks_insert_attrib(gtalk, "xmlns", "http://www.google.com/session");
00430    iks_insert_attrib(gtalk, "type",initiator ? "initiate": "accept");
00431    iks_insert_attrib(gtalk, "initiator", initiator ? from : to);
00432    iks_insert_attrib(gtalk, "id", sid);
00433    iks_insert_node(iq, gtalk);
00434    iks_insert_node(gtalk, dcodecs);
00435    iks_insert_node(gtalk, transport);
00436    iks_insert_node(dcodecs, payload_telephone);
00437 
00438    ast_aji_send(client->connection, iq);
00439 
00440    iks_delete(payload_telephone);
00441    iks_delete(transport);
00442    iks_delete(dcodecs);
00443    iks_delete(gtalk);
00444    iks_delete(iq);
00445    return 1;
00446 }

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

Definition at line 448 of file chan_gtalk.c.

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

Referenced by gtalk_newcall().

00449 {
00450    iks *iq, *session, *transport;
00451    iq = iks_new("iq");
00452    session = iks_new("session");
00453    transport = iks_new("transport");
00454    if(!(iq && session && transport)) {
00455       iks_delete(iq);
00456       iks_delete(session);
00457       iks_delete(transport);
00458       ast_log(LOG_ERROR, " Unable to allocate IKS node\n");
00459       return -1;
00460    }
00461    iks_insert_attrib(iq, "from", from);
00462    iks_insert_attrib(iq, "to", to);
00463    iks_insert_attrib(iq, "type", "set");
00464    iks_insert_attrib(iq, "id",p->parent->connection->mid);
00465    ast_aji_increment_mid(p->parent->connection->mid);
00466    iks_insert_attrib(session, "type", "transport-accept");
00467    iks_insert_attrib(session, "id", sid);
00468    iks_insert_attrib(session, "initiator", initiator ? from : to);
00469    iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
00470    iks_insert_attrib(transport, "xmlns", "http://www.google.com/transport/p2p");
00471    iks_insert_node(iq,session);
00472    iks_insert_node(session,transport);
00473    ast_aji_send(p->parent->connection, iq);
00474 
00475    iks_delete(transport);
00476    iks_delete(session);
00477    iks_delete(iq);
00478    return 1;
00479 
00480 }

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

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

00638 {
00639    struct gtalk_pvt *tmp;
00640    char *from;
00641 
00642    ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00643    /* find corresponding call */
00644    for (tmp = client->p; tmp; tmp = tmp->next) {
00645       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00646          break;
00647    }
00648 
00649    from = iks_find_attrib(pak->x, "to");
00650    if(!from)
00651       from = client->connection->jid->full;
00652 
00653    if (!tmp)
00654       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00655 
00656    /* answer 'iq' packet to let the remote peer know that we're alive */
00657    gtalk_response(client, from, pak, NULL, NULL);
00658    return 1;
00659 }

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

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

00585 {
00586    struct gtalk_pvt *tmp;
00587    char *from;
00588    iks *codec;
00589    char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ];
00590    int peernoncodeccapability;
00591 
00592    ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00593    /* Make sure our new call doesn't exist yet */
00594    for (tmp = client->p; tmp; tmp = tmp->next) {
00595       if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00596          break;
00597    }
00598 
00599    /* codec points to the first <payload-type/> tag */
00600    codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
00601    while (codec) {
00602       ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")));
00603       ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
00604       codec = iks_next_tag(codec);
00605    }
00606    
00607    /* Now gather all of the codecs that we are asked for */
00608    ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability);
00609    
00610    /* at this point, we received an awser from the remote Gtalk client,
00611       which allows us to compare capabilities */
00612    tmp->jointcapability = tmp->capability & tmp->peercapability;
00613    if (!tmp->jointcapability) {
00614       ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->capability),
00615          ast_getformatname_multiple(s2, BUFSIZ, tmp->peercapability),
00616          ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcapability));
00617       /* close session if capabilities don't match */
00618       ast_queue_hangup(tmp->owner);
00619 
00620       return -1;
00621 
00622    }  
00623    
00624    from = iks_find_attrib(pak->x, "to");
00625    if(!from)
00626       from = client->connection->jid->full;
00627 
00628    if (tmp) {
00629       if (tmp->owner)
00630          ast_queue_control(tmp->owner, AST_CONTROL_ANSWER);
00631    } else
00632       ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00633    gtalk_response(client, from, pak, NULL, NULL);
00634    return 1;
00635 }

static int gtalk_load_config ( void   )  [static]

Definition at line 1854 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, config_flags, context, default_jbconf, global_capability, global_jbconf, GOOGLE_CONFIG, hp, LOG_WARNING, parkinglot, prefs, and var.

Referenced by load_module().

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

static void gtalk_member_destroy ( struct gtalk obj  )  [static]

Definition at line 235 of file chan_gtalk.c.

References ast_free.

Referenced by gtalk_parser(), and unload_module().

00236 {
00237    ast_free(obj);
00238 }

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 959 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_channel_set_fd(), 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_codec_setpref(), 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, EVENT_FLAG_SYSTEM, ast_channel::exten, gtalk_pvt::exten, global_capability, global_jbconf, gtalk_tech, ast_channel::hangupcause, gtalk_pvt::jointcapability, language, gtalk::language, LOG_WARNING, manager_event, musicclass, gtalk::musicclass, ast_channel::name, ast_channel::nativeformats, gtalk_pvt::owner, parkinglot, gtalk::parkinglot, 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, gtalk_pvt::sid, ast_channel::tech, ast_channel::tech_pvt, gtalk_pvt::us, gtalk_pvt::vrtp, and ast_channel::writeformat.

Referenced by gtalk_newcall(), and gtalk_request().

00960 {
00961    struct ast_channel *tmp;
00962    int fmt;
00963    int what;
00964    const char *n2;
00965 
00966    if (title)
00967       n2 = title;
00968    else
00969       n2 = i->us;
00970    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);
00971    if (!tmp) {
00972       ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n");
00973       return NULL;
00974    }
00975    tmp->tech = &gtalk_tech;
00976 
00977    /* Select our native format based on codec preference until we receive
00978       something from another device to the contrary. */
00979    if (i->jointcapability)
00980       what = i->jointcapability;
00981    else if (i->capability)
00982       what = i->capability;
00983    else
00984       what = global_capability;
00985 
00986    /* Set Frame packetization */
00987    if (i->rtp)
00988       ast_rtp_codec_setpref(i->rtp, &i->prefs);
00989 
00990    tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
00991    fmt = ast_best_codec(tmp->nativeformats);
00992 
00993    if (i->rtp) {
00994       ast_rtp_setstun(i->rtp, 1);
00995       ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
00996       ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
00997    }
00998    if (i->vrtp) {
00999       ast_rtp_setstun(i->rtp, 1);
01000       ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
01001       ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
01002    }
01003    if (state == AST_STATE_RING)
01004       tmp->rings = 1;
01005    tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01006    tmp->writeformat = fmt;
01007    tmp->rawwriteformat = fmt;
01008    tmp->readformat = fmt;
01009    tmp->rawreadformat = fmt;
01010    tmp->tech_pvt = i;
01011 
01012    tmp->callgroup = client->callgroup;
01013    tmp->pickupgroup = client->pickupgroup;
01014    tmp->cid.cid_pres = client->callingpres;
01015    if (!ast_strlen_zero(client->accountcode))
01016       ast_string_field_set(tmp, accountcode, client->accountcode);
01017    if (client->amaflags)
01018       tmp->amaflags = client->amaflags;
01019    if (!ast_strlen_zero(client->language))
01020       ast_string_field_set(tmp, language, client->language);
01021    if (!ast_strlen_zero(client->musicclass))
01022       ast_string_field_set(tmp, musicclass, client->musicclass);
01023    if (!ast_strlen_zero(client->parkinglot))
01024       ast_string_field_set(tmp, parkinglot, client->parkinglot);
01025    i->owner = tmp;
01026    ast_module_ref(ast_module_info->self);
01027    ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
01028    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01029 
01030    if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
01031       tmp->cid.cid_dnid = ast_strdup(i->exten);
01032    tmp->priority = 1;
01033    if (i->rtp)
01034       ast_jb_configure(tmp, &global_jbconf);
01035    if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
01036       ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01037       tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
01038       ast_hangup(tmp);
01039       tmp = NULL;
01040    } else {
01041       manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
01042          "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n",
01043          i->owner ? i->owner->name : "", "Gtalk", i->sid);
01044    }
01045    return tmp;
01046 }

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

Definition at line 1116 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, chan, 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().

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

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

Definition at line 1717 of file chan_gtalk.c.

References ast_debug, 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(), and LOG_NOTICE.

Referenced by gtalk_create_member().

01718 {
01719    struct gtalk *client = ASTOBJ_REF((struct gtalk *) data);
01720 
01721    if (iks_find_attrib(pak->x, "type") && !strcmp(iks_find_attrib (pak->x, "type"),"error")) {
01722       ast_log(LOG_NOTICE, "Remote peer reported an error, trying to establish the call anyway\n");
01723    }
01724    else if (iks_find_with_attrib(pak->x, "session", "type", "initiate")) {
01725       /* New call */
01726       gtalk_newcall(client, pak);
01727    } else if (iks_find_with_attrib(pak->x, "session", "type", "candidates") || iks_find_with_attrib(pak->x, "session", "type", "transport-info")) {
01728       ast_debug(3, "About to add candidate!\n");
01729       gtalk_add_candidate(client, pak);
01730       ast_debug(3, "Candidate Added!\n");
01731    } else if (iks_find_with_attrib(pak->x, "session", "type", "accept")) {
01732       gtalk_is_answered(client, pak);
01733    } else if (iks_find_with_attrib(pak->x, "session", "type", "transport-accept")) {
01734       gtalk_is_accepted(client, pak);
01735    } else if (iks_find_with_attrib(pak->x, "session", "type", "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) {
01736       gtalk_handle_dtmf(client, pak);
01737    } else if (iks_find_with_attrib(pak->x, "session", "type", "terminate")) {
01738       gtalk_hangup_farend(client, pak);
01739    } else if (iks_find_with_attrib(pak->x, "session", "type", "reject")) {
01740       gtalk_hangup_farend(client, pak);
01741    }
01742    ASTOBJ_UNREF(client, gtalk_member_destroy);
01743    return IKS_FILTER_EAT;
01744 }

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

Definition at line 1375 of file chan_gtalk.c.

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

01376 {
01377    struct ast_frame *fr;
01378    struct gtalk_pvt *p = ast->tech_pvt;
01379 
01380    ast_mutex_lock(&p->lock);
01381    fr = gtalk_rtp_read(ast, p);
01382    ast_mutex_unlock(&p->lock);
01383    return fr;
01384 }

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

Part of PBX interface.

Definition at line 1591 of file chan_gtalk.c.

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

01592 {
01593    struct gtalk_pvt *p = NULL;
01594    struct gtalk *client = NULL;
01595    char *sender = NULL, *to = NULL, *s = NULL;
01596    struct ast_channel *chan = NULL;
01597 
01598    if (data) {
01599       s = ast_strdupa(data);
01600       if (s) {
01601          sender = strsep(&s, "/");
01602          if (sender && (sender[0] != '\0'))
01603             to = strsep(&s, "/");
01604          if (!to) {
01605             ast_log(LOG_ERROR, "Bad arguments in Gtalk Dialstring: %s\n", (char*) data);
01606             return NULL;
01607          }
01608       }
01609    }
01610 
01611    client = find_gtalk(to, sender);
01612    if (!client) {
01613       ast_log(LOG_WARNING, "Could not find recipient.\n");
01614       return NULL;
01615    }
01616    if (!strcasecmp(client->name, "guest")){
01617       /* the guest account is not tied to any configured XMPP client,
01618          let's set it now */
01619       client->connection = ast_aji_get_client(sender);
01620       if (!client->connection) {
01621          ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01622          return NULL;
01623       }
01624    }
01625        
01626    ASTOBJ_WRLOCK(client);
01627    p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL);
01628    if (p)
01629       chan = gtalk_new(client, p, AST_STATE_DOWN, to);
01630 
01631    ASTOBJ_UNLOCK(client);
01632    return chan;
01633 }

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

Definition at line 552 of file chan_gtalk.c.

References ast_aji_send(), and gtalk::connection.

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

00553 {
00554    iks *response = NULL, *error = NULL, *reason = NULL;
00555    int res = -1;
00556 
00557    response = iks_new("iq");
00558    if (response) {
00559       iks_insert_attrib(response, "type", "result");
00560       iks_insert_attrib(response, "from", from);
00561       iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
00562       iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
00563       if (reasonstr) {
00564          error = iks_new("error");
00565          if (error) {
00566             iks_insert_attrib(error, "type", "cancel");
00567             reason = iks_new(reasonstr);
00568             if (reason)
00569                iks_insert_node(error, reason);
00570             iks_insert_node(response, error);
00571          }
00572       }
00573       ast_aji_send(client->connection, response);
00574       res = 0;
00575    }
00576 
00577    iks_delete(reason);
00578    iks_delete(error);
00579    iks_delete(response);
00580 
00581    return res;
00582 }

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

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

00483 {
00484    struct gtalk_pvt *p = data;
00485 
00486    if (p->ringrule)
00487       iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00488    p->ringrule = NULL;
00489    if (p->owner)
00490       ast_queue_control(p->owner, AST_CONTROL_RINGING);
00491    return IKS_FILTER_EAT;
00492 }

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

Definition at line 1347 of file chan_gtalk.c.

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

Referenced by gtalk_read().

01348 {
01349    struct ast_frame *f;
01350 
01351    if (!p->rtp)
01352       return &ast_null_frame;
01353    f = ast_rtp_read(p->rtp);
01354    gtalk_update_stun(p->parent, p);
01355    if (p->owner) {
01356       /* We already hold the channel lock */
01357       if (f->frametype == AST_FRAME_VOICE) {
01358          if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
01359             ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
01360             p->owner->nativeformats =
01361                (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
01362             ast_set_read_format(p->owner, p->owner->readformat);
01363             ast_set_write_format(p->owner, p->owner->writeformat);
01364          }
01365 /*       if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
01366             f = ast_dsp_process(p->owner, p->vad, f);
01367             if (option_debug && f && (f->frametype == AST_FRAME_DTMF))
01368                ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass);
01369               } */
01370       }
01371    }
01372    return f;
01373 }

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

Definition at line 1520 of file chan_gtalk.c.

References ast_log(), and LOG_NOTICE.

01521 {
01522    ast_log(LOG_NOTICE, "XXX Implement gtalk sendhtml XXX\n");
01523 
01524    return -1;
01525 }

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

Definition at line 532 of file chan_gtalk.c.

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

00533 {
00534    struct gtalk_pvt *p;
00535 
00536    p = chan->tech_pvt;
00537    if (!p)
00538       return -1;
00539    ast_mutex_lock(&p->lock);
00540 
00541 /* if (rtp)
00542       ast_rtp_get_peer(rtp, &p->redirip);
00543    else
00544       memset(&p->redirip, 0, sizeof(p->redirip));
00545    p->redircodecs = codecs; */
00546 
00547    /* Reset lastrtprx timer */
00548    ast_mutex_unlock(&p->lock);
00549    return 0;
00550 }

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

CLI command "gtalk show channels".

Definition at line 1636 of file chan_gtalk.c.

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

01637 {
01638 #define FORMAT  "%-30.30s  %-30.30s  %-15.15s  %-5.5s %-5.5s \n"
01639    struct gtalk_pvt *p;
01640    struct ast_channel *chan;
01641    int numchans = 0;
01642    char them[AJI_MAX_JIDLEN];
01643    char *jid = NULL;
01644    char *resource = NULL;
01645 
01646    switch (cmd) {
01647    case CLI_INIT:
01648       e->command = "gtalk show channels";
01649       e->usage =
01650          "Usage: gtalk show channels\n"
01651          "       Shows current state of the Gtalk channels.\n";
01652       return NULL;
01653    case CLI_GENERATE:
01654       return NULL;
01655    }
01656 
01657    if (a->argc != 3)
01658       return CLI_SHOWUSAGE;
01659 
01660    ast_mutex_lock(&gtalklock);
01661    ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
01662    ASTOBJ_CONTAINER_TRAVERSE(&gtalk_list, 1, {
01663       ASTOBJ_WRLOCK(iterator);
01664       p = iterator->p;
01665       while(p) {
01666          chan = p->owner;
01667          ast_copy_string(them, p->them, sizeof(them));
01668          jid = them;
01669          resource = strchr(them, '/');
01670          if (!resource)
01671             resource = "None";
01672          else {
01673             *resource = '\0';
01674             resource ++;
01675          }
01676          if (chan)
01677             ast_cli(a->fd, FORMAT, 
01678                chan->name,
01679                jid,
01680                resource,
01681                ast_getformatname(chan->readformat),
01682                ast_getformatname(chan->writeformat)               
01683                );
01684          else 
01685             ast_log(LOG_WARNING, "No available channel\n");
01686          numchans ++;
01687          p = p->next;
01688       }
01689       ASTOBJ_UNLOCK(iterator);
01690    });
01691 
01692    ast_mutex_unlock(&gtalklock);
01693 
01694    ast_cli(a->fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : "");
01695    return CLI_SUCCESS;
01696 #undef FORMAT
01697 }

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

Definition at line 1218 of file chan_gtalk.c.

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

Referenced by gtalk_add_candidate(), and gtalk_rtp_read().

01219 {
01220    struct gtalk_candidate *tmp;
01221    struct hostent *hp;
01222    struct ast_hostent ahp;
01223    struct sockaddr_in sin;
01224    struct sockaddr_in aux;
01225 
01226    if (time(NULL) == p->laststun)
01227       return 0;
01228 
01229    tmp = p->theircandidates;
01230    p->laststun = time(NULL);
01231    while (tmp) {
01232       char username[256];
01233 
01234       /* Find the IP address of the host */
01235       hp = ast_gethostbyname(tmp->ip, &ahp);
01236       sin.sin_family = AF_INET;
01237       memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01238       sin.sin_port = htons(tmp->port);
01239       snprintf(username, sizeof(username), "%s%s", tmp->username,
01240           p->ourcandidates->username);
01241       
01242       /* Find out the result of the STUN */
01243       ast_rtp_get_peer(p->rtp, &aux);
01244 
01245       /* If the STUN result is different from the IP of the hostname,
01246          lock on the stun IP of the hostname advertised by the
01247          remote client */
01248       if (aux.sin_addr.s_addr && 
01249           aux.sin_addr.s_addr != sin.sin_addr.s_addr)
01250          ast_rtp_stun_request(p->rtp, &aux, username);
01251       else 
01252          ast_rtp_stun_request(p->rtp, &sin, username);
01253       
01254       if (aux.sin_addr.s_addr) {
01255          ast_debug(4, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip);
01256          ast_debug(4, "Sending STUN request to %s\n", tmp->ip);
01257       }
01258 
01259       tmp = tmp->next;
01260    }
01261    return 1;
01262 }

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

Send frame to media channel (rtp).

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

01388 {
01389    struct gtalk_pvt *p = ast->tech_pvt;
01390    int res = 0;
01391 
01392    switch (frame->frametype) {
01393    case AST_FRAME_VOICE:
01394       if (!(frame->subclass & ast->nativeformats)) {
01395          ast_log(LOG_WARNING,
01396                "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01397                frame->subclass, ast->nativeformats, ast->readformat,
01398                ast->writeformat);
01399          return 0;
01400       }
01401       if (p) {
01402          ast_mutex_lock(&p->lock);
01403          if (p->rtp) {
01404             res = ast_rtp_write(p->rtp, frame);
01405          }
01406          ast_mutex_unlock(&p->lock);
01407       }
01408       break;
01409    case AST_FRAME_VIDEO:
01410       if (p) {
01411          ast_mutex_lock(&p->lock);
01412          if (p->vrtp) {
01413             res = ast_rtp_write(p->vrtp, frame);
01414          }
01415          ast_mutex_unlock(&p->lock);
01416       }
01417       break;
01418    case AST_FRAME_IMAGE:
01419       return 0;
01420       break;
01421    default:
01422       ast_log(LOG_WARNING, "Can't send %d type frames with Gtalk write\n",
01423             frame->frametype);
01424       return 0;
01425    }
01426 
01427    return res;
01428 }

static int load_module ( void   )  [static]

Load module into PBX, register channel.

Definition at line 1981 of file chan_gtalk.c.

References __ourip, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_find_ourip(), ast_log(), ast_module_helper(), AST_MODULE_LOAD_DECLINE, ast_rtp_proto_register(), ASTOBJ_CONTAINER_INIT, bindaddr, 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.

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

static int reload ( void   )  [static]

Reload module.

Definition at line 2026 of file chan_gtalk.c.

02027 {
02028    return 0;
02029 }

static int unload_module ( void   )  [static]

Unload the gtalk channel from Asterisk.

Definition at line 2032 of file chan_gtalk.c.

References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, gtalk_cli, gtalk_list, gtalk_member_destroy(), gtalk_rtp, gtalk_tech, gtalklock, LOG_WARNING, gtalk_pvt::next, and gtalk_pvt::owner.

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


Variable Documentation

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

Definition at line 2067 of file chan_gtalk.c.

struct in_addr __ourip [static]

Definition at line 216 of file chan_gtalk.c.

Referenced by build_gateway(), find_subchannel_and_lock(), gtalk_create_candidates(), jingle_create_candidates(), load_module(), and reload_config().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 2067 of file chan_gtalk.c.

struct sockaddr_in bindaddr = { 0, } [static]

The address we bind to

Definition at line 212 of file chan_gtalk.c.

Referenced by gtalk_alloc(), gtalk_create_candidates(), gtalk_load_config(), jingle_alloc(), jingle_create_candidates(), jingle_load_config(), load_module(), reload_config(), and start_rtp().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 75 of file chan_gtalk.c.

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

Definition at line 160 of file chan_gtalk.c.

Referenced by ast_tcptls_client_start(), ast_tcptls_server_root(), ast_tcptls_server_start(), ast_tcptls_server_stop(), dump_cause(), handle_cli_ulimit(), load_rpt_vars(), misdn_cfg_get_desc(), and show_config_description().

char externip[16] [static]

Definition at line 231 of file chan_gtalk.c.

Referenced by gtalk_create_candidates(), jingle_create_candidates(), and jingle_load_config().

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

Definition at line 162 of file chan_gtalk.c.

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

struct ast_jb_conf global_jbconf [static]

Definition at line 82 of file chan_gtalk.c.

struct ast_cli_entry gtalk_cli[] [static]

Initial value:

 {
   { .handler =  gtalk_do_reload , .summary =  "Reload GoogleTalk configuration" ,__VA_ARGS__ },
   { .handler =  gtalk_show_channels , .summary =  "Show GoogleTalk channels" ,__VA_ARGS__ },
}

Definition at line 226 of file chan_gtalk.c.

Referenced by load_module(), and unload_module().

struct gtalk_container gtalk_list [static]

Definition at line 233 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 219 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 192 of file chan_gtalk.c.

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

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

Protect the interface list (of gtalk_pvt's)

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

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

struct sched_context* sched [static]

The scheduling context

Definition at line 214 of file chan_gtalk.c.


Generated on Fri Jun 19 12:10:12 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7