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