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