#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include <iksemel.h>
#include <pthread.h>
#include <ctype.h>
#include <gcrypt.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/stringfields.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astobj.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/jabber.h"
Go to the source code of this file.
Data Structures | |
struct | gtalk |
struct | gtalk_candidate |
struct | gtalk_container |
struct | gtalk_pvt |
Defines | |
#define | FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
#define | GOOGLE_CONFIG "gtalk.conf" |
#define | GOOGLE_NS "http://www.google.com/session" |
Enumerations | |
enum | gtalk_connect_type { AJI_CONNECT_STUN = 1, AJI_CONNECT_LOCAL = 2, AJI_CONNECT_RELAY = 3 } |
enum | gtalk_protocol { AJI_PROTOCOL_UDP = 1, AJI_PROTOCOL_SSLTCP = 2 } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | add_codec_to_answer (const struct gtalk_pvt *p, int codec, iks *dcodecs) |
static struct gtalk * | find_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_pvt * | gtalk_alloc (struct gtalk *client, const char *us, const char *them, const char *sid) |
static int | gtalk_answer (struct ast_channel *ast) |
static int | gtalk_call (struct ast_channel *ast, char *dest, int timeout) |
Initiate new call, part of PBX interface dest is the dial string. | |
static int | gtalk_create_candidates (struct gtalk *client, struct gtalk_pvt *p, char *sid, char *from, char *to) |
static int | gtalk_create_member (char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct gtalk *member) |
static int | gtalk_digit (struct ast_channel *ast, char digit, unsigned int duration) |
static int | gtalk_digit_begin (struct ast_channel *ast, char digit) |
static int | gtalk_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
static int | gtalk_do_reload (int fd, int argc, char **argv) |
CLI command "gtalk show channels". | |
static int | gtalk_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static void | gtalk_free_candidates (struct gtalk_candidate *candidate) |
static void | gtalk_free_pvt (struct gtalk *client, struct gtalk_pvt *p) |
static int | gtalk_get_codec (struct ast_channel *chan) |
static enum ast_rtp_get_result | gtalk_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
static int | gtalk_handle_dtmf (struct gtalk *client, ikspak *pak) |
static int | gtalk_hangup (struct ast_channel *ast) |
Hangup a call through the gtalk proxy channel. | |
static int | gtalk_hangup_farend (struct gtalk *client, ikspak *pak) |
static int | gtalk_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen) |
static int | gtalk_invite (struct gtalk_pvt *p, char *to, char *from, char *sid, int initiator) |
static int | gtalk_invite_response (struct gtalk_pvt *p, char *to, char *from, char *sid, int initiator) |
static int | gtalk_is_accepted (struct gtalk *client, ikspak *pak) |
static int | gtalk_is_answered (struct gtalk *client, ikspak *pak) |
static int | gtalk_load_config (void) |
static void | gtalk_member_destroy (struct gtalk *obj) |
static struct ast_channel * | gtalk_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_frame * | gtalk_read (struct ast_channel *ast) |
static struct ast_channel * | gtalk_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_frame * | gtalk_rtp_read (struct ast_channel *ast, struct gtalk_pvt *p) |
static int | gtalk_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen) |
static int | gtalk_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active) |
static int | gtalk_show_channels (int fd, int argc, char **argv) |
CLI command "gtalk show channels". | |
static int | gtalk_update_stun (struct gtalk *client, struct gtalk_pvt *p) |
static int | gtalk_write (struct ast_channel *ast, struct ast_frame *frame) |
Send frame to media channel (rtp). | |
static int | load_module (void) |
Load module into PBX, register channel. | |
static int | reload (void) |
Reload module. | |
static int | unload_module (void) |
Unload the gtalk channel from Asterisk. | |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Gtalk Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct in_addr | __ourip |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct sockaddr_in | bindaddr = { 0, } |
static struct ast_jb_conf | default_jbconf |
static const char | desc [] = "Gtalk Channel" |
static char | externip [16] |
GCRY_THREAD_OPTION_PTHREAD_IMPL | |
static int | global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 |
static struct ast_jb_conf | global_jbconf |
static struct ast_cli_entry | gtalk_cli [] |
static struct gtalk_container | gtalk_list |
static struct ast_rtp_protocol | gtalk_rtp |
RTP driver interface. | |
static struct ast_channel_tech | gtalk_tech |
PBX interface structure for channel registration. | |
static ast_mutex_t | gtalklock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static struct io_context * | io |
static char | reload_usage [] |
static struct sched_context * | sched |
static char | show_channels_usage [] |
Definition in file chan_gtalk.c.
#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" |
Definition at line 86 of file chan_gtalk.c.
enum gtalk_connect_type |
Definition at line 104 of file chan_gtalk.c.
00104 { 00105 AJI_CONNECT_STUN = 1, 00106 AJI_CONNECT_LOCAL = 2, 00107 AJI_CONNECT_RELAY = 3, 00108 };
enum gtalk_protocol |
Definition at line 99 of file chan_gtalk.c.
00099 { 00100 AJI_PROTOCOL_UDP = 1, 00101 AJI_PROTOCOL_SSLTCP = 2, 00102 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 2109 of file chan_gtalk.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 2109 of file chan_gtalk.c.
static int add_codec_to_answer | ( | const struct gtalk_pvt * | p, | |
int | codec, | |||
iks * | dcodecs | |||
) | [static] |
Definition at line 298 of file chan_gtalk.c.
References ast_getformatname(), ast_log(), ast_rtp_lookup_code(), format, LOG_WARNING, gtalk::p, and gtalk_pvt::rtp.
Referenced by gtalk_invite().
00299 { 00300 int res = 0; 00301 char *format = ast_getformatname(codec); 00302 00303 if (!strcasecmp("ulaw", format)) { 00304 iks *payload_eg711u, *payload_pcmu; 00305 payload_pcmu = iks_new("payload-type"); 00306 payload_eg711u = iks_new("payload-type"); 00307 00308 if(!payload_eg711u || !payload_pcmu) { 00309 if(payload_pcmu) 00310 iks_delete(payload_pcmu); 00311 if(payload_eg711u) 00312 iks_delete(payload_eg711u); 00313 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00314 return -1; 00315 } 00316 iks_insert_attrib(payload_pcmu, "id", "0"); 00317 iks_insert_attrib(payload_pcmu, "name", "PCMU"); 00318 iks_insert_attrib(payload_pcmu, "clockrate","8000"); 00319 iks_insert_attrib(payload_pcmu, "bitrate","64000"); 00320 iks_insert_attrib(payload_eg711u, "id", "100"); 00321 iks_insert_attrib(payload_eg711u, "name", "EG711U"); 00322 iks_insert_attrib(payload_eg711u, "clockrate","8000"); 00323 iks_insert_attrib(payload_eg711u, "bitrate","64000"); 00324 iks_insert_node(dcodecs, payload_pcmu); 00325 iks_insert_node(dcodecs, payload_eg711u); 00326 res ++; 00327 } 00328 if (!strcasecmp("alaw", format)) { 00329 iks *payload_eg711a, *payload_pcma; 00330 payload_pcma = iks_new("payload-type"); 00331 payload_eg711a = iks_new("payload-type"); 00332 if(!payload_eg711a || !payload_pcma) { 00333 if(payload_eg711a) 00334 iks_delete(payload_eg711a); 00335 if(payload_pcma) 00336 iks_delete(payload_pcma); 00337 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00338 return -1; 00339 } 00340 iks_insert_attrib(payload_pcma, "id", "8"); 00341 iks_insert_attrib(payload_pcma, "name", "PCMA"); 00342 iks_insert_attrib(payload_pcma, "clockrate","8000"); 00343 iks_insert_attrib(payload_pcma, "bitrate","64000"); 00344 payload_eg711a = iks_new("payload-type"); 00345 iks_insert_attrib(payload_eg711a, "id", "101"); 00346 iks_insert_attrib(payload_eg711a, "name", "EG711A"); 00347 iks_insert_attrib(payload_eg711a, "clockrate","8000"); 00348 iks_insert_attrib(payload_eg711a, "bitrate","64000"); 00349 iks_insert_node(dcodecs, payload_pcma); 00350 iks_insert_node(dcodecs, payload_eg711a); 00351 res ++; 00352 } 00353 if (!strcasecmp("ilbc", format)) { 00354 iks *payload_ilbc = iks_new("payload-type"); 00355 if(!payload_ilbc) { 00356 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00357 return -1; 00358 } 00359 iks_insert_attrib(payload_ilbc, "id", "97"); 00360 iks_insert_attrib(payload_ilbc, "name", "iLBC"); 00361 iks_insert_attrib(payload_ilbc, "clockrate","8000"); 00362 iks_insert_attrib(payload_ilbc, "bitrate","13300"); 00363 iks_insert_node(dcodecs, payload_ilbc); 00364 res ++; 00365 } 00366 if (!strcasecmp("g723", format)) { 00367 iks *payload_g723 = iks_new("payload-type"); 00368 if(!payload_g723) { 00369 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00370 return -1; 00371 } 00372 iks_insert_attrib(payload_g723, "id", "4"); 00373 iks_insert_attrib(payload_g723, "name", "G723"); 00374 iks_insert_attrib(payload_g723, "clockrate","8000"); 00375 iks_insert_attrib(payload_g723, "bitrate","6300"); 00376 iks_insert_node(dcodecs, payload_g723); 00377 res ++; 00378 } 00379 if (!strcasecmp("speex", format)) { 00380 iks *payload_speex = iks_new("payload-type"); 00381 if(!payload_speex) { 00382 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00383 return -1; 00384 } 00385 iks_insert_attrib(payload_speex, "id", "110"); 00386 iks_insert_attrib(payload_speex, "name", "speex"); 00387 iks_insert_attrib(payload_speex, "clockrate","8000"); 00388 iks_insert_attrib(payload_speex, "bitrate","11000"); 00389 iks_insert_node(dcodecs, payload_speex); 00390 res++; 00391 } 00392 if (!strcasecmp("gsm", format)) { 00393 iks *payload_gsm = iks_new("payload-type"); 00394 if(!payload_gsm) { 00395 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00396 return -1; 00397 } 00398 iks_insert_attrib(payload_gsm, "id", "103"); 00399 iks_insert_attrib(payload_gsm, "name", "gsm"); 00400 iks_insert_node(dcodecs, payload_gsm); 00401 res++; 00402 } 00403 ast_rtp_lookup_code(p->rtp, 1, codec); 00404 return res; 00405 }
static struct gtalk* find_gtalk | ( | char * | name, | |
char * | connection | |||
) | [static] |
Definition at line 266 of file chan_gtalk.c.
References ast_strdupa, ast_verbose(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, gtalk_list, s, and gtalk::user.
Referenced by gtalk_request().
00267 { 00268 struct gtalk *gtalk = NULL; 00269 char *domain = NULL , *s = NULL; 00270 00271 if(strchr(connection, '@')) { 00272 s = ast_strdupa(connection); 00273 domain = strsep(&s, "@"); 00274 ast_verbose("OOOOH domain = %s\n", domain); 00275 } 00276 gtalk = ASTOBJ_CONTAINER_FIND(>alk_list, name); 00277 if (!gtalk && strchr(name, '@')) 00278 gtalk = ASTOBJ_CONTAINER_FIND_FULL(>alk_list, name, user,,, strcasecmp); 00279 00280 if (!gtalk) { 00281 /* guest call */ 00282 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { 00283 ASTOBJ_RDLOCK(iterator); 00284 if (!strcasecmp(iterator->name, "guest")) { 00285 gtalk = iterator; 00286 } 00287 ASTOBJ_UNLOCK(iterator); 00288 00289 if (gtalk) 00290 break; 00291 }); 00292 00293 } 00294 return gtalk; 00295 }
static int gtalk_action | ( | struct gtalk * | client, | |
struct gtalk_pvt * | p, | |||
const char * | action | |||
) | [static] |
Definition at line 1099 of file chan_gtalk.c.
References ast_aji_increment_mid(), ast_strdupa, gtalk::connection, gtalk_pvt::initiator, aji_client::mid, aji_client::p, gtalk_pvt::sid, t, gtalk_pvt::them, and gtalk_pvt::us.
Referenced by gtalk_hangup(), and gtalk_newcall().
01100 { 01101 iks *request, *session = NULL; 01102 int res = -1; 01103 char *lowerthem = NULL; 01104 01105 request = iks_new("iq"); 01106 if (request) { 01107 iks_insert_attrib(request, "type", "set"); 01108 iks_insert_attrib(request, "from", p->us); 01109 iks_insert_attrib(request, "to", p->them); 01110 iks_insert_attrib(request, "id", client->connection->mid); 01111 ast_aji_increment_mid(client->connection->mid); 01112 session = iks_new("session"); 01113 if (session) { 01114 iks_insert_attrib(session, "type", action); 01115 iks_insert_attrib(session, "id", p->sid); 01116 /* put the initiator attribute to lower case if we receive the call 01117 * otherwise GoogleTalk won't establish the session */ 01118 if (!p->initiator) { 01119 char c; 01120 char *t = lowerthem = ast_strdupa(p->them); 01121 while (((c = *t) != '/') && (*t++ = tolower(c))); 01122 } 01123 iks_insert_attrib(session, "initiator", p->initiator ? p->us : lowerthem); 01124 iks_insert_attrib(session, "xmlns", "http://www.google.com/session"); 01125 iks_insert_node(request, session); 01126 iks_send(client->connection->p, request); 01127 iks_delete(session); 01128 res = 0; 01129 } 01130 iks_delete(request); 01131 } 01132 return res; 01133 }
static int gtalk_add_candidate | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1321 of file chan_gtalk.c.
References AJI_CONNECT_LOCAL, AJI_CONNECT_RELAY, AJI_CONNECT_STUN, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_calloc, ast_copy_string(), gtalk::connection, gtalk_update_stun(), aji_client::jid, gtalk_pvt::laststun, gtalk_pvt::next, aji_client::p, gtalk::p, gtalk_pvt::parent, gtalk_candidate::receipt, and gtalk_pvt::theircandidates.
Referenced by gtalk_parser().
01322 { 01323 struct gtalk_pvt *p = NULL, *tmp = NULL; 01324 struct aji_client *c = client->connection; 01325 struct gtalk_candidate *newcandidate = NULL; 01326 iks *traversenodes = NULL, *receipt = NULL; 01327 char *from; 01328 01329 from = iks_find_attrib(pak->x,"to"); 01330 if(!from) 01331 from = c->jid->full; 01332 01333 for (tmp = client->p; tmp; tmp = tmp->next) { 01334 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) { 01335 p = tmp; 01336 break; 01337 } 01338 } 01339 01340 if (!p) 01341 return -1; 01342 01343 traversenodes = pak->query; 01344 while(traversenodes) { 01345 if(!strcasecmp(iks_name(traversenodes), "session")) { 01346 traversenodes = iks_first_tag(traversenodes); 01347 continue; 01348 } 01349 if(!strcasecmp(iks_name(traversenodes), "transport")) { 01350 traversenodes = iks_first_tag(traversenodes); 01351 continue; 01352 } 01353 if(!strcasecmp(iks_name(traversenodes), "candidate")) { 01354 newcandidate = ast_calloc(1, sizeof(*newcandidate)); 01355 if (!newcandidate) 01356 return 0; 01357 ast_copy_string(newcandidate->name, iks_find_attrib(traversenodes, "name"), 01358 sizeof(newcandidate->name)); 01359 ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "address"), 01360 sizeof(newcandidate->ip)); 01361 newcandidate->port = atoi(iks_find_attrib(traversenodes, "port")); 01362 ast_copy_string(newcandidate->username, iks_find_attrib(traversenodes, "username"), 01363 sizeof(newcandidate->username)); 01364 ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "password"), 01365 sizeof(newcandidate->password)); 01366 newcandidate->preference = atof(iks_find_attrib(traversenodes, "preference")); 01367 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp")) 01368 newcandidate->protocol = AJI_PROTOCOL_UDP; 01369 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp")) 01370 newcandidate->protocol = AJI_PROTOCOL_SSLTCP; 01371 01372 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "stun")) 01373 newcandidate->type = AJI_CONNECT_STUN; 01374 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "local")) 01375 newcandidate->type = AJI_CONNECT_LOCAL; 01376 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay")) 01377 newcandidate->type = AJI_CONNECT_RELAY; 01378 ast_copy_string(newcandidate->network, iks_find_attrib(traversenodes, "network"), 01379 sizeof(newcandidate->network)); 01380 newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation")); 01381 newcandidate->next = NULL; 01382 01383 newcandidate->next = p->theircandidates; 01384 p->theircandidates = newcandidate; 01385 p->laststun = 0; 01386 gtalk_update_stun(p->parent, p); 01387 newcandidate = NULL; 01388 } 01389 traversenodes = iks_next_tag(traversenodes); 01390 } 01391 01392 receipt = iks_new("iq"); 01393 iks_insert_attrib(receipt, "type", "result"); 01394 iks_insert_attrib(receipt, "from", from); 01395 iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from")); 01396 iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id")); 01397 iks_send(c->p, receipt); 01398 iks_delete(receipt); 01399 01400 return 1; 01401 }
static struct gtalk_pvt * gtalk_alloc | ( | struct gtalk * | client, | |
const char * | us, | |||
const char * | them, | |||
const char * | sid | |||
) | [static] |
Definition at line 942 of file chan_gtalk.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_new_with_bindaddr(), ast_rtp_pt_clear(), ast_strdupa, ASTOBJ_CONTAINER_FIND, bindaddr, aji_client::buddies, gtalk::buddy, aji_resource::cap, gtalk::capability, gtalk::connection, exten, free, global_capability, gtalklock, io, aji_version::jingle, LOG_DEBUG, LOG_ERROR, LOG_WARNING, gtalk::name, aji_resource::next, option_debug, gtalk::p, aji_resource::resource, and aji_buddy::resources.
Referenced by gtalk_newcall(), and gtalk_request().
00943 { 00944 struct gtalk_pvt *tmp = NULL; 00945 struct aji_resource *resources = NULL; 00946 struct aji_buddy *buddy; 00947 char idroster[200]; 00948 char *data, *exten = NULL; 00949 00950 if (option_debug) 00951 ast_log(LOG_DEBUG, "The client is %s for alloc\n", client->name); 00952 if (!sid && !strchr(them, '/')) { /* I started call! */ 00953 if (!strcasecmp(client->name, "guest")) { 00954 buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, them); 00955 if (buddy) 00956 resources = buddy->resources; 00957 } else if (client->buddy) 00958 resources = client->buddy->resources; 00959 while (resources) { 00960 if (resources->cap->jingle) { 00961 break; 00962 } 00963 resources = resources->next; 00964 } 00965 if (resources) 00966 snprintf(idroster, sizeof(idroster), "%s/%s", them, resources->resource); 00967 else { 00968 ast_log(LOG_ERROR, "no gtalk capable clients to talk to.\n"); 00969 return NULL; 00970 } 00971 } 00972 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 00973 return NULL; 00974 } 00975 if (sid) { 00976 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid)); 00977 ast_copy_string(tmp->them, them, sizeof(tmp->them)); 00978 ast_copy_string(tmp->us, us, sizeof(tmp->us)); 00979 } else { 00980 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random()); 00981 ast_copy_string(tmp->them, idroster, sizeof(tmp->them)); 00982 ast_copy_string(tmp->us, us, sizeof(tmp->us)); 00983 tmp->initiator = 1; 00984 } 00985 /* clear codecs */ 00986 tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 00987 ast_rtp_pt_clear(tmp->rtp); 00988 00989 /* add user configured codec capabilites */ 00990 if (client->capability) 00991 tmp->capability = client->capability; 00992 else if (global_capability) 00993 tmp->capability = global_capability; 00994 00995 tmp->parent = client; 00996 if (!tmp->rtp) { 00997 ast_log(LOG_WARNING, "Out of RTP sessions?\n"); 00998 free(tmp); 00999 return NULL; 01000 } 01001 01002 /* Set CALLERID(name) to the full JID of the remote peer */ 01003 ast_copy_string(tmp->cid_name, tmp->them, sizeof(tmp->cid_name)); 01004 01005 if(strchr(tmp->us, '/')) { 01006 data = ast_strdupa(tmp->us); 01007 exten = strsep(&data, "/"); 01008 } else 01009 exten = tmp->us; 01010 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten)); 01011 ast_mutex_init(&tmp->lock); 01012 ast_mutex_lock(>alklock); 01013 tmp->next = client->p; 01014 client->p = tmp; 01015 ast_mutex_unlock(>alklock); 01016 return tmp; 01017 }
static int gtalk_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 547 of file chan_gtalk.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), gtalk_invite(), gtalk_pvt::lock, LOG_DEBUG, option_debug, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.
00548 { 00549 struct gtalk_pvt *p = ast->tech_pvt; 00550 int res = 0; 00551 00552 if (option_debug) 00553 ast_log(LOG_DEBUG, "Answer!\n"); 00554 ast_mutex_lock(&p->lock); 00555 gtalk_invite(p, p->them, p->us,p->sid, 0); 00556 ast_mutex_unlock(&p->lock); 00557 return res; 00558 }
static int gtalk_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Initiate new call, part of PBX interface dest is the dial string.
Definition at line 1614 of file chan_gtalk.c.
References ast_channel::_state, ast_copy_string(), ast_log(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RING, gtalk::connection, aji_client::f, gtalk_create_candidates(), gtalk_invite(), gtalk_ringing_ack(), LOG_WARNING, aji_client::mid, ast_channel::name, gtalk_pvt::parent, gtalk_pvt::ring, gtalk_pvt::ringrule, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.
01615 { 01616 struct gtalk_pvt *p = ast->tech_pvt; 01617 01618 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 01619 ast_log(LOG_WARNING, "gtalk_call called on %s, neither down nor reserved\n", ast->name); 01620 return -1; 01621 } 01622 01623 ast_setstate(ast, AST_STATE_RING); 01624 if (!p->ringrule) { 01625 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring)); 01626 p->ringrule = iks_filter_add_rule(p->parent->connection->f, gtalk_ringing_ack, p, 01627 IKS_RULE_ID, p->ring, IKS_RULE_DONE); 01628 } else 01629 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n"); 01630 01631 gtalk_invite(p, p->them, p->us, p->sid, 1); 01632 gtalk_create_candidates(p->parent, p, p->sid, p->them, p->us); 01633 01634 return 0; 01635 }
static int gtalk_create_candidates | ( | struct gtalk * | client, | |
struct gtalk_pvt * | p, | |||
char * | sid, | |||
char * | from, | |||
char * | to | |||
) | [static] |
Definition at line 806 of file chan_gtalk.c.
References __ourip, AJI_CONNECT_LOCAL, AJI_CONNECT_RELAY, AJI_CONNECT_STUN, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_increment_mid(), ast_calloc, ast_copy_string(), ast_find_ourip(), ast_inet_ntoa(), ast_log(), ast_random(), ast_rtp_get_us(), ast_strdupa, ast_strlen_zero(), bindaddr, gtalk::connection, externip, free, GOOGLE_NS, gtalk_pvt::initiator, gtalk_candidate::ip, gtalk_pvt::laststun, LOG_ERROR, LOG_NOTICE, aji_client::mid, gtalk_candidate::name, gtalk_candidate::next, gtalk_pvt::next, gtalk_pvt::ourcandidates, aji_client::p, gtalk_candidate::password, gtalk_candidate::port, gtalk_candidate::preference, gtalk_candidate::protocol, gtalk_pvt::rtp, gtalk_pvt::sid, t, gtalk_candidate::type, and gtalk_candidate::username.
Referenced by gtalk_call(), and gtalk_newcall().
00807 { 00808 struct gtalk_candidate *tmp; 00809 struct aji_client *c = client->connection; 00810 struct gtalk_candidate *ours1 = NULL, *ours2 = NULL; 00811 struct sockaddr_in sin; 00812 struct sockaddr_in dest; 00813 struct in_addr us; 00814 iks *iq, *gtalk, *candidate, *transport; 00815 char user[17], pass[17], preference[5], port[7]; 00816 char *lowerfrom = NULL; 00817 00818 00819 iq = iks_new("iq"); 00820 gtalk = iks_new("session"); 00821 candidate = iks_new("candidate"); 00822 transport = iks_new("transport"); 00823 if (!iq || !gtalk || !candidate || !transport) { 00824 ast_log(LOG_ERROR, "Memory allocation error\n"); 00825 goto safeout; 00826 } 00827 ours1 = ast_calloc(1, sizeof(*ours1)); 00828 ours2 = ast_calloc(1, sizeof(*ours2)); 00829 if (!ours1 || !ours2) 00830 goto safeout; 00831 00832 iks_insert_attrib(transport, "xmlns","http://www.google.com/transport/p2p"); 00833 iks_insert_node(iq, gtalk); 00834 iks_insert_node(gtalk,transport); 00835 iks_insert_node(transport, candidate); 00836 00837 for (; p; p = p->next) { 00838 if (!strcasecmp(p->sid, sid)) 00839 break; 00840 } 00841 00842 if (!p) { 00843 ast_log(LOG_NOTICE, "No matching gtalk session - SID %s!\n", sid); 00844 goto safeout; 00845 } 00846 00847 ast_rtp_get_us(p->rtp, &sin); 00848 ast_find_ourip(&us, bindaddr); 00849 00850 /* Setup our gtalk candidates */ 00851 ast_copy_string(ours1->name, "rtp", sizeof(ours1->name)); 00852 ours1->port = ntohs(sin.sin_port); 00853 ours1->preference = 1; 00854 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00855 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00856 ast_copy_string(ours1->username, user, sizeof(ours1->username)); 00857 ast_copy_string(ours1->password, pass, sizeof(ours1->password)); 00858 ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip)); 00859 ours1->protocol = AJI_PROTOCOL_UDP; 00860 ours1->type = AJI_CONNECT_LOCAL; 00861 ours1->generation = 0; 00862 p->ourcandidates = ours1; 00863 00864 if (!ast_strlen_zero(externip)) { 00865 /* XXX We should really stun for this one not just go with externip XXX */ 00866 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00867 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00868 ast_copy_string(ours2->username, user, sizeof(ours2->username)); 00869 ast_copy_string(ours2->password, pass, sizeof(ours2->password)); 00870 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip)); 00871 ast_copy_string(ours2->name, "rtp", sizeof(ours1->name)); 00872 ours2->port = ntohs(sin.sin_port); 00873 ours2->preference = 0.9; 00874 ours2->protocol = AJI_PROTOCOL_UDP; 00875 ours2->type = AJI_CONNECT_STUN; 00876 ours2->generation = 0; 00877 ours1->next = ours2; 00878 ours2 = NULL; 00879 } 00880 ours1 = NULL; 00881 dest.sin_addr = __ourip; 00882 dest.sin_port = sin.sin_port; 00883 00884 00885 for (tmp = p->ourcandidates; tmp; tmp = tmp->next) { 00886 snprintf(port, sizeof(port), "%d", tmp->port); 00887 snprintf(preference, sizeof(preference), "%.2f", tmp->preference); 00888 iks_insert_attrib(iq, "from", to); 00889 iks_insert_attrib(iq, "to", from); 00890 iks_insert_attrib(iq, "type", "set"); 00891 iks_insert_attrib(iq, "id", c->mid); 00892 ast_aji_increment_mid(c->mid); 00893 iks_insert_attrib(gtalk, "type", "transport-info"); 00894 iks_insert_attrib(gtalk, "id", sid); 00895 /* put the initiator attribute to lower case if we receive the call 00896 * otherwise GoogleTalk won't establish the session */ 00897 if (!p->initiator) { 00898 char c; 00899 char *t = lowerfrom = ast_strdupa(from); 00900 while (((c = *t) != '/') && (*t++ = tolower(c))); 00901 } 00902 iks_insert_attrib(gtalk, "initiator", (p->initiator) ? to : lowerfrom); 00903 iks_insert_attrib(gtalk, "xmlns", GOOGLE_NS); 00904 iks_insert_attrib(candidate, "name", tmp->name); 00905 iks_insert_attrib(candidate, "address", tmp->ip); 00906 iks_insert_attrib(candidate, "port", port); 00907 iks_insert_attrib(candidate, "username", tmp->username); 00908 iks_insert_attrib(candidate, "password", tmp->password); 00909 iks_insert_attrib(candidate, "preference", preference); 00910 if (tmp->protocol == AJI_PROTOCOL_UDP) 00911 iks_insert_attrib(candidate, "protocol", "udp"); 00912 if (tmp->protocol == AJI_PROTOCOL_SSLTCP) 00913 iks_insert_attrib(candidate, "protocol", "ssltcp"); 00914 if (tmp->type == AJI_CONNECT_STUN) 00915 iks_insert_attrib(candidate, "type", "stun"); 00916 if (tmp->type == AJI_CONNECT_LOCAL) 00917 iks_insert_attrib(candidate, "type", "local"); 00918 if (tmp->type == AJI_CONNECT_RELAY) 00919 iks_insert_attrib(candidate, "type", "relay"); 00920 iks_insert_attrib(candidate, "network", "0"); 00921 iks_insert_attrib(candidate, "generation", "0"); 00922 iks_send(c->p, iq); 00923 } 00924 p->laststun = 0; 00925 00926 safeout: 00927 if (ours1) 00928 free(ours1); 00929 if (ours2) 00930 free(ours2); 00931 if (iq) 00932 iks_delete(iq); 00933 if (gtalk) 00934 iks_delete(gtalk); 00935 if (candidate) 00936 iks_delete(candidate); 00937 if(transport) 00938 iks_delete(transport); 00939 return 1; 00940 }
static int gtalk_create_member | ( | char * | label, | |
struct ast_variable * | var, | |||
int | allowguest, | |||
struct ast_codec_pref | prefs, | |||
char * | context, | |||
struct gtalk * | member | |||
) | [static] |
Definition at line 1839 of file chan_gtalk.c.
References gtalk::allowguest, ast_aji_get_client(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, gtalk::buddy, gtalk::capability, gtalk::connection, gtalk::context, aji_client::f, gtalk_parser(), LOG_ERROR, LOG_WARNING, gtalk::name, gtalk_candidate::next, prefs, gtalk::prefs, gtalk::user, and var.
01842 { 01843 struct aji_client *client; 01844 01845 if (!member) 01846 ast_log(LOG_WARNING, "Out of memory.\n"); 01847 01848 ast_copy_string(member->name, label, sizeof(member->name)); 01849 ast_copy_string(member->user, label, sizeof(member->user)); 01850 ast_copy_string(member->context, context, sizeof(member->context)); 01851 member->allowguest = allowguest; 01852 member->prefs = prefs; 01853 while (var) { 01854 #if 0 01855 struct gtalk_candidate *candidate = NULL; 01856 #endif 01857 if (!strcasecmp(var->name, "username")) 01858 ast_copy_string(member->user, var->value, sizeof(member->user)); 01859 else if (!strcasecmp(var->name, "disallow")) 01860 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0); 01861 else if (!strcasecmp(var->name, "allow")) 01862 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1); 01863 else if (!strcasecmp(var->name, "context")) 01864 ast_copy_string(member->context, var->value, sizeof(member->context)); 01865 #if 0 01866 else if (!strcasecmp(var->name, "candidate")) { 01867 candidate = gtalk_create_candidate(var->value); 01868 if (candidate) { 01869 candidate->next = member->ourcandidates; 01870 member->ourcandidates = candidate; 01871 } 01872 } 01873 #endif 01874 else if (!strcasecmp(var->name, "connection")) { 01875 if ((client = ast_aji_get_client(var->value))) { 01876 member->connection = client; 01877 iks_filter_add_rule(client->f, gtalk_parser, member, 01878 IKS_RULE_TYPE, IKS_PAK_IQ, 01879 IKS_RULE_FROM_PARTIAL, member->user, 01880 IKS_RULE_NS, "http://www.google.com/session", 01881 IKS_RULE_DONE); 01882 01883 } else { 01884 ast_log(LOG_ERROR, "connection referenced not found!\n"); 01885 return 0; 01886 } 01887 } 01888 var = var->next; 01889 } 01890 if (member->connection && member->user) 01891 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); 01892 else { 01893 ast_log(LOG_ERROR, "No Connection or Username!\n"); 01894 } 01895 return 1; 01896 }
static int gtalk_digit | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1531 of file chan_gtalk.c.
References ast_aji_increment_mid(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, gtalk::connection, ast_channel::dtmff, ast_frame::frametype, gtalk_pvt::initiator, gtalk_pvt::lock, LOG_ERROR, aji_client::mid, aji_client::p, gtalk::p, gtalk_pvt::parent, gtalk_pvt::sid, t, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.
Referenced by gtalk_digit_begin(), and gtalk_digit_end().
01532 { 01533 struct gtalk_pvt *p = ast->tech_pvt; 01534 struct gtalk *client = p->parent; 01535 iks *iq, *gtalk, *dtmf; 01536 char buffer[2] = {digit, '\0'}; 01537 char *lowerthem = NULL; 01538 iq = iks_new("iq"); 01539 gtalk = iks_new("gtalk"); 01540 dtmf = iks_new("dtmf"); 01541 if(!iq || !gtalk || !dtmf) { 01542 if(iq) 01543 iks_delete(iq); 01544 if(gtalk) 01545 iks_delete(gtalk); 01546 if(dtmf) 01547 iks_delete(dtmf); 01548 ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n"); 01549 return -1; 01550 } 01551 01552 iks_insert_attrib(iq, "type", "set"); 01553 iks_insert_attrib(iq, "to", p->them); 01554 iks_insert_attrib(iq, "from", p->us); 01555 iks_insert_attrib(iq, "id", client->connection->mid); 01556 ast_aji_increment_mid(client->connection->mid); 01557 iks_insert_attrib(gtalk, "xmlns", "http://jabber.org/protocol/gtalk"); 01558 iks_insert_attrib(gtalk, "action", "session-info"); 01559 /* put the initiator attribute to lower case if we receive the call 01560 * otherwise GoogleTalk won't establish the session */ 01561 if (!p->initiator) { 01562 char c; 01563 char *t = lowerthem = ast_strdupa(p->them); 01564 while (((c = *t) != '/') && (*t++ = tolower(c))); 01565 } 01566 iks_insert_attrib(gtalk, "initiator", p->initiator ? p->us: lowerthem); 01567 iks_insert_attrib(gtalk, "sid", p->sid); 01568 iks_insert_attrib(dtmf, "xmlns", "http://jabber.org/protocol/gtalk/info/dtmf"); 01569 iks_insert_attrib(dtmf, "code", buffer); 01570 iks_insert_node(iq, gtalk); 01571 iks_insert_node(gtalk, dtmf); 01572 01573 ast_mutex_lock(&p->lock); 01574 if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) { 01575 iks_insert_attrib(dtmf, "action", "button-down"); 01576 } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) { 01577 iks_insert_attrib(dtmf, "action", "button-up"); 01578 } 01579 iks_send(client->connection->p, iq); 01580 iks_delete(iq); 01581 iks_delete(gtalk); 01582 iks_delete(dtmf); 01583 ast_mutex_unlock(&p->lock); 01584 return 0; 01585 }
static int gtalk_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1521 of file chan_gtalk.c.
References gtalk_digit().
01522 { 01523 return gtalk_digit(chan, digit, 0); 01524 }
static int gtalk_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1526 of file chan_gtalk.c.
References gtalk_digit().
01527 { 01528 return gtalk_digit(chan, digit, duration); 01529 }
static int gtalk_do_reload | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
CLI command "gtalk show channels".
Definition at line 1757 of file chan_gtalk.c.
References ast_verbose(), and RESULT_SUCCESS.
01758 { 01759 ast_verbose("IT DOES WORK!\n"); 01760 return RESULT_SUCCESS; 01761 }
static int gtalk_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 1487 of file chan_gtalk.c.
References ast_mutex_lock(), ast_mutex_unlock(), gtalk_pvt::lock, gtalk_pvt::owner, and ast_channel::tech_pvt.
01488 { 01489 struct gtalk_pvt *p = newchan->tech_pvt; 01490 ast_mutex_lock(&p->lock); 01491 01492 if ((p->owner != oldchan)) { 01493 ast_mutex_unlock(&p->lock); 01494 return -1; 01495 } 01496 if (p->owner == oldchan) 01497 p->owner = newchan; 01498 ast_mutex_unlock(&p->lock); 01499 return 0; 01500 }
static void gtalk_free_candidates | ( | struct gtalk_candidate * | candidate | ) | [static] |
Definition at line 1135 of file chan_gtalk.c.
References free, last, and gtalk_candidate::next.
Referenced by gtalk_free_pvt().
01136 { 01137 struct gtalk_candidate *last; 01138 while (candidate) { 01139 last = candidate; 01140 candidate = candidate->next; 01141 free(last); 01142 } 01143 }
Definition at line 1145 of file chan_gtalk.c.
References ast_log(), ast_rtp_destroy(), gtalk::connection, aji_client::f, free, gtalk_free_candidates(), LOG_WARNING, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, gtalk_pvt::parent, gtalk_pvt::ringrule, gtalk_pvt::rtp, gtalk_pvt::theircandidates, and gtalk_pvt::vrtp.
Referenced by gtalk_hangup(), and gtalk_newcall().
01146 { 01147 struct gtalk_pvt *cur, *prev = NULL; 01148 cur = client->p; 01149 while (cur) { 01150 if (cur == p) { 01151 if (prev) 01152 prev->next = p->next; 01153 else 01154 client->p = p->next; 01155 break; 01156 } 01157 prev = cur; 01158 cur = cur->next; 01159 } 01160 if (p->ringrule) 01161 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 01162 if (p->owner) 01163 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n"); 01164 if (p->rtp) 01165 ast_rtp_destroy(p->rtp); 01166 if (p->vrtp) 01167 ast_rtp_destroy(p->vrtp); 01168 gtalk_free_candidates(p->theircandidates); 01169 free(p); 01170 }
static int gtalk_get_codec | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 578 of file chan_gtalk.c.
References gtalk_pvt::peercapability, and ast_channel::tech_pvt.
00579 { 00580 struct gtalk_pvt *p = chan->tech_pvt; 00581 return p->peercapability; 00582 }
static enum ast_rtp_get_result gtalk_get_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp ** | rtp | |||
) | [static] |
Definition at line 560 of file chan_gtalk.c.
References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_PARTIAL, gtalk_pvt::lock, gtalk_pvt::rtp, and ast_channel::tech_pvt.
00561 { 00562 struct gtalk_pvt *p = chan->tech_pvt; 00563 enum ast_rtp_get_result res = AST_RTP_GET_FAILED; 00564 00565 if (!p) 00566 return res; 00567 00568 ast_mutex_lock(&p->lock); 00569 if (p->rtp){ 00570 *rtp = p->rtp; 00571 res = AST_RTP_TRY_PARTIAL; 00572 } 00573 ast_mutex_unlock(&p->lock); 00574 00575 return res; 00576 }
static int gtalk_handle_dtmf | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 713 of file chan_gtalk.c.
References AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), ast_verbose(), gtalk::connection, f, gtalk_response(), aji_client::jid, LOG_NOTICE, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, and gtalk_pvt::sid.
Referenced by gtalk_parser().
00714 { 00715 struct gtalk_pvt *tmp; 00716 iks *dtmfnode = NULL, *dtmfchild = NULL; 00717 char *dtmf; 00718 char *from; 00719 /* Make sure our new call doesn't exist yet */ 00720 for (tmp = client->p; tmp; tmp = tmp->next) { 00721 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || iks_find_with_attrib(pak->x, "gtalk", "sid", tmp->sid)) 00722 break; 00723 } 00724 from = iks_find_attrib(pak->x, "to"); 00725 if(!from) 00726 from = client->connection->jid->full; 00727 00728 00729 if (tmp) { 00730 if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) { 00731 gtalk_response(client, from, pak, 00732 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", 00733 "unsupported-dtmf-method xmlns='http://jabber.org/protocol/gtalk/info/dtmf#errors'"); 00734 return -1; 00735 } 00736 if ((dtmfnode = iks_find(pak->x, "dtmf"))) { 00737 if((dtmf = iks_find_attrib(dtmfnode, "code"))) { 00738 if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) { 00739 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00740 f.subclass = dtmf[0]; 00741 ast_queue_frame(tmp->owner, &f); 00742 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00743 } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) { 00744 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00745 f.subclass = dtmf[0]; 00746 ast_queue_frame(tmp->owner, &f); 00747 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00748 } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */ 00749 struct ast_frame f = {AST_FRAME_DTMF, }; 00750 f.subclass = dtmf[0]; 00751 ast_queue_frame(tmp->owner, &f); 00752 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00753 } 00754 } 00755 } else if ((dtmfnode = iks_find_with_attrib(pak->x, "gtalk", "action", "session-info"))) { 00756 if((dtmfchild = iks_find(dtmfnode, "dtmf"))) { 00757 if((dtmf = iks_find_attrib(dtmfchild, "code"))) { 00758 if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) { 00759 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00760 f.subclass = dtmf[0]; 00761 ast_queue_frame(tmp->owner, &f); 00762 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00763 } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) { 00764 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00765 f.subclass = dtmf[0]; 00766 ast_queue_frame(tmp->owner, &f); 00767 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00768 } 00769 } 00770 } 00771 } 00772 gtalk_response(client, from, pak, NULL, NULL); 00773 return 1; 00774 } else 00775 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00776 00777 gtalk_response(client, from, pak, NULL, NULL); 00778 return 1; 00779 }
static int gtalk_hangup | ( | struct ast_channel * | ast | ) | [static] |
Hangup a call through the gtalk proxy channel.
Definition at line 1638 of file chan_gtalk.c.
References gtalk_pvt::alreadygone, ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), gtalk_action(), gtalk_free_pvt(), gtalk_pvt::lock, gtalk_pvt::owner, gtalk::p, gtalk_pvt::parent, and ast_channel::tech_pvt.
Referenced by gtalk_newcall().
01639 { 01640 struct gtalk_pvt *p = ast->tech_pvt; 01641 struct gtalk *client; 01642 01643 ast_mutex_lock(&p->lock); 01644 client = p->parent; 01645 p->owner = NULL; 01646 ast->tech_pvt = NULL; 01647 if (!p->alreadygone) 01648 gtalk_action(client, p, "terminate"); 01649 ast_mutex_unlock(&p->lock); 01650 01651 gtalk_free_pvt(client, p); 01652 ast_module_unref(ast_module_info->self); 01653 01654 return 0; 01655 }
static int gtalk_hangup_farend | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 781 of file chan_gtalk.c.
References gtalk_pvt::alreadygone, ast_log(), ast_queue_hangup(), gtalk::connection, gtalk_response(), aji_client::jid, LOG_DEBUG, LOG_NOTICE, gtalk::name, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, and gtalk_pvt::sid.
Referenced by gtalk_parser().
00782 { 00783 struct gtalk_pvt *tmp; 00784 char *from; 00785 00786 ast_log(LOG_DEBUG, "The client is %s\n", client->name); 00787 /* Make sure our new call doesn't exist yet */ 00788 for (tmp = client->p; tmp; tmp = tmp->next) { 00789 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) 00790 break; 00791 } 00792 from = iks_find_attrib(pak->x, "to"); 00793 if(!from) 00794 from = client->connection->jid->full; 00795 00796 if (tmp) { 00797 tmp->alreadygone = 1; 00798 if (tmp->owner) 00799 ast_queue_hangup(tmp->owner); 00800 } else 00801 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00802 gtalk_response(client, from, pak, NULL, NULL); 00803 return 1; 00804 }
static int gtalk_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 1502 of file chan_gtalk.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), and LOG_NOTICE.
01503 { 01504 int res = 0; 01505 01506 switch (condition) { 01507 case AST_CONTROL_HOLD: 01508 ast_moh_start(ast, data, NULL); 01509 break; 01510 case AST_CONTROL_UNHOLD: 01511 ast_moh_stop(ast); 01512 break; 01513 default: 01514 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition); 01515 res = -1; 01516 } 01517 01518 return res; 01519 }
static int gtalk_invite | ( | struct gtalk_pvt * | p, | |
char * | to, | |||
char * | from, | |||
char * | sid, | |||
int | initiator | |||
) | [static] |
Definition at line 407 of file chan_gtalk.c.
References add_codec_to_answer(), ast_aji_increment_mid(), ast_codec_pref_index(), ast_log(), ast_strdupa, gtalk::capability, gtalk::connection, LOG_ERROR, aji_client::mid, aji_client::p, gtalk::p, gtalk_pvt::parent, gtalk::prefs, and t.
Referenced by gtalk_answer(), and gtalk_call().
00408 { 00409 struct gtalk *client = p->parent; 00410 iks *iq, *gtalk, *dcodecs, *payload_telephone, *transport; 00411 int x; 00412 int pref_codec = 0; 00413 int alreadysent = 0; 00414 int codecs_num = 0; 00415 char *lowerto = NULL; 00416 00417 iq = iks_new("iq"); 00418 gtalk = iks_new("session"); 00419 dcodecs = iks_new("description"); 00420 transport = iks_new("transport"); 00421 payload_telephone = iks_new("payload-type"); 00422 if (!(iq && gtalk && dcodecs && transport && payload_telephone)){ 00423 if(iq) 00424 iks_delete(iq); 00425 if(gtalk) 00426 iks_delete(gtalk); 00427 if(dcodecs) 00428 iks_delete(dcodecs); 00429 if(transport) 00430 iks_delete(transport); 00431 if(payload_telephone) 00432 iks_delete(payload_telephone); 00433 00434 ast_log(LOG_ERROR, "Could not allocate iksemel nodes\n"); 00435 return 0; 00436 } 00437 iks_insert_attrib(dcodecs, "xmlns", "http://www.google.com/session/phone"); 00438 iks_insert_attrib(dcodecs, "xml:lang", "en"); 00439 00440 for (x = 0; x < 32; x++) { 00441 if (!(pref_codec = ast_codec_pref_index(&client->prefs, x))) 00442 break; 00443 if (!(client->capability & pref_codec)) 00444 continue; 00445 if (alreadysent & pref_codec) 00446 continue; 00447 codecs_num = add_codec_to_answer(p, pref_codec, dcodecs); 00448 alreadysent |= pref_codec; 00449 } 00450 00451 if (codecs_num) { 00452 /* only propose DTMF within an audio session */ 00453 iks_insert_attrib(payload_telephone, "id", "106"); 00454 iks_insert_attrib(payload_telephone, "name", "telephone-event"); 00455 iks_insert_attrib(payload_telephone, "clockrate", "8000"); 00456 } 00457 iks_insert_attrib(transport,"xmlns","http://www.google.com/transport/p2p"); 00458 00459 iks_insert_attrib(iq, "type", "set"); 00460 iks_insert_attrib(iq, "to", to); 00461 iks_insert_attrib(iq, "from", from); 00462 iks_insert_attrib(iq, "id", client->connection->mid); 00463 ast_aji_increment_mid(client->connection->mid); 00464 00465 iks_insert_attrib(gtalk, "xmlns", "http://www.google.com/session"); 00466 iks_insert_attrib(gtalk, "type",initiator ? "initiate": "accept"); 00467 /* put the initiator attribute to lower case if we receive the call 00468 * otherwise GoogleTalk won't establish the session */ 00469 if (!initiator) { 00470 char c; 00471 char *t = lowerto = ast_strdupa(to); 00472 while (((c = *t) != '/') && (*t++ = tolower(c))); 00473 } 00474 iks_insert_attrib(gtalk, "initiator", initiator ? from : lowerto); 00475 iks_insert_attrib(gtalk, "id", sid); 00476 iks_insert_node(iq, gtalk); 00477 iks_insert_node(gtalk, dcodecs); 00478 iks_insert_node(gtalk, transport); 00479 iks_insert_node(dcodecs, payload_telephone); 00480 00481 iks_send(client->connection->p, iq); 00482 iks_delete(payload_telephone); 00483 iks_delete(transport); 00484 iks_delete(dcodecs); 00485 iks_delete(gtalk); 00486 iks_delete(iq); 00487 return 1; 00488 }
static int gtalk_invite_response | ( | struct gtalk_pvt * | p, | |
char * | to, | |||
char * | from, | |||
char * | sid, | |||
int | initiator | |||
) | [static] |
Definition at line 490 of file chan_gtalk.c.
References ast_aji_increment_mid(), ast_log(), ast_strdupa, gtalk::connection, LOG_ERROR, aji_client::mid, aji_client::p, gtalk::p, gtalk_pvt::parent, and t.
Referenced by gtalk_newcall().
00491 { 00492 iks *iq, *session, *transport; 00493 char *lowerto = NULL; 00494 00495 iq = iks_new("iq"); 00496 session = iks_new("session"); 00497 transport = iks_new("transport"); 00498 if(!(iq && session && transport)) { 00499 if(iq) 00500 iks_delete(iq); 00501 if(session) 00502 iks_delete(session); 00503 if(transport) 00504 iks_delete(transport); 00505 ast_log(LOG_ERROR, " Unable to allocate IKS node\n"); 00506 return -1; 00507 } 00508 iks_insert_attrib(iq, "from", from); 00509 iks_insert_attrib(iq, "to", to); 00510 iks_insert_attrib(iq, "type", "set"); 00511 iks_insert_attrib(iq, "id",p->parent->connection->mid); 00512 ast_aji_increment_mid(p->parent->connection->mid); 00513 iks_insert_attrib(session, "type", "transport-accept"); 00514 iks_insert_attrib(session, "id", sid); 00515 /* put the initiator attribute to lower case if we receive the call 00516 * otherwise GoogleTalk won't establish the session */ 00517 if (!initiator) { 00518 char c; 00519 char *t = lowerto = ast_strdupa(to); 00520 while (((c = *t) != '/') && (*t++ = tolower(c))); 00521 } 00522 iks_insert_attrib(session, "initiator", initiator ? from : lowerto); 00523 iks_insert_attrib(session, "xmlns", "http://www.google.com/session"); 00524 iks_insert_attrib(transport, "xmlns", "http://www.google.com/transport/p2p"); 00525 iks_insert_node(iq,session); 00526 iks_insert_node(session,transport); 00527 iks_send(p->parent->connection->p, iq); 00528 iks_delete(transport); 00529 iks_delete(session); 00530 iks_delete(iq); 00531 return 1; 00532 00533 }
static int gtalk_is_accepted | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 689 of file chan_gtalk.c.
References ast_log(), gtalk::connection, gtalk_response(), aji_client::jid, LOG_DEBUG, LOG_NOTICE, gtalk::name, gtalk_pvt::next, gtalk::p, and gtalk_pvt::sid.
Referenced by gtalk_parser().
00690 { 00691 struct gtalk_pvt *tmp; 00692 char *from; 00693 00694 ast_log(LOG_DEBUG, "The client is %s\n", client->name); 00695 /* find corresponding call */ 00696 for (tmp = client->p; tmp; tmp = tmp->next) { 00697 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) 00698 break; 00699 } 00700 00701 from = iks_find_attrib(pak->x, "to"); 00702 if(!from) 00703 from = client->connection->jid->full; 00704 00705 if (!tmp) 00706 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00707 00708 /* answer 'iq' packet to let the remote peer know that we're alive */ 00709 gtalk_response(client, from, pak, NULL, NULL); 00710 return 1; 00711 }
static int gtalk_is_answered | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 636 of file chan_gtalk.c.
References AST_CONTROL_ANSWER, ast_getformatname_multiple(), ast_log(), ast_queue_control(), ast_queue_hangup(), ast_rtp_get_current_formats(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), gtalk_pvt::capability, gtalk::connection, gtalk_response(), aji_client::jid, gtalk_pvt::jointcapability, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, gtalk::name, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, gtalk_pvt::peercapability, gtalk_pvt::rtp, and gtalk_pvt::sid.
Referenced by gtalk_parser().
00637 { 00638 struct gtalk_pvt *tmp; 00639 char *from; 00640 iks *codec; 00641 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ]; 00642 int peernoncodeccapability; 00643 00644 ast_log(LOG_DEBUG, "The client is %s\n", client->name); 00645 /* Make sure our new call doesn't exist yet */ 00646 for (tmp = client->p; tmp; tmp = tmp->next) { 00647 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) 00648 break; 00649 } 00650 00651 /* codec points to the first <payload-type/> tag */ 00652 codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x))); 00653 while (codec) { 00654 ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id"))); 00655 ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); 00656 codec = iks_next_tag(codec); 00657 } 00658 00659 /* Now gather all of the codecs that we are asked for */ 00660 ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability); 00661 00662 /* at this point, we received an awser from the remote Gtalk client, 00663 which allows us to compare capabilities */ 00664 tmp->jointcapability = tmp->capability & tmp->peercapability; 00665 if (!tmp->jointcapability) { 00666 ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->capability), 00667 ast_getformatname_multiple(s2, BUFSIZ, tmp->peercapability), 00668 ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcapability)); 00669 /* close session if capabilities don't match */ 00670 ast_queue_hangup(tmp->owner); 00671 00672 return -1; 00673 00674 } 00675 00676 from = iks_find_attrib(pak->x, "to"); 00677 if(!from) 00678 from = client->connection->jid->full; 00679 00680 if (tmp) { 00681 if (tmp->owner) 00682 ast_queue_control(tmp->owner, AST_CONTROL_ANSWER); 00683 } else 00684 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00685 gtalk_response(client, from, pak, NULL, NULL); 00686 return 1; 00687 }
static int gtalk_load_config | ( | void | ) | [static] |
Definition at line 1898 of file chan_gtalk.c.
References ahp, ast_category_browse(), ast_config_load(), ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), AST_MAX_CONTEXT, ast_parse_allow_disallow(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), bindaddr, clients, context, default_jbconf, global_capability, global_jbconf, GOOGLE_CONFIG, hp, LOG_WARNING, prefs, and var.
Referenced by load_module().
01899 { 01900 char *cat = NULL; 01901 struct ast_config *cfg = NULL; 01902 char context[AST_MAX_CONTEXT]; 01903 int allowguest = 1; 01904 struct ast_variable *var; 01905 struct gtalk *member; 01906 struct ast_codec_pref prefs; 01907 struct aji_client_container *clients; 01908 struct gtalk_candidate *global_candidates = NULL; 01909 struct hostent *hp; 01910 struct ast_hostent ahp; 01911 01912 cfg = ast_config_load(GOOGLE_CONFIG); 01913 if (!cfg) 01914 return 0; 01915 01916 /* Copy the default jb config over global_jbconf */ 01917 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01918 01919 cat = ast_category_browse(cfg, NULL); 01920 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 01921 /* handle jb conf */ 01922 if (!ast_jb_read_conf(&global_jbconf, var->name, var->value)) 01923 continue; 01924 01925 if (!strcasecmp(var->name, "allowguest")) 01926 allowguest = 01927 (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0; 01928 else if (!strcasecmp(var->name, "disallow")) 01929 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0); 01930 else if (!strcasecmp(var->name, "allow")) 01931 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1); 01932 else if (!strcasecmp(var->name, "context")) 01933 ast_copy_string(context, var->value, sizeof(context)); 01934 else if (!strcasecmp(var->name, "bindaddr")) { 01935 if (!(hp = ast_gethostbyname(var->value, &ahp))) { 01936 ast_log(LOG_WARNING, "Invalid address: %s\n", var->value); 01937 } else { 01938 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 01939 } 01940 } 01941 /* Idea to allow for custom candidates */ 01942 /* 01943 else if (!strcasecmp(var->name, "candidate")) { 01944 candidate = gtalk_create_candidate(var->value); 01945 if (candidate) { 01946 candidate->next = global_candidates; 01947 global_candidates = candidate; 01948 } 01949 } 01950 */ 01951 } 01952 while (cat) { 01953 if (strcasecmp(cat, "general")) { 01954 var = ast_variable_browse(cfg, cat); 01955 member = (struct gtalk *) malloc(sizeof(struct gtalk)); 01956 memset(member, 0, sizeof(struct gtalk)); 01957 ASTOBJ_INIT(member); 01958 ASTOBJ_WRLOCK(member); 01959 if (!strcasecmp(cat, "guest")) { 01960 ast_copy_string(member->name, "guest", sizeof(member->name)); 01961 ast_copy_string(member->user, "guest", sizeof(member->user)); 01962 ast_copy_string(member->context, context, sizeof(member->context)); 01963 member->allowguest = allowguest; 01964 member->prefs = prefs; 01965 while (var) { 01966 if (!strcasecmp(var->name, "disallow")) 01967 ast_parse_allow_disallow(&member->prefs, &member->capability, 01968 var->value, 0); 01969 else if (!strcasecmp(var->name, "allow")) 01970 ast_parse_allow_disallow(&member->prefs, &member->capability, 01971 var->value, 1); 01972 else if (!strcasecmp(var->name, "context")) 01973 ast_copy_string(member->context, var->value, 01974 sizeof(member->context)); 01975 /* Idea to allow for custom candidates */ 01976 /* 01977 else if (!strcasecmp(var->name, "candidate")) { 01978 candidate = gtalk_create_candidate(var->value); 01979 if (candidate) { 01980 candidate->next = member->ourcandidates; 01981 member->ourcandidates = candidate; 01982 } 01983 } 01984 */ 01985 var = var->next; 01986 } 01987 ASTOBJ_UNLOCK(member); 01988 clients = ast_aji_get_clients(); 01989 if (clients) { 01990 ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { 01991 ASTOBJ_WRLOCK(iterator); 01992 ASTOBJ_WRLOCK(member); 01993 member->connection = NULL; 01994 iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://www.google.com/session", IKS_RULE_DONE); 01995 iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://jabber.org/protocol/gtalk", IKS_RULE_DONE); 01996 ASTOBJ_UNLOCK(member); 01997 ASTOBJ_UNLOCK(iterator); 01998 }); 01999 ASTOBJ_CONTAINER_LINK(>alk_list, member); 02000 ASTOBJ_UNREF(member, gtalk_member_destroy); 02001 } else { 02002 ASTOBJ_UNLOCK(member); 02003 ASTOBJ_UNREF(member, gtalk_member_destroy); 02004 } 02005 } else { 02006 ASTOBJ_UNLOCK(member); 02007 if (gtalk_create_member(cat, var, allowguest, prefs, context, member)) 02008 ASTOBJ_CONTAINER_LINK(>alk_list, member); 02009 ASTOBJ_UNREF(member, gtalk_member_destroy); 02010 } 02011 } 02012 cat = ast_category_browse(cfg, cat); 02013 } 02014 gtalk_free_candidates(global_candidates); 02015 return 1; 02016 }
static void gtalk_member_destroy | ( | struct gtalk * | obj | ) | [static] |
Definition at line 261 of file chan_gtalk.c.
References free.
Referenced by gtalk_parser(), gtalk_request(), and unload_module().
00262 { 00263 free(obj); 00264 }
static struct ast_channel* gtalk_new | ( | struct gtalk * | client, | |
struct gtalk_pvt * | i, | |||
int | state, | |||
const char * | title | |||
) | [static] |
Start new gtalk channel.
Definition at line 1020 of file chan_gtalk.c.
References accountcode, gtalk::accountcode, ast_channel::adsicpe, ast_channel::amaflags, gtalk::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc(), ast_codec_choose(), ast_copy_string(), AST_FORMAT_VIDEO_MASK, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_rtcp_fd(), ast_rtp_fd(), ast_rtp_setstun(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), gtalk::callgroup, ast_channel::callgroup, gtalk::callingpres, gtalk_pvt::capability, ast_channel::cid, ast_callerid::cid_dnid, gtalk_pvt::cid_name, gtalk_pvt::cid_num, ast_callerid::cid_pres, ast_channel::context, gtalk::context, ast_channel::exten, gtalk_pvt::exten, ast_channel::fds, global_capability, global_jbconf, gtalk_tech, ast_channel::hangupcause, gtalk_pvt::jointcapability, language, gtalk::language, LOG_WARNING, musicclass, gtalk::musicclass, ast_channel::name, ast_channel::nativeformats, gtalk_pvt::owner, gtalk::pickupgroup, ast_channel::pickupgroup, gtalk_pvt::prefs, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, gtalk_pvt::rtp, ast_channel::tech, ast_channel::tech_pvt, gtalk_pvt::us, gtalk_pvt::vrtp, and ast_channel::writeformat.
Referenced by gtalk_newcall(), and gtalk_request().
01021 { 01022 struct ast_channel *tmp; 01023 int fmt; 01024 int what; 01025 const char *n2; 01026 01027 if (title) 01028 n2 = title; 01029 else 01030 n2 = i->us; 01031 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, client->accountcode, i->exten, client->context, client->amaflags, "Gtalk/%s-%04lx", n2, ast_random() & 0xffff); 01032 if (!tmp) { 01033 ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n"); 01034 return NULL; 01035 } 01036 tmp->tech = >alk_tech; 01037 01038 /* Select our native format based on codec preference until we receive 01039 something from another device to the contrary. */ 01040 if (i->jointcapability) 01041 what = i->jointcapability; 01042 else if (i->capability) 01043 what = i->capability; 01044 else 01045 what = global_capability; 01046 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK); 01047 fmt = ast_best_codec(tmp->nativeformats); 01048 01049 if (i->rtp) { 01050 ast_rtp_setstun(i->rtp, 1); 01051 tmp->fds[0] = ast_rtp_fd(i->rtp); 01052 tmp->fds[1] = ast_rtcp_fd(i->rtp); 01053 } 01054 if (i->vrtp) { 01055 ast_rtp_setstun(i->rtp, 1); 01056 tmp->fds[2] = ast_rtp_fd(i->vrtp); 01057 tmp->fds[3] = ast_rtcp_fd(i->vrtp); 01058 } 01059 if (state == AST_STATE_RING) 01060 tmp->rings = 1; 01061 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 01062 tmp->writeformat = fmt; 01063 tmp->rawwriteformat = fmt; 01064 tmp->readformat = fmt; 01065 tmp->rawreadformat = fmt; 01066 tmp->tech_pvt = i; 01067 01068 tmp->callgroup = client->callgroup; 01069 tmp->pickupgroup = client->pickupgroup; 01070 tmp->cid.cid_pres = client->callingpres; 01071 if (!ast_strlen_zero(client->accountcode)) 01072 ast_string_field_set(tmp, accountcode, client->accountcode); 01073 if (client->amaflags) 01074 tmp->amaflags = client->amaflags; 01075 if (!ast_strlen_zero(client->language)) 01076 ast_string_field_set(tmp, language, client->language); 01077 if (!ast_strlen_zero(client->musicclass)) 01078 ast_string_field_set(tmp, musicclass, client->musicclass); 01079 i->owner = tmp; 01080 ast_module_ref(ast_module_info->self); 01081 ast_copy_string(tmp->context, client->context, sizeof(tmp->context)); 01082 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 01083 01084 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) 01085 tmp->cid.cid_dnid = ast_strdup(i->exten); 01086 tmp->priority = 1; 01087 if (i->rtp) 01088 ast_jb_configure(tmp, &global_jbconf); 01089 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 01090 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 01091 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 01092 ast_hangup(tmp); 01093 tmp = NULL; 01094 } 01095 01096 return tmp; 01097 }
static int gtalk_newcall | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1173 of file chan_gtalk.c.
References gtalk_pvt::alreadygone, ast_aji_get_client(), ast_channel_free(), ast_copy_string(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_rtp_get_current_formats(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, gtalk_pvt::capability, gtalk::connection, gtalk_action(), gtalk_alloc(), gtalk_create_candidates(), gtalk_free_pvt(), gtalk_hangup(), gtalk_invite_response(), gtalk_new(), gtalk_response(), aji_client::jid, gtalk_pvt::jointcapability, gtalk_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, gtalk::name, gtalk_pvt::next, gtalk::p, gtalk_pvt::peercapability, gtalk_pvt::rtp, gtalk_pvt::sid, gtalk_pvt::them, and gtalk_pvt::us.
Referenced by gtalk_parser().
01174 { 01175 struct gtalk_pvt *p, *tmp = client->p; 01176 struct ast_channel *chan; 01177 int res; 01178 iks *codec; 01179 char *from = NULL; 01180 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ]; 01181 int peernoncodeccapability; 01182 01183 /* Make sure our new call doesn't exist yet */ 01184 from = iks_find_attrib(pak->x,"to"); 01185 if(!from) 01186 from = client->connection->jid->full; 01187 01188 while (tmp) { 01189 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) { 01190 ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid); 01191 gtalk_response(client, from, pak, "out-of-order", NULL); 01192 return -1; 01193 } 01194 tmp = tmp->next; 01195 } 01196 01197 if (!strcasecmp(client->name, "guest")){ 01198 /* the guest account is not tied to any configured XMPP client, 01199 let's set it now */ 01200 client->connection = ast_aji_get_client(from); 01201 if (!client->connection) { 01202 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); 01203 return -1; 01204 } 01205 } 01206 01207 p = gtalk_alloc(client, from, pak->from->full, iks_find_attrib(pak->query, "id")); 01208 if (!p) { 01209 ast_log(LOG_WARNING, "Unable to allocate gtalk structure!\n"); 01210 return -1; 01211 } 01212 01213 chan = gtalk_new(client, p, AST_STATE_DOWN, pak->from->user); 01214 if (!chan) { 01215 gtalk_free_pvt(client, p); 01216 return -1; 01217 } 01218 01219 ast_mutex_lock(&p->lock); 01220 ast_copy_string(p->them, pak->from->full, sizeof(p->them)); 01221 if (iks_find_attrib(pak->query, "id")) { 01222 ast_copy_string(p->sid, iks_find_attrib(pak->query, "id"), 01223 sizeof(p->sid)); 01224 } 01225 01226 /* codec points to the first <payload-type/> tag */ 01227 codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x))); 01228 01229 while (codec) { 01230 ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id"))); 01231 ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); 01232 codec = iks_next_tag(codec); 01233 } 01234 01235 /* Now gather all of the codecs that we are asked for */ 01236 ast_rtp_get_current_formats(p->rtp, &p->peercapability, &peernoncodeccapability); 01237 p->jointcapability = p->capability & p->peercapability; 01238 ast_mutex_unlock(&p->lock); 01239 01240 ast_setstate(chan, AST_STATE_RING); 01241 if (!p->jointcapability) { 01242 ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->capability), 01243 ast_getformatname_multiple(s2, BUFSIZ, p->peercapability), 01244 ast_getformatname_multiple(s3, BUFSIZ, p->jointcapability)); 01245 /* close session if capabilities don't match */ 01246 gtalk_action(client, p, "reject"); 01247 p->alreadygone = 1; 01248 gtalk_hangup(chan); 01249 ast_channel_free(chan); 01250 return -1; 01251 } 01252 01253 res = ast_pbx_start(chan); 01254 01255 switch (res) { 01256 case AST_PBX_FAILED: 01257 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 01258 gtalk_response(client, from, pak, "service-unavailable", NULL); 01259 break; 01260 case AST_PBX_CALL_LIMIT: 01261 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 01262 gtalk_response(client, from, pak, "service-unavailable", NULL); 01263 break; 01264 case AST_PBX_SUCCESS: 01265 gtalk_response(client, from, pak, NULL, NULL); 01266 gtalk_invite_response(p, p->them, p->us,p->sid, 0); 01267 gtalk_create_candidates(client, p, p->sid, p->them, p->us); 01268 /* nothing to do */ 01269 break; 01270 } 01271 01272 return 1; 01273 }
static int gtalk_parser | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1763 of file chan_gtalk.c.
References ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, gtalk_add_candidate(), gtalk_handle_dtmf(), gtalk_hangup_farend(), gtalk_is_accepted(), gtalk_is_answered(), gtalk_member_destroy(), gtalk_newcall(), LOG_DEBUG, and option_debug.
Referenced by gtalk_create_member().
01764 { 01765 struct gtalk *client = ASTOBJ_REF((struct gtalk *) data); 01766 01767 if (iks_find_with_attrib(pak->x, "session", "type", "initiate")) { 01768 /* New call */ 01769 gtalk_newcall(client, pak); 01770 } else if (iks_find_with_attrib(pak->x, "session", "type", "candidates") || iks_find_with_attrib(pak->x, "session", "type", "transport-info")) { 01771 if (option_debug > 2) 01772 ast_log(LOG_DEBUG, "About to add candidate!\n"); 01773 gtalk_add_candidate(client, pak); 01774 if (option_debug > 2) 01775 ast_log(LOG_DEBUG, "Candidate Added!\n"); 01776 } else if (iks_find_with_attrib(pak->x, "session", "type", "accept")) { 01777 gtalk_is_answered(client, pak); 01778 } else if (iks_find_with_attrib(pak->x, "session", "type", "transport-accept")) { 01779 gtalk_is_accepted(client, pak); 01780 } else if (iks_find_with_attrib(pak->x, "session", "type", "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) { 01781 gtalk_handle_dtmf(client, pak); 01782 } else if (iks_find_with_attrib(pak->x, "session", "type", "terminate")) { 01783 gtalk_hangup_farend(client, pak); 01784 } else if (iks_find_with_attrib(pak->x, "session", "type", "reject")) { 01785 gtalk_hangup_farend(client, pak); 01786 } 01787 ASTOBJ_UNREF(client, gtalk_member_destroy); 01788 return IKS_FILTER_EAT; 01789 }
static struct ast_frame * gtalk_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1432 of file chan_gtalk.c.
References ast_mutex_lock(), ast_mutex_unlock(), gtalk_rtp_read(), gtalk_pvt::lock, and ast_channel::tech_pvt.
01433 { 01434 struct ast_frame *fr; 01435 struct gtalk_pvt *p = ast->tech_pvt; 01436 01437 ast_mutex_lock(&p->lock); 01438 fr = gtalk_rtp_read(ast, p); 01439 ast_mutex_unlock(&p->lock); 01440 return fr; 01441 }
static struct ast_channel * gtalk_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Part of PBX interface.
Definition at line 1658 of file chan_gtalk.c.
References ast_aji_get_client(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, gtalk::connection, find_gtalk(), gtalk_alloc(), gtalk_member_destroy(), gtalk_new(), aji_client::jid, LOG_ERROR, LOG_WARNING, gtalk::name, s, and gtalk::user.
01659 { 01660 struct gtalk_pvt *p = NULL; 01661 struct gtalk *client = NULL; 01662 char *sender = NULL, *to = NULL, *s = NULL; 01663 struct ast_channel *chan = NULL; 01664 01665 if (data) { 01666 s = ast_strdupa(data); 01667 if (s) { 01668 sender = strsep(&s, "/"); 01669 if (sender && (sender[0] != '\0')) 01670 to = strsep(&s, "/"); 01671 if (!to) { 01672 ast_log(LOG_ERROR, "Bad arguments in Gtalk Dialstring: %s\n", (char*) data); 01673 return NULL; 01674 } 01675 } 01676 } 01677 01678 client = find_gtalk(to, sender); 01679 if (!client) { 01680 ast_log(LOG_WARNING, "Could not find recipient.\n"); 01681 return NULL; 01682 } 01683 if (!strcasecmp(client->name, "guest")){ 01684 /* the guest account is not tied to any configured XMPP client, 01685 let's set it now */ 01686 client->connection = ast_aji_get_client(sender); 01687 if (!client->connection) { 01688 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender); 01689 ASTOBJ_UNREF(client, gtalk_member_destroy); 01690 return NULL; 01691 } 01692 } 01693 01694 ASTOBJ_WRLOCK(client); 01695 p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL); 01696 if (p) 01697 chan = gtalk_new(client, p, AST_STATE_DOWN, to); 01698 01699 ASTOBJ_UNLOCK(client); 01700 return chan; 01701 }
static int gtalk_response | ( | struct gtalk * | client, | |
char * | from, | |||
ikspak * | pak, | |||
const char * | reasonstr, | |||
const char * | reasonstr2 | |||
) | [static] |
Definition at line 604 of file chan_gtalk.c.
References gtalk::connection, and aji_client::p.
Referenced by gtalk_handle_dtmf(), gtalk_hangup_farend(), gtalk_is_accepted(), gtalk_is_answered(), and gtalk_newcall().
00605 { 00606 iks *response = NULL, *error = NULL, *reason = NULL; 00607 int res = -1; 00608 00609 response = iks_new("iq"); 00610 if (response) { 00611 iks_insert_attrib(response, "type", "result"); 00612 iks_insert_attrib(response, "from", from); 00613 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from")); 00614 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id")); 00615 if (reasonstr) { 00616 error = iks_new("error"); 00617 if (error) { 00618 iks_insert_attrib(error, "type", "cancel"); 00619 reason = iks_new(reasonstr); 00620 if (reason) 00621 iks_insert_node(error, reason); 00622 iks_insert_node(response, error); 00623 } 00624 } 00625 iks_send(client->connection->p, response); 00626 if (reason) 00627 iks_delete(reason); 00628 if (error) 00629 iks_delete(error); 00630 iks_delete(response); 00631 res = 0; 00632 } 00633 return res; 00634 }
static int gtalk_ringing_ack | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 535 of file chan_gtalk.c.
References AST_CONTROL_RINGING, ast_queue_control(), gtalk::connection, aji_client::f, gtalk_pvt::owner, gtalk_pvt::parent, and gtalk_pvt::ringrule.
Referenced by gtalk_call().
00536 { 00537 struct gtalk_pvt *p = data; 00538 00539 if (p->ringrule) 00540 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 00541 p->ringrule = NULL; 00542 if (p->owner) 00543 ast_queue_control(p->owner, AST_CONTROL_RINGING); 00544 return IKS_FILTER_EAT; 00545 }
static struct ast_frame* gtalk_rtp_read | ( | struct ast_channel * | ast, | |
struct gtalk_pvt * | p | |||
) | [static] |
Definition at line 1403 of file chan_gtalk.c.
References AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_VOICE, ast_log(), ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), f, gtalk_update_stun(), LOG_DEBUG, ast_channel::nativeformats, option_debug, gtalk_pvt::owner, gtalk_pvt::parent, ast_channel::readformat, gtalk_pvt::rtp, and ast_channel::writeformat.
Referenced by gtalk_read().
01404 { 01405 struct ast_frame *f; 01406 01407 if (!p->rtp) 01408 return &ast_null_frame; 01409 f = ast_rtp_read(p->rtp); 01410 gtalk_update_stun(p->parent, p); 01411 if (p->owner) { 01412 /* We already hold the channel lock */ 01413 if (f->frametype == AST_FRAME_VOICE) { 01414 if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { 01415 if (option_debug) 01416 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass); 01417 p->owner->nativeformats = 01418 (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass; 01419 ast_set_read_format(p->owner, p->owner->readformat); 01420 ast_set_write_format(p->owner, p->owner->writeformat); 01421 } 01422 /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { 01423 f = ast_dsp_process(p->owner, p->vad, f); 01424 if (option_debug && f && (f->frametype == AST_FRAME_DTMF)) 01425 ast_log(LOG_DEBUG, "* Detected inband DTMF '%c'\n", f->subclass); 01426 } */ 01427 } 01428 } 01429 return f; 01430 }
static int gtalk_sendhtml | ( | struct ast_channel * | ast, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 1587 of file chan_gtalk.c.
References ast_log(), and LOG_NOTICE.
01588 { 01589 ast_log(LOG_NOTICE, "XXX Implement gtalk sendhtml XXX\n"); 01590 01591 return -1; 01592 }
static int gtalk_set_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
struct ast_rtp * | vrtp, | |||
int | codecs, | |||
int | nat_active | |||
) | [static] |
Definition at line 584 of file chan_gtalk.c.
References ast_mutex_lock(), ast_mutex_unlock(), gtalk_pvt::lock, and ast_channel::tech_pvt.
00585 { 00586 struct gtalk_pvt *p; 00587 00588 p = chan->tech_pvt; 00589 if (!p) 00590 return -1; 00591 ast_mutex_lock(&p->lock); 00592 00593 /* if (rtp) 00594 ast_rtp_get_peer(rtp, &p->redirip); 00595 else 00596 memset(&p->redirip, 0, sizeof(p->redirip)); 00597 p->redircodecs = codecs; */ 00598 00599 /* Reset lastrtprx timer */ 00600 ast_mutex_unlock(&p->lock); 00601 return 0; 00602 }
static int gtalk_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
CLI command "gtalk show channels".
Definition at line 1704 of file chan_gtalk.c.
References AJI_MAX_JIDLEN, ast_cli(), ast_copy_string(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, FORMAT, gtalk_list, gtalklock, LOG_WARNING, ast_channel::name, gtalk_pvt::next, gtalk_pvt::owner, ast_channel::readformat, RESULT_SHOWUSAGE, RESULT_SUCCESS, gtalk_pvt::them, and ast_channel::writeformat.
01705 { 01706 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" 01707 struct gtalk_pvt *p; 01708 struct ast_channel *chan; 01709 int numchans = 0; 01710 char them[AJI_MAX_JIDLEN]; 01711 char *jid = NULL; 01712 char *resource = NULL; 01713 01714 if (argc != 3) 01715 return RESULT_SHOWUSAGE; 01716 01717 ast_mutex_lock(>alklock); 01718 ast_cli(fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); 01719 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { 01720 ASTOBJ_WRLOCK(iterator); 01721 p = iterator->p; 01722 while(p) { 01723 chan = p->owner; 01724 ast_copy_string(them, p->them, sizeof(them)); 01725 jid = them; 01726 resource = strchr(them, '/'); 01727 if (!resource) 01728 resource = "None"; 01729 else { 01730 *resource = '\0'; 01731 resource ++; 01732 } 01733 if (chan) 01734 ast_cli(fd, FORMAT, 01735 chan->name, 01736 jid, 01737 resource, 01738 ast_getformatname(chan->readformat), 01739 ast_getformatname(chan->writeformat) 01740 ); 01741 else 01742 ast_log(LOG_WARNING, "No available channel\n"); 01743 numchans ++; 01744 p = p->next; 01745 } 01746 ASTOBJ_UNLOCK(iterator); 01747 }); 01748 01749 ast_mutex_unlock(>alklock); 01750 01751 ast_cli(fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : ""); 01752 return RESULT_SUCCESS; 01753 #undef FORMAT 01754 }
Definition at line 1275 of file chan_gtalk.c.
References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_stun_request(), hp, gtalk_candidate::ip, gtalk_pvt::laststun, LOG_DEBUG, gtalk_candidate::next, option_debug, gtalk_pvt::ourcandidates, gtalk_candidate::port, gtalk_pvt::rtp, gtalk_pvt::theircandidates, gtalk_candidate::username, and username.
Referenced by gtalk_add_candidate(), and gtalk_rtp_read().
01276 { 01277 struct gtalk_candidate *tmp; 01278 struct hostent *hp; 01279 struct ast_hostent ahp; 01280 struct sockaddr_in sin; 01281 struct sockaddr_in aux; 01282 01283 if (time(NULL) == p->laststun) 01284 return 0; 01285 01286 tmp = p->theircandidates; 01287 p->laststun = time(NULL); 01288 while (tmp) { 01289 char username[256]; 01290 01291 /* Find the IP address of the host */ 01292 hp = ast_gethostbyname(tmp->ip, &ahp); 01293 sin.sin_family = AF_INET; 01294 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01295 sin.sin_port = htons(tmp->port); 01296 snprintf(username, sizeof(username), "%s%s", tmp->username, 01297 p->ourcandidates->username); 01298 01299 /* Find out the result of the STUN */ 01300 ast_rtp_get_peer(p->rtp, &aux); 01301 01302 /* If the STUN result is different from the IP of the hostname, 01303 lock on the stun IP of the hostname advertised by the 01304 remote client */ 01305 if (aux.sin_addr.s_addr && 01306 aux.sin_addr.s_addr != sin.sin_addr.s_addr) 01307 ast_rtp_stun_request(p->rtp, &aux, username); 01308 else 01309 ast_rtp_stun_request(p->rtp, &sin, username); 01310 01311 if (aux.sin_addr.s_addr && option_debug > 3) { 01312 ast_log(LOG_DEBUG, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip); 01313 ast_log(LOG_DEBUG, "Sending STUN request to %s\n", tmp->ip); 01314 } 01315 01316 tmp = tmp->next; 01317 } 01318 return 1; 01319 }
static int gtalk_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Send frame to media channel (rtp).
Definition at line 1444 of file chan_gtalk.c.
References AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, gtalk_pvt::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, gtalk_pvt::rtp, ast_frame::subclass, ast_channel::tech_pvt, gtalk_pvt::vrtp, and ast_channel::writeformat.
01445 { 01446 struct gtalk_pvt *p = ast->tech_pvt; 01447 int res = 0; 01448 01449 switch (frame->frametype) { 01450 case AST_FRAME_VOICE: 01451 if (!(frame->subclass & ast->nativeformats)) { 01452 ast_log(LOG_WARNING, 01453 "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", 01454 frame->subclass, ast->nativeformats, ast->readformat, 01455 ast->writeformat); 01456 return 0; 01457 } 01458 if (p) { 01459 ast_mutex_lock(&p->lock); 01460 if (p->rtp) { 01461 res = ast_rtp_write(p->rtp, frame); 01462 } 01463 ast_mutex_unlock(&p->lock); 01464 } 01465 break; 01466 case AST_FRAME_VIDEO: 01467 if (p) { 01468 ast_mutex_lock(&p->lock); 01469 if (p->vrtp) { 01470 res = ast_rtp_write(p->vrtp, frame); 01471 } 01472 ast_mutex_unlock(&p->lock); 01473 } 01474 break; 01475 case AST_FRAME_IMAGE: 01476 return 0; 01477 break; 01478 default: 01479 ast_log(LOG_WARNING, "Can't send %d type frames with Gtalk write\n", 01480 frame->frametype); 01481 return 0; 01482 } 01483 01484 return res; 01485 }
static int load_module | ( | void | ) | [static] |
Load module into PBX, register channel.
Definition at line 2019 of file chan_gtalk.c.
References __ourip, ast_channel_register(), ast_cli_register_multiple(), ast_find_ourip(), ast_log(), ast_module_helper(), AST_MODULE_LOAD_DECLINE, ast_rtp_proto_register(), ASTOBJ_CONTAINER_INIT, bindaddr, free, GOOGLE_CONFIG, gtalk_cli, gtalk_list, gtalk_load_config(), gtalk_rtp, gtalk_tech, io, io_context_create(), LOG_ERROR, LOG_WARNING, sched_context_create(), and ast_channel_tech::type.
02020 { 02021 char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); 02022 free(jabber_loaded); 02023 if (!jabber_loaded) { 02024 /* If embedded, check for a different module name */ 02025 jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0); 02026 free(jabber_loaded); 02027 if (!jabber_loaded) { 02028 ast_log(LOG_ERROR, "chan_gtalk.so depends upon res_jabber.so\n"); 02029 return AST_MODULE_LOAD_DECLINE; 02030 } 02031 } 02032 02033 #ifdef HAVE_GNUTLS 02034 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); 02035 #endif /* HAVE_GNUTLS */ 02036 02037 ASTOBJ_CONTAINER_INIT(>alk_list); 02038 if (!gtalk_load_config()) { 02039 ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", GOOGLE_CONFIG); 02040 return 0; 02041 } 02042 02043 sched = sched_context_create(); 02044 if (!sched) 02045 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 02046 02047 io = io_context_create(); 02048 if (!io) 02049 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 02050 02051 if (ast_find_ourip(&__ourip, bindaddr)) { 02052 ast_log(LOG_WARNING, "Unable to get own IP address, Gtalk disabled\n"); 02053 return 0; 02054 } 02055 02056 ast_rtp_proto_register(>alk_rtp); 02057 ast_cli_register_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0])); 02058 02059 /* Make sure we can register our channel type */ 02060 if (ast_channel_register(>alk_tech)) { 02061 ast_log(LOG_ERROR, "Unable to register channel class %s\n", gtalk_tech.type); 02062 return -1; 02063 } 02064 return 0; 02065 }
static int reload | ( | void | ) | [static] |
static int unload_module | ( | void | ) | [static] |
Unload the gtalk channel from Asterisk.
Definition at line 2074 of file chan_gtalk.c.
References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, gtalk_cli, gtalk_list, gtalk_member_destroy(), gtalk_rtp, gtalk_tech, gtalklock, LOG_WARNING, gtalk_pvt::next, and gtalk_pvt::owner.
02075 { 02076 struct gtalk_pvt *privates = NULL; 02077 ast_cli_unregister_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0])); 02078 /* First, take us out of the channel loop */ 02079 ast_channel_unregister(>alk_tech); 02080 ast_rtp_proto_unregister(>alk_rtp); 02081 02082 if (!ast_mutex_lock(>alklock)) { 02083 /* Hangup all interfaces if they have an owner */ 02084 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { 02085 ASTOBJ_WRLOCK(iterator); 02086 privates = iterator->p; 02087 while(privates) { 02088 if (privates->owner) 02089 ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD); 02090 privates = privates->next; 02091 } 02092 iterator->p = NULL; 02093 ASTOBJ_UNLOCK(iterator); 02094 }); 02095 ast_mutex_unlock(>alklock); 02096 } else { 02097 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 02098 return -1; 02099 } 02100 ASTOBJ_CONTAINER_DESTROYALL(>alk_list, gtalk_member_destroy); 02101 ASTOBJ_CONTAINER_DESTROY(>alk_list); 02102 return 0; 02103 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Gtalk Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 2109 of file chan_gtalk.c.
struct in_addr __ourip [static] |
Definition at line 230 of file chan_gtalk.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 2109 of file chan_gtalk.c.
struct sockaddr_in bindaddr = { 0, } [static] |
The address we bind to
Definition at line 226 of file chan_gtalk.c.
Referenced by ast_sip_ouraddrfor(), gtalk_alloc(), gtalk_create_candidates(), gtalk_load_config(), load_module(), reload_config(), sip_alloc(), sip_show_settings(), start_rtp(), and transmit_register().
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 90 of file chan_gtalk.c.
const char desc[] = "Gtalk Channel" [static] |
Definition at line 174 of file chan_gtalk.c.
Referenced by ast_cause2str(), ast_codec2str(), load_rpt_vars(), misdn_cfg_get_desc(), and show_config_description().
char externip[16] [static] |
Definition at line 56 of file chan_gtalk.c.
int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 [static] |
Definition at line 176 of file chan_gtalk.c.
Referenced by gtalk_alloc(), gtalk_load_config(), and gtalk_new().
struct ast_jb_conf global_jbconf [static] |
Definition at line 97 of file chan_gtalk.c.
struct ast_cli_entry gtalk_cli[] [static] |
Initial value:
{ {{ "gtalk", "reload", NULL}, gtalk_do_reload, "Reload GoogleTalk configuration", reload_usage }, {{ "gtalk", "show", "channels", NULL}, gtalk_show_channels, "Show GoogleTalk channels", show_channels_usage }, }
Definition at line 250 of file chan_gtalk.c.
Referenced by load_module(), and unload_module().
struct gtalk_container gtalk_list [static] |
Definition at line 259 of file chan_gtalk.c.
Referenced by find_gtalk(), gtalk_show_channels(), load_module(), and unload_module().
struct ast_rtp_protocol gtalk_rtp [static] |
RTP driver interface.
Definition at line 234 of file chan_gtalk.c.
Referenced by load_module(), and unload_module().
struct ast_channel_tech gtalk_tech [static] |
PBX interface structure for channel registration.
Definition at line 206 of file chan_gtalk.c.
Referenced by gtalk_new(), load_module(), and unload_module().
ast_mutex_t gtalklock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the interface list (of gtalk_pvt's)
Definition at line 178 of file chan_gtalk.c.
Referenced by gtalk_alloc(), gtalk_show_channels(), and unload_module().
struct io_context* io [static] |
The IO context
Definition at line 229 of file chan_gtalk.c.
Referenced by __oh323_rtp_create(), ast_expr(), ast_rtp_new(), ast_udptl_new(), ast_udptl_new_with_bindaddr(), do_monitor(), gtalk_alloc(), load_module(), network_thread(), peer_set_srcaddr(), reload(), reload_config(), set_config(), sip_alloc(), start_rtp(), and unload_module().
char reload_usage[] [static] |
Initial value:
"Usage: gtalk reload\n" " Reload gtalk channel driver.\n"
Definition at line 245 of file chan_gtalk.c.
struct sched_context* sched [static] |
The scheduling context
Definition at line 228 of file chan_gtalk.c.
char show_channels_usage[] [static] |
Initial value:
"Usage: gtalk show channels\n" " Shows current state of the Gtalk channels.\n"
Definition at line 241 of file chan_gtalk.c.