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