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