#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"
#include "asterisk/jingle.h"
#include "asterisk/features.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 " %-25.20s %-15.30s\n" |
| #define | FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
| #define | GOOGLE_CONFIG "gtalk.conf" |
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, struct ast_format *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, const 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_begin (struct ast_channel *ast, char digit) |
| static int | gtalk_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| 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 void | gtalk_get_codec (struct ast_channel *chan, struct ast_format_cap *result) |
| static int | gtalk_get_local_ip (struct ast_sockaddr *ourip) |
| 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_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) |
| CLI command "gtalk reload". | |
| static struct ast_frame * | gtalk_read (struct ast_channel *ast) |
| static struct ast_channel * | gtalk_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *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, const struct ast_format_cap *cap, 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 char * | gtalk_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| List global settings for the GoogleTalk channel. | |
| static int | gtalk_update_externip (void) |
| 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 | unload_module (void) |
| Reload module. | |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } |
| static struct in_addr | __ourip |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct sockaddr_in | bindaddr = { 0, } |
| static const int | DEFAULT_ALLOWGUEST = 1 |
| static const char | DEFAULT_CONTEXT [] = "default" |
| static struct ast_jb_conf | default_jbconf |
| static const char | desc [] = "Gtalk Channel" |
| static char | externip [16] |
| static int | global_allowguest |
| static struct ast_format_cap * | global_capability |
| static char | global_context [AST_MAX_CONTEXT] |
| static struct ast_jb_conf | global_jbconf |
| static char | global_parkinglot [AST_MAX_CONTEXT] |
| static int | global_stunaddr |
| 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 = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| static struct io_context * | io |
| static struct ast_sched_context * | sched |
| static struct sockaddr_in | stunaddr |
********** General TODO:s
Definition in file chan_gtalk.c.
| #define FORMAT " %-25.20s %-15.30s\n" |
| #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
| #define GOOGLE_CONFIG "gtalk.conf" |
| enum gtalk_connect_type |
Definition at line 98 of file chan_gtalk.c.
00098 { 00099 AJI_CONNECT_STUN = 1, 00100 AJI_CONNECT_LOCAL = 2, 00101 AJI_CONNECT_RELAY = 3, 00102 };
| enum gtalk_protocol |
Definition at line 93 of file chan_gtalk.c.
00093 { 00094 AJI_PROTOCOL_UDP = 1, 00095 AJI_PROTOCOL_SSLTCP = 2, 00096 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 2407 of file chan_gtalk.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 2407 of file chan_gtalk.c.
| static int add_codec_to_answer | ( | const struct gtalk_pvt * | p, | |
| struct ast_format * | codec, | |||
| iks * | dcodecs | |||
| ) | [static] |
Definition at line 294 of file chan_gtalk.c.
References ast_getformatname(), ast_log(), format, and LOG_WARNING.
Referenced by gtalk_invite(), and jingle_accept_call().
00295 { 00296 int res = 0; 00297 const char *format = ast_getformatname(codec); 00298 00299 if (!strcasecmp("ulaw", format)) { 00300 iks *payload_eg711u, *payload_pcmu; 00301 payload_pcmu = iks_new("payload-type"); 00302 payload_eg711u = iks_new("payload-type"); 00303 00304 if(!payload_eg711u || !payload_pcmu) { 00305 iks_delete(payload_pcmu); 00306 iks_delete(payload_eg711u); 00307 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00308 return -1; 00309 } 00310 iks_insert_attrib(payload_pcmu, "id", "0"); 00311 iks_insert_attrib(payload_pcmu, "name", "PCMU"); 00312 iks_insert_attrib(payload_pcmu, "clockrate","8000"); 00313 iks_insert_attrib(payload_pcmu, "bitrate","64000"); 00314 iks_insert_attrib(payload_eg711u, "id", "100"); 00315 iks_insert_attrib(payload_eg711u, "name", "EG711U"); 00316 iks_insert_attrib(payload_eg711u, "clockrate","8000"); 00317 iks_insert_attrib(payload_eg711u, "bitrate","64000"); 00318 iks_insert_node(dcodecs, payload_pcmu); 00319 iks_insert_node(dcodecs, payload_eg711u); 00320 res ++; 00321 } 00322 if (!strcasecmp("alaw", format)) { 00323 iks *payload_eg711a, *payload_pcma; 00324 payload_pcma = iks_new("payload-type"); 00325 payload_eg711a = iks_new("payload-type"); 00326 if(!payload_eg711a || !payload_pcma) { 00327 iks_delete(payload_eg711a); 00328 iks_delete(payload_pcma); 00329 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00330 return -1; 00331 } 00332 iks_insert_attrib(payload_pcma, "id", "8"); 00333 iks_insert_attrib(payload_pcma, "name", "PCMA"); 00334 iks_insert_attrib(payload_pcma, "clockrate","8000"); 00335 iks_insert_attrib(payload_pcma, "bitrate","64000"); 00336 payload_eg711a = iks_new("payload-type"); 00337 iks_insert_attrib(payload_eg711a, "id", "101"); 00338 iks_insert_attrib(payload_eg711a, "name", "EG711A"); 00339 iks_insert_attrib(payload_eg711a, "clockrate","8000"); 00340 iks_insert_attrib(payload_eg711a, "bitrate","64000"); 00341 iks_insert_node(dcodecs, payload_pcma); 00342 iks_insert_node(dcodecs, payload_eg711a); 00343 res ++; 00344 } 00345 if (!strcasecmp("ilbc", format)) { 00346 iks *payload_ilbc = iks_new("payload-type"); 00347 if(!payload_ilbc) { 00348 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00349 return -1; 00350 } 00351 iks_insert_attrib(payload_ilbc, "id", "97"); 00352 iks_insert_attrib(payload_ilbc, "name", "iLBC"); 00353 iks_insert_attrib(payload_ilbc, "clockrate","8000"); 00354 iks_insert_attrib(payload_ilbc, "bitrate","13300"); 00355 iks_insert_node(dcodecs, payload_ilbc); 00356 res ++; 00357 } 00358 if (!strcasecmp("g723", format)) { 00359 iks *payload_g723 = iks_new("payload-type"); 00360 if(!payload_g723) { 00361 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00362 return -1; 00363 } 00364 iks_insert_attrib(payload_g723, "id", "4"); 00365 iks_insert_attrib(payload_g723, "name", "G723"); 00366 iks_insert_attrib(payload_g723, "clockrate","8000"); 00367 iks_insert_attrib(payload_g723, "bitrate","6300"); 00368 iks_insert_node(dcodecs, payload_g723); 00369 res ++; 00370 } 00371 if (!strcasecmp("speex", format)) { 00372 iks *payload_speex = iks_new("payload-type"); 00373 if(!payload_speex) { 00374 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00375 return -1; 00376 } 00377 iks_insert_attrib(payload_speex, "id", "110"); 00378 iks_insert_attrib(payload_speex, "name", "speex"); 00379 iks_insert_attrib(payload_speex, "clockrate","8000"); 00380 iks_insert_attrib(payload_speex, "bitrate","11000"); 00381 iks_insert_node(dcodecs, payload_speex); 00382 res++; 00383 } 00384 if (!strcasecmp("gsm", format)) { 00385 iks *payload_gsm = iks_new("payload-type"); 00386 if(!payload_gsm) { 00387 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00388 return -1; 00389 } 00390 iks_insert_attrib(payload_gsm, "id", "103"); 00391 iks_insert_attrib(payload_gsm, "name", "gsm"); 00392 iks_insert_node(dcodecs, payload_gsm); 00393 res++; 00394 } 00395 00396 return res; 00397 }
| static struct gtalk* find_gtalk | ( | char * | name, | |
| char * | connection | |||
| ) | [static, read] |
Definition at line 262 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, and strsep().
Referenced by gtalk_request().
00263 { 00264 struct gtalk *gtalk = NULL; 00265 char *domain = NULL , *s = NULL; 00266 00267 if (strchr(connection, '@')) { 00268 s = ast_strdupa(connection); 00269 domain = strsep(&s, "@"); 00270 ast_verbose("OOOOH domain = %s\n", domain); 00271 } 00272 gtalk = ASTOBJ_CONTAINER_FIND(>alk_list, name); 00273 if (!gtalk && strchr(name, '@')) 00274 gtalk = ASTOBJ_CONTAINER_FIND_FULL(>alk_list, name, user,,, strcasecmp); 00275 00276 if (!gtalk) { 00277 /* guest call */ 00278 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { 00279 ASTOBJ_RDLOCK(iterator); 00280 if (!strcasecmp(iterator->name, "guest")) { 00281 gtalk = iterator; 00282 } 00283 ASTOBJ_UNLOCK(iterator); 00284 00285 if (gtalk) 00286 break; 00287 }); 00288 00289 } 00290 return gtalk; 00291 }
| static int gtalk_action | ( | struct gtalk * | client, | |
| struct gtalk_pvt * | p, | |||
| const char * | action | |||
| ) | [static] |
Definition at line 1217 of file chan_gtalk.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_strdupa, gtalk::connection, GOOGLE_NS, gtalk_pvt::initiator, aji_client::mid, gtalk_pvt::sid, gtalk_pvt::them, and gtalk_pvt::us.
Referenced by gtalk_hangup(), and gtalk_newcall().
01218 { 01219 iks *request, *session = NULL; 01220 int res = -1; 01221 char *lowerthem = NULL; 01222 01223 request = iks_new("iq"); 01224 if (request) { 01225 iks_insert_attrib(request, "type", "set"); 01226 iks_insert_attrib(request, "from", p->us); 01227 iks_insert_attrib(request, "to", p->them); 01228 iks_insert_attrib(request, "id", client->connection->mid); 01229 ast_aji_increment_mid(client->connection->mid); 01230 session = iks_new("session"); 01231 if (session) { 01232 iks_insert_attrib(session, "type", action); 01233 iks_insert_attrib(session, "id", p->sid); 01234 /* put the initiator attribute to lower case if we receive the call 01235 * otherwise GoogleTalk won't establish the session */ 01236 if (!p->initiator) { 01237 char c; 01238 char *t = lowerthem = ast_strdupa(p->them); 01239 while (((c = *t) != '/') && (*t++ = tolower(c))); 01240 } 01241 iks_insert_attrib(session, "initiator", p->initiator ? p->us : lowerthem); 01242 iks_insert_attrib(session, "xmlns", GOOGLE_NS); 01243 iks_insert_node(request, session); 01244 ast_aji_send(client->connection, request); 01245 res = 0; 01246 } 01247 } 01248 01249 iks_delete(session); 01250 iks_delete(request); 01251 01252 return res; 01253 }
| static int gtalk_add_candidate | ( | struct gtalk * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1525 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, S_OR, gtalk_pvt::theircandidates, gtalk_candidate::type, and gtalk_candidate::username.
Referenced by gtalk_parser().
01526 { 01527 struct gtalk_pvt *p = NULL, *tmp = NULL; 01528 struct aji_client *c = client->connection; 01529 struct gtalk_candidate *newcandidate = NULL; 01530 iks *traversenodes = NULL, *receipt = NULL; 01531 char *from; 01532 01533 from = iks_find_attrib(pak->x,"to"); 01534 if (!from) { 01535 from = c->jid->full; 01536 } 01537 01538 for (tmp = client->p; tmp; tmp = tmp->next) { 01539 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || 01540 (iks_find_attrib(pak->query, "id") && !strcmp(iks_find_attrib(pak->query, "id"), tmp->sid))) { 01541 p = tmp; 01542 break; 01543 } 01544 } 01545 01546 if (!p) { 01547 return -1; 01548 } 01549 traversenodes = pak->query; 01550 while(traversenodes) { 01551 if(!strcasecmp(S_OR(iks_name(traversenodes), ""), "session")) { 01552 traversenodes = iks_first_tag(traversenodes); 01553 continue; 01554 } 01555 if(!strcasecmp(S_OR(iks_name(traversenodes), ""), "ses:session")) { 01556 traversenodes = iks_child(traversenodes); 01557 continue; 01558 } 01559 if(!strcasecmp(S_OR(iks_name(traversenodes), ""), "candidate") || !strcasecmp(S_OR(iks_name(traversenodes), ""), "ses:candidate")) { 01560 newcandidate = ast_calloc(1, sizeof(*newcandidate)); 01561 if (!newcandidate) 01562 return 0; 01563 ast_copy_string(newcandidate->name, 01564 S_OR(iks_find_attrib(traversenodes, "name"), ""), 01565 sizeof(newcandidate->name)); 01566 ast_copy_string(newcandidate->ip, 01567 S_OR(iks_find_attrib(traversenodes, "address"), ""), 01568 sizeof(newcandidate->ip)); 01569 newcandidate->port = atoi(iks_find_attrib(traversenodes, "port")); 01570 ast_copy_string(newcandidate->username, 01571 S_OR(iks_find_attrib(traversenodes, "username"), ""), 01572 sizeof(newcandidate->username)); 01573 ast_copy_string(newcandidate->password, 01574 S_OR(iks_find_attrib(traversenodes, "password"), ""), 01575 sizeof(newcandidate->password)); 01576 newcandidate->preference = atof(iks_find_attrib(traversenodes, "preference")); 01577 if (!strcasecmp(S_OR(iks_find_attrib(traversenodes, "protocol"), ""), "udp")) 01578 newcandidate->protocol = AJI_PROTOCOL_UDP; 01579 if (!strcasecmp(S_OR(iks_find_attrib(traversenodes, "protocol"), ""), "ssltcp")) 01580 newcandidate->protocol = AJI_PROTOCOL_SSLTCP; 01581 01582 if (!strcasecmp(S_OR(iks_find_attrib(traversenodes, "type"), ""), "stun")) 01583 newcandidate->type = AJI_CONNECT_STUN; 01584 if (!strcasecmp(S_OR(iks_find_attrib(traversenodes, "type"), ""), "local")) 01585 newcandidate->type = AJI_CONNECT_LOCAL; 01586 if (!strcasecmp(S_OR(iks_find_attrib(traversenodes, "type"), ""), "relay")) 01587 newcandidate->type = AJI_CONNECT_RELAY; 01588 ast_copy_string(newcandidate->network, 01589 S_OR(iks_find_attrib(traversenodes, "network"), ""), 01590 sizeof(newcandidate->network)); 01591 newcandidate->generation = atoi(S_OR(iks_find_attrib(traversenodes, "generation"), "0")); 01592 newcandidate->next = NULL; 01593 01594 newcandidate->next = p->theircandidates; 01595 p->theircandidates = newcandidate; 01596 p->laststun = 0; 01597 gtalk_update_stun(p->parent, p); 01598 newcandidate = NULL; 01599 } 01600 traversenodes = iks_next_tag(traversenodes); 01601 } 01602 01603 receipt = iks_new("iq"); 01604 iks_insert_attrib(receipt, "type", "result"); 01605 iks_insert_attrib(receipt, "from", from); 01606 iks_insert_attrib(receipt, "to", S_OR(iks_find_attrib(pak->x, "from"), "")); 01607 iks_insert_attrib(receipt, "id", S_OR(iks_find_attrib(pak->x, "id"), "")); 01608 ast_aji_send(c, receipt); 01609 01610 iks_delete(receipt); 01611 01612 return 1; 01613 }
| static struct gtalk_pvt * gtalk_alloc | ( | struct gtalk * | client, | |
| const char * | us, | |||
| const char * | them, | |||
| const char * | sid | |||
| ) | [static, read] |
Definition at line 1002 of file chan_gtalk.c.
References ast_aji_buddy_destroy(), ast_calloc, ast_copy_string(), ast_debug, ast_format_cap_alloc_nolock(), ast_format_cap_copy(), ast_format_cap_destroy(), ast_format_cap_is_empty(), ast_free, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_rtp_codecs_payloads_clear(), AST_RTP_DTMF_MODE_RFC2833, ast_rtp_instance_dtmf_mode_set(), ast_rtp_instance_get_codecs(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_DTMF, AST_RTP_PROPERTY_RTCP, AST_RTP_PROPERTY_STUN, ast_sockaddr_from_sin, ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, aji_client::buddies, gtalk::buddy, gtalk::cap, gtalk_pvt::cap, aji_resource::cap, gtalk_pvt::cid_name, gtalk::connection, gtalk_pvt::exten, exten, gtalklock, gtalk_pvt::initiator, aji_version::jingle, gtalk_pvt::jointcap, gtalk_pvt::lock, LOG_ERROR, LOG_WARNING, gtalk::name, gtalk_pvt::next, aji_resource::next, gtalk::p, gtalk_pvt::parent, gtalk_pvt::peercap, 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().
01003 { 01004 struct gtalk_pvt *tmp = NULL; 01005 struct aji_resource *resources = NULL; 01006 struct aji_buddy *buddy = NULL; 01007 char idroster[200]; 01008 char *data, *exten = NULL; 01009 struct ast_sockaddr bindaddr_tmp; 01010 01011 ast_debug(1, "The client is %s for alloc\n", client->name); 01012 if (!sid && !strchr(them, '/')) { /* I started call! */ 01013 if (!strcasecmp(client->name, "guest")) { 01014 buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, them); 01015 if (buddy) { 01016 resources = buddy->resources; 01017 } 01018 } else if (client->buddy) { 01019 resources = client->buddy->resources; 01020 } 01021 01022 while (resources) { 01023 if (resources->cap->jingle) { 01024 break; 01025 } 01026 resources = resources->next; 01027 } 01028 if (resources) { 01029 snprintf(idroster, sizeof(idroster), "%s/%s", them, resources->resource); 01030 } else if ((*them == '+') || (strstr(them, "@voice.google.com"))) { 01031 snprintf(idroster, sizeof(idroster), "%s", them); 01032 } else { 01033 ast_log(LOG_ERROR, "no gtalk capable clients to talk to.\n"); 01034 if (buddy) { 01035 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 01036 } 01037 return NULL; 01038 } 01039 if (buddy) { 01040 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 01041 } 01042 } 01043 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 01044 return NULL; 01045 } 01046 tmp->cap = ast_format_cap_alloc_nolock(); 01047 tmp->jointcap = ast_format_cap_alloc_nolock(); 01048 tmp->peercap = ast_format_cap_alloc_nolock(); 01049 if (!tmp->jointcap || !tmp->peercap || !tmp->cap) { 01050 tmp->cap = ast_format_cap_destroy(tmp->cap); 01051 tmp->jointcap = ast_format_cap_destroy(tmp->jointcap); 01052 tmp->peercap = ast_format_cap_destroy(tmp->peercap); 01053 ast_free(tmp); 01054 return NULL; 01055 } 01056 01057 memcpy(&tmp->prefs, &client->prefs, sizeof(struct ast_codec_pref)); 01058 01059 if (sid) { 01060 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid)); 01061 ast_copy_string(tmp->them, them, sizeof(tmp->them)); 01062 ast_copy_string(tmp->us, us, sizeof(tmp->us)); 01063 } else { 01064 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random()); 01065 ast_copy_string(tmp->them, idroster, sizeof(tmp->them)); 01066 ast_copy_string(tmp->us, us, sizeof(tmp->us)); 01067 tmp->initiator = 1; 01068 } 01069 /* clear codecs */ 01070 bindaddr.sin_family = AF_INET; 01071 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 01072 if (!(tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL))) { 01073 ast_log(LOG_ERROR, "Failed to create a new RTP instance (possibly an invalid bindaddr?)\n"); 01074 ast_free(tmp); 01075 return NULL; 01076 } 01077 ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_RTCP, 1); 01078 ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_STUN, 1); 01079 ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_DTMF, 1); 01080 ast_rtp_instance_dtmf_mode_set(tmp->rtp, AST_RTP_DTMF_MODE_RFC2833); 01081 ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp); 01082 01083 /* add user configured codec capabilites */ 01084 if (!(ast_format_cap_is_empty(client->cap))) { 01085 ast_format_cap_copy(tmp->cap, client->cap); 01086 } else if (!(ast_format_cap_is_empty(global_capability))) { 01087 ast_format_cap_copy(tmp->cap, global_capability); 01088 } 01089 01090 tmp->parent = client; 01091 if (!tmp->rtp) { 01092 ast_log(LOG_WARNING, "Out of RTP sessions?\n"); 01093 ast_free(tmp); 01094 return NULL; 01095 } 01096 01097 /* Set CALLERID(name) to the full JID of the remote peer */ 01098 ast_copy_string(tmp->cid_name, tmp->them, sizeof(tmp->cid_name)); 01099 01100 if(strchr(tmp->us, '/')) { 01101 data = ast_strdupa(tmp->us); 01102 exten = strsep(&data, "/"); 01103 } else { 01104 exten = tmp->us; 01105 } 01106 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten)); 01107 ast_mutex_init(&tmp->lock); 01108 ast_mutex_lock(>alklock); 01109 tmp->next = client->p; 01110 client->p = tmp; 01111 ast_mutex_unlock(>alklock); 01112 return tmp; 01113 }
| static int gtalk_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 531 of file chan_gtalk.c.
References ast_channel_name(), ast_debug, ast_mutex_lock, ast_mutex_unlock, EVENT_FLAG_SYSTEM, gtalk_invite(), gtalk_pvt::lock, manager_event, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.
00532 { 00533 struct gtalk_pvt *p = ast->tech_pvt; 00534 int res = 0; 00535 00536 ast_debug(1, "Answer!\n"); 00537 ast_mutex_lock(&p->lock); 00538 gtalk_invite(p, p->them, p->us,p->sid, 0); 00539 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n", 00540 ast_channel_name(ast), "GTALK", p->sid); 00541 ast_mutex_unlock(&p->lock); 00542 return res; 00543 }
| static int gtalk_call | ( | struct ast_channel * | ast, | |
| const char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Initiate new call, part of PBX interface dest is the dial string.
Definition at line 1855 of file chan_gtalk.c.
References ast_channel::_state, ast_channel_name(), ast_copy_string(), ast_log(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RING, gtalk::connection, aji_client::f, gtalk_invite(), gtalk_ringing_ack(), LOG_WARNING, aji_client::mid, gtalk_pvt::parent, gtalk_pvt::ring, gtalk_pvt::ringrule, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.
01856 { 01857 struct gtalk_pvt *p = ast->tech_pvt; 01858 01859 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 01860 ast_log(LOG_WARNING, "gtalk_call called on %s, neither down nor reserved\n", ast_channel_name(ast)); 01861 return -1; 01862 } 01863 01864 ast_setstate(ast, AST_STATE_RING); 01865 if (!p->ringrule) { 01866 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring)); 01867 p->ringrule = iks_filter_add_rule(p->parent->connection->f, gtalk_ringing_ack, p, 01868 IKS_RULE_ID, p->ring, IKS_RULE_DONE); 01869 } else { 01870 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n"); 01871 } 01872 01873 gtalk_invite(p, p->them, p->us, p->sid, 1); 01874 01875 return 0; 01876 }
| static int gtalk_create_candidates | ( | struct gtalk * | client, | |
| struct gtalk_pvt * | p, | |||
| char * | sid, | |||
| char * | from, | |||
| char * | to | |||
| ) | [static] |
Definition at line 865 of file chan_gtalk.c.
References 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_free, ast_log(), ast_random(), ast_rtp_instance_get_local_address(), ast_sockaddr_stringify_addr(), ast_sockaddr_to_sin, ast_strdupa, ast_strlen_zero(), gtalk::connection, gtalk_candidate::generation, GOOGLE_NS, GOOGLE_TRANSPORT_NS, gtalk_get_local_ip(), gtalk_update_externip(), 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_newcall(), and gtalk_ringing_ack().
00866 { 00867 struct gtalk_candidate *tmp; 00868 struct aji_client *c = client->connection; 00869 struct gtalk_candidate *ours1 = NULL, *ours2 = NULL; 00870 struct sockaddr_in sin = { 0, }; 00871 struct ast_sockaddr sin_tmp; 00872 struct ast_sockaddr us; 00873 iks *iq, *gtalk, *candidate, *transport; 00874 char user[17], pass[17], preference[5], port[7]; 00875 char *lowerfrom = NULL; 00876 00877 iq = iks_new("iq"); 00878 gtalk = iks_new("session"); 00879 candidate = iks_new("candidate"); 00880 transport = iks_new("transport"); 00881 if (!iq || !gtalk || !candidate || !transport) { 00882 ast_log(LOG_ERROR, "Memory allocation error\n"); 00883 goto safeout; 00884 } 00885 ours1 = ast_calloc(1, sizeof(*ours1)); 00886 ours2 = ast_calloc(1, sizeof(*ours2)); 00887 if (!ours1 || !ours2) 00888 goto safeout; 00889 00890 iks_insert_attrib(transport, "xmlns",GOOGLE_TRANSPORT_NS); 00891 iks_insert_node(iq, gtalk); 00892 iks_insert_node(gtalk,candidate); 00893 iks_insert_node(gtalk,transport); 00894 00895 for (; p; p = p->next) { 00896 if (!strcasecmp(p->sid, sid)) 00897 break; 00898 } 00899 00900 if (!p) { 00901 ast_log(LOG_NOTICE, "No matching gtalk session - SID %s!\n", sid); 00902 goto safeout; 00903 } 00904 00905 ast_rtp_instance_get_local_address(p->rtp, &sin_tmp); 00906 ast_sockaddr_to_sin(&sin_tmp, &sin); 00907 00908 gtalk_get_local_ip(&us); 00909 00910 if (!strcmp(ast_sockaddr_stringify_addr(&us), "127.0.0.1")) { 00911 ast_log(LOG_WARNING, "Found a loopback IP on the system, check your network configuration or set the bindaddr attribute."); 00912 } 00913 00914 /* Setup our gtalk candidates */ 00915 ast_copy_string(ours1->name, "rtp", sizeof(ours1->name)); 00916 ours1->port = ntohs(sin.sin_port); 00917 ours1->preference = 1; 00918 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00919 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00920 ast_copy_string(ours1->username, user, sizeof(ours1->username)); 00921 ast_copy_string(ours1->password, pass, sizeof(ours1->password)); 00922 ast_copy_string(ours1->ip, ast_sockaddr_stringify_addr(&us), 00923 sizeof(ours1->ip)); 00924 ours1->protocol = AJI_PROTOCOL_UDP; 00925 ours1->type = AJI_CONNECT_LOCAL; 00926 ours1->generation = 0; 00927 p->ourcandidates = ours1; 00928 00929 /* XXX this is a blocking action. We send a STUN request to the server 00930 * and wait for the response. If blocking here is a problem the STUN requests/responses 00931 * for the externip may need to be done differently. */ 00932 gtalk_update_externip(); 00933 if (!ast_strlen_zero(externip)) { 00934 ast_copy_string(ours2->username, user, sizeof(ours2->username)); 00935 ast_copy_string(ours2->password, pass, sizeof(ours2->password)); 00936 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip)); 00937 ast_copy_string(ours2->name, "rtp", sizeof(ours1->name)); 00938 ours2->port = ntohs(sin.sin_port); 00939 ours2->preference = 0.9; 00940 ours2->protocol = AJI_PROTOCOL_UDP; 00941 ours2->type = AJI_CONNECT_STUN; 00942 ours2->generation = 0; 00943 ours1->next = ours2; 00944 ours2 = NULL; 00945 } 00946 ours1 = NULL; 00947 00948 for (tmp = p->ourcandidates; tmp; tmp = tmp->next) { 00949 snprintf(port, sizeof(port), "%d", tmp->port); 00950 snprintf(preference, sizeof(preference), "%.2f", tmp->preference); 00951 iks_insert_attrib(iq, "from", to); 00952 iks_insert_attrib(iq, "to", from); 00953 iks_insert_attrib(iq, "type", "set"); 00954 iks_insert_attrib(iq, "id", c->mid); 00955 ast_aji_increment_mid(c->mid); 00956 iks_insert_attrib(gtalk, "type", "candidates"); 00957 iks_insert_attrib(gtalk, "id", sid); 00958 /* put the initiator attribute to lower case if we receive the call 00959 * otherwise GoogleTalk won't establish the session */ 00960 if (!p->initiator) { 00961 char c; 00962 char *t = lowerfrom = ast_strdupa(from); 00963 while (((c = *t) != '/') && (*t++ = tolower(c))); 00964 } 00965 iks_insert_attrib(gtalk, "initiator", (p->initiator) ? to : lowerfrom); 00966 iks_insert_attrib(gtalk, "xmlns", GOOGLE_NS); 00967 iks_insert_attrib(candidate, "name", tmp->name); 00968 iks_insert_attrib(candidate, "address", tmp->ip); 00969 iks_insert_attrib(candidate, "port", port); 00970 iks_insert_attrib(candidate, "username", tmp->username); 00971 iks_insert_attrib(candidate, "password", tmp->password); 00972 iks_insert_attrib(candidate, "preference", preference); 00973 if (tmp->protocol == AJI_PROTOCOL_UDP) 00974 iks_insert_attrib(candidate, "protocol", "udp"); 00975 if (tmp->protocol == AJI_PROTOCOL_SSLTCP) 00976 iks_insert_attrib(candidate, "protocol", "ssltcp"); 00977 if (tmp->type == AJI_CONNECT_STUN) 00978 iks_insert_attrib(candidate, "type", "stun"); 00979 if (tmp->type == AJI_CONNECT_LOCAL) 00980 iks_insert_attrib(candidate, "type", "local"); 00981 if (tmp->type == AJI_CONNECT_RELAY) 00982 iks_insert_attrib(candidate, "type", "relay"); 00983 iks_insert_attrib(candidate, "network", "0"); 00984 iks_insert_attrib(candidate, "generation", "0"); 00985 ast_aji_send(c, iq); 00986 } 00987 p->laststun = 0; 00988 00989 safeout: 00990 if (ours1) 00991 ast_free(ours1); 00992 if (ours2) 00993 ast_free(ours2); 00994 iks_delete(iq); 00995 iks_delete(gtalk); 00996 iks_delete(candidate); 00997 iks_delete(transport); 00998 00999 return 1; 01000 }
| 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 2113 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::cap, gtalk::connection, gtalk::context, aji_client::f, GOOGLE_NS, gtalk_parser(), LOG_ERROR, LOG_WARNING, ast_variable::name, gtalk::name, ast_variable::next, gtalk::parkinglot, gtalk::prefs, gtalk::user, and ast_variable::value.
Referenced by gtalk_load_config().
02116 { 02117 struct aji_client *client; 02118 02119 if (!member) 02120 ast_log(LOG_WARNING, "Out of memory.\n"); 02121 02122 ast_copy_string(member->name, label, sizeof(member->name)); 02123 ast_copy_string(member->user, label, sizeof(member->user)); 02124 ast_copy_string(member->context, context, sizeof(member->context)); 02125 member->allowguest = allowguest; 02126 member->prefs = prefs; 02127 while (var) { 02128 if (!strcasecmp(var->name, "username")) 02129 ast_copy_string(member->user, var->value, sizeof(member->user)); 02130 else if (!strcasecmp(var->name, "disallow")) 02131 ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 0); 02132 else if (!strcasecmp(var->name, "allow")) 02133 ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 1); 02134 else if (!strcasecmp(var->name, "context")) 02135 ast_copy_string(member->context, var->value, sizeof(member->context)); 02136 else if (!strcasecmp(var->name, "parkinglot")) 02137 ast_copy_string(member->parkinglot, var->value, sizeof(member->parkinglot)); 02138 else if (!strcasecmp(var->name, "connection")) { 02139 if ((client = ast_aji_get_client(var->value))) { 02140 member->connection = client; 02141 iks_filter_add_rule(client->f, gtalk_parser, member, 02142 IKS_RULE_TYPE, IKS_PAK_IQ, 02143 IKS_RULE_FROM_PARTIAL, member->user, 02144 IKS_RULE_NS, GOOGLE_NS, 02145 IKS_RULE_DONE); 02146 } else { 02147 ast_log(LOG_ERROR, "connection referenced not found!\n"); 02148 return 0; 02149 } 02150 } 02151 var = var->next; 02152 } 02153 if (member->connection && member->user) 02154 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); 02155 else { 02156 ast_log(LOG_ERROR, "No Connection or Username!\n"); 02157 } 02158 return 1; 02159 }
| static int gtalk_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1755 of file chan_gtalk.c.
References ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_begin(), gtalk_pvt::lock, gtalk_pvt::rtp, and ast_channel::tech_pvt.
01756 { 01757 struct gtalk_pvt *p = chan->tech_pvt; 01758 int res = 0; 01759 01760 ast_mutex_lock(&p->lock); 01761 if (p->rtp) { 01762 ast_rtp_instance_dtmf_begin(p->rtp, digit); 01763 } else { 01764 res = -1; 01765 } 01766 ast_mutex_unlock(&p->lock); 01767 01768 return res; 01769 }
| static int gtalk_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1771 of file chan_gtalk.c.
References ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_end_with_duration(), gtalk_pvt::lock, gtalk_pvt::rtp, and ast_channel::tech_pvt.
01772 { 01773 struct gtalk_pvt *p = chan->tech_pvt; 01774 int res = 0; 01775 01776 ast_mutex_lock(&p->lock); 01777 if (p->rtp) { 01778 ast_rtp_instance_dtmf_end_with_duration(p->rtp, digit, duration); 01779 } else { 01780 res = -1; 01781 } 01782 ast_mutex_unlock(&p->lock); 01783 01784 return res; 01785 }
| static int gtalk_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 1702 of file chan_gtalk.c.
References ast_mutex_lock, ast_mutex_unlock, gtalk_pvt::lock, gtalk_pvt::owner, and ast_channel::tech_pvt.
01703 { 01704 struct gtalk_pvt *p = newchan->tech_pvt; 01705 ast_mutex_lock(&p->lock); 01706 01707 if ((p->owner != oldchan)) { 01708 ast_mutex_unlock(&p->lock); 01709 return -1; 01710 } 01711 if (p->owner == oldchan) 01712 p->owner = newchan; 01713 ast_mutex_unlock(&p->lock); 01714 return 0; 01715 }
| static void gtalk_free_candidates | ( | struct gtalk_candidate * | candidate | ) | [static] |
Definition at line 1255 of file chan_gtalk.c.
References ast_free, last, and gtalk_candidate::next.
Referenced by gtalk_free_pvt(), and gtalk_load_config().
01256 { 01257 struct gtalk_candidate *last; 01258 while (candidate) { 01259 last = candidate; 01260 candidate = candidate->next; 01261 ast_free(last); 01262 } 01263 }
Definition at line 1265 of file chan_gtalk.c.
References ast_format_cap_destroy(), ast_free, ast_log(), ast_rtp_instance_destroy(), gtalk_pvt::cap, gtalk::connection, aji_client::f, gtalk_free_candidates(), gtalk_pvt::jointcap, LOG_WARNING, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, gtalk_pvt::parent, gtalk_pvt::peercap, gtalk_pvt::ringrule, gtalk_pvt::rtp, gtalk_pvt::theircandidates, and gtalk_pvt::vrtp.
Referenced by gtalk_hangup(), and gtalk_newcall().
01266 { 01267 struct gtalk_pvt *cur, *prev = NULL; 01268 cur = client->p; 01269 while (cur) { 01270 if (cur == p) { 01271 if (prev) 01272 prev->next = p->next; 01273 else 01274 client->p = p->next; 01275 break; 01276 } 01277 prev = cur; 01278 cur = cur->next; 01279 } 01280 if (p->ringrule) 01281 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 01282 if (p->owner) 01283 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n"); 01284 if (p->rtp) 01285 ast_rtp_instance_destroy(p->rtp); 01286 if (p->vrtp) 01287 ast_rtp_instance_destroy(p->vrtp); 01288 gtalk_free_candidates(p->theircandidates); 01289 p->cap = ast_format_cap_destroy(p->cap); 01290 p->jointcap = ast_format_cap_destroy(p->jointcap); 01291 p->peercap = ast_format_cap_destroy(p->peercap); 01292 ast_free(p); 01293 }
| static void gtalk_get_codec | ( | struct ast_channel * | chan, | |
| struct ast_format_cap * | result | |||
| ) | [static] |
Definition at line 564 of file chan_gtalk.c.
References ast_format_cap_copy(), ast_mutex_lock, ast_mutex_unlock, gtalk_pvt::lock, gtalk_pvt::peercap, and ast_channel::tech_pvt.
00565 { 00566 struct gtalk_pvt *p = chan->tech_pvt; 00567 ast_mutex_lock(&p->lock); 00568 ast_format_cap_copy(result, p->peercap); 00569 ast_mutex_unlock(&p->lock); 00570 }
| static int gtalk_get_local_ip | ( | struct ast_sockaddr * | ourip | ) | [static] |
Definition at line 837 of file chan_gtalk.c.
References ast_find_ourip(), ast_free, ast_ouraddrfor(), ast_sockaddr_copy(), ast_sockaddr_from_sin, ast_sockaddr_is_any(), ast_sockaddr_resolve(), and PARSE_PORT_FORBID.
Referenced by gtalk_create_candidates(), and load_module().
00838 { 00839 struct ast_sockaddr root; 00840 struct ast_sockaddr bindaddr_tmp; 00841 struct ast_sockaddr *addrs; 00842 int addrs_cnt; 00843 00844 /* If bind address is not 0.0.0.0, then bindaddr is our local ip. */ 00845 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 00846 if (!ast_sockaddr_is_any(&bindaddr_tmp)) { 00847 ast_sockaddr_copy(ourip, &bindaddr_tmp); 00848 return 0; 00849 } 00850 00851 /* If no bind address was provided, lets see what ip we would use to connect to google.com and use that. 00852 * If you can't resolve google.com from your network, then this module is useless for you anyway. */ 00853 if ((addrs_cnt = ast_sockaddr_resolve(&addrs, "google.com", PARSE_PORT_FORBID, AF_INET)) > 0) { 00854 ast_sockaddr_copy(&root, &addrs[0]); 00855 ast_free(addrs); 00856 if (!ast_ouraddrfor(&root, ourip)) { 00857 return 0; 00858 } 00859 } 00860 00861 /* As a last resort, use this function to find our local address. */ 00862 return ast_find_ourip(ourip, &bindaddr_tmp, AF_INET); 00863 }
| static enum ast_rtp_glue_result gtalk_get_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp_instance ** | instance | |||
| ) | [static] |
Definition at line 545 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.
00546 { 00547 struct gtalk_pvt *p = chan->tech_pvt; 00548 enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID; 00549 00550 if (!p) 00551 return res; 00552 00553 ast_mutex_lock(&p->lock); 00554 if (p->rtp){ 00555 ao2_ref(p->rtp, +1); 00556 *instance = p->rtp; 00557 res = AST_RTP_GLUE_RESULT_LOCAL; 00558 } 00559 ast_mutex_unlock(&p->lock); 00560 00561 return res; 00562 }
| static int gtalk_handle_dtmf | ( | struct gtalk * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 738 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(), ast_frame_subclass::integer, aji_client::jid, LOG_NOTICE, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, gtalk_pvt::sid, and ast_frame::subclass.
Referenced by gtalk_parser().
00739 { 00740 struct gtalk_pvt *tmp; 00741 iks *dtmfnode = NULL, *dtmfchild = NULL; 00742 char *dtmf; 00743 char *from; 00744 /* Make sure our new call doesn't exist yet */ 00745 for (tmp = client->p; tmp; tmp = tmp->next) { 00746 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || iks_find_with_attrib(pak->x, "gtalk", "sid", tmp->sid)) 00747 break; 00748 } 00749 from = iks_find_attrib(pak->x, "to"); 00750 if (!from) { 00751 from = client->connection->jid->full; 00752 } 00753 00754 if (tmp) { 00755 if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) { 00756 gtalk_response(client, from, pak, 00757 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", 00758 "unsupported-dtmf-method xmlns='http://jabber.org/protocol/gtalk/info/dtmf#errors'"); 00759 return -1; 00760 } 00761 if ((dtmfnode = iks_find(pak->x, "dtmf"))) { 00762 if((dtmf = iks_find_attrib(dtmfnode, "code"))) { 00763 if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) { 00764 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00765 f.subclass.integer = dtmf[0]; 00766 ast_queue_frame(tmp->owner, &f); 00767 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", (int) f.subclass.integer); 00768 } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) { 00769 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00770 f.subclass.integer = dtmf[0]; 00771 ast_queue_frame(tmp->owner, &f); 00772 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", (int) f.subclass.integer); 00773 } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */ 00774 struct ast_frame f = {AST_FRAME_DTMF, }; 00775 f.subclass.integer = dtmf[0]; 00776 ast_queue_frame(tmp->owner, &f); 00777 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", (int) f.subclass.integer); 00778 } 00779 } 00780 } else if ((dtmfnode = iks_find_with_attrib(pak->x, "gtalk", "action", "session-info"))) { 00781 if((dtmfchild = iks_find(dtmfnode, "dtmf"))) { 00782 if((dtmf = iks_find_attrib(dtmfchild, "code"))) { 00783 if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) { 00784 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00785 f.subclass.integer = dtmf[0]; 00786 ast_queue_frame(tmp->owner, &f); 00787 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", (int) f.subclass.integer); 00788 } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) { 00789 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00790 f.subclass.integer = dtmf[0]; 00791 ast_queue_frame(tmp->owner, &f); 00792 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", (int) f.subclass.integer); 00793 } 00794 } 00795 } 00796 } 00797 gtalk_response(client, from, pak, NULL, NULL); 00798 return 1; 00799 } else { 00800 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00801 } 00802 00803 gtalk_response(client, from, pak, NULL, NULL); 00804 return 1; 00805 }
| static int gtalk_hangup | ( | struct ast_channel * | ast | ) | [static] |
Hangup a call through the gtalk proxy channel.
Definition at line 1879 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().
01880 { 01881 struct gtalk_pvt *p = ast->tech_pvt; 01882 struct gtalk *client; 01883 01884 ast_mutex_lock(&p->lock); 01885 client = p->parent; 01886 p->owner = NULL; 01887 ast->tech_pvt = NULL; 01888 if (!p->alreadygone) { 01889 gtalk_action(client, p, "terminate"); 01890 } 01891 ast_mutex_unlock(&p->lock); 01892 01893 gtalk_free_pvt(client, p); 01894 ast_module_unref(ast_module_info->self); 01895 01896 return 0; 01897 }
| static int gtalk_hangup_farend | ( | struct gtalk * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 807 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().
00808 { 00809 struct gtalk_pvt *tmp; 00810 char *from; 00811 00812 ast_debug(1, "The client is %s\n", client->name); 00813 /* Make sure our new call doesn't exist yet */ 00814 for (tmp = client->p; tmp; tmp = tmp->next) { 00815 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || 00816 (iks_find_attrib(pak->query, "id") && !strcmp(iks_find_attrib(pak->query, "id"), tmp->sid))) { 00817 break; 00818 } 00819 } 00820 from = iks_find_attrib(pak->x, "to"); 00821 if (!from) { 00822 from = client->connection->jid->full; 00823 } 00824 00825 if (tmp) { 00826 tmp->alreadygone = 1; 00827 if (tmp->owner) { 00828 ast_queue_hangup(tmp->owner); 00829 } 00830 } else { 00831 ast_log(LOG_NOTICE, "Whoa, didn't find call during hangup!\n"); 00832 } 00833 gtalk_response(client, from, pak, NULL, NULL); 00834 return 1; 00835 }
| static int gtalk_indicate | ( | struct ast_channel * | ast, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 1717 of file chan_gtalk.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, ast_moh_start(), and ast_moh_stop().
01718 { 01719 int res = 0; 01720 01721 switch (condition) { 01722 case AST_CONTROL_HOLD: 01723 ast_moh_start(ast, data, NULL); 01724 break; 01725 case AST_CONTROL_UNHOLD: 01726 ast_moh_stop(ast); 01727 break; 01728 default: 01729 ast_debug(3, "Don't know how to indicate condition '%d'\n", condition); 01730 res = -1; 01731 } 01732 01733 return res; 01734 }
| static int gtalk_invite | ( | struct gtalk_pvt * | p, | |
| char * | to, | |||
| char * | from, | |||
| char * | sid, | |||
| int | initiator | |||
| ) | [static] |
Definition at line 399 of file chan_gtalk.c.
References add_codec_to_answer(), ast_aji_increment_mid(), ast_aji_send(), ast_codec_pref_index(), AST_CODEC_PREF_SIZE, ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_iscompatible(), ast_log(), ast_strdupa, gtalk::cap, gtalk::connection, GOOGLE_AUDIO_NS, GOOGLE_NS, GOOGLE_TRANSPORT_NS, LOG_ERROR, aji_client::mid, gtalk_pvt::parent, and gtalk::prefs.
Referenced by gtalk_answer(), gtalk_call(), and gtalk_ringing_ack().
00400 { 00401 struct gtalk *client = p->parent; 00402 iks *iq, *gtalk, *dcodecs, *payload_telephone, *transport; 00403 int x; 00404 struct ast_format_cap *alreadysent; 00405 int codecs_num = 0; 00406 char *lowerto = NULL; 00407 struct ast_format tmpfmt; 00408 00409 iq = iks_new("iq"); 00410 gtalk = iks_new("session"); 00411 dcodecs = iks_new("description"); 00412 transport = iks_new("transport"); 00413 payload_telephone = iks_new("payload-type"); 00414 if (!(iq && gtalk && dcodecs && transport && payload_telephone)) { 00415 iks_delete(iq); 00416 iks_delete(gtalk); 00417 iks_delete(dcodecs); 00418 iks_delete(transport); 00419 iks_delete(payload_telephone); 00420 00421 ast_log(LOG_ERROR, "Could not allocate iksemel nodes\n"); 00422 return 0; 00423 } 00424 iks_insert_attrib(dcodecs, "xmlns", GOOGLE_AUDIO_NS); 00425 iks_insert_attrib(dcodecs, "xml:lang", "en"); 00426 00427 if (!(alreadysent = ast_format_cap_alloc_nolock())) { 00428 return 0; 00429 } 00430 for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { 00431 if (!(ast_codec_pref_index(&client->prefs, x, &tmpfmt))) { 00432 break; 00433 } 00434 if (!(ast_format_cap_iscompatible(client->cap, &tmpfmt))) { 00435 continue; 00436 } 00437 if (ast_format_cap_iscompatible(alreadysent, &tmpfmt)) { 00438 continue; 00439 } 00440 codecs_num = add_codec_to_answer(p, &tmpfmt, dcodecs); 00441 ast_format_cap_add(alreadysent, &tmpfmt); 00442 } 00443 alreadysent = ast_format_cap_destroy(alreadysent); 00444 00445 if (codecs_num) { 00446 /* only propose DTMF within an audio session */ 00447 iks_insert_attrib(payload_telephone, "id", "101"); 00448 iks_insert_attrib(payload_telephone, "name", "telephone-event"); 00449 iks_insert_attrib(payload_telephone, "clockrate", "8000"); 00450 } 00451 iks_insert_attrib(transport,"xmlns",GOOGLE_TRANSPORT_NS); 00452 00453 iks_insert_attrib(iq, "type", "set"); 00454 iks_insert_attrib(iq, "to", to); 00455 iks_insert_attrib(iq, "from", from); 00456 iks_insert_attrib(iq, "id", client->connection->mid); 00457 ast_aji_increment_mid(client->connection->mid); 00458 00459 iks_insert_attrib(gtalk, "xmlns", GOOGLE_NS); 00460 iks_insert_attrib(gtalk, "type",initiator ? "initiate": "accept"); 00461 /* put the initiator attribute to lower case if we receive the call 00462 * otherwise GoogleTalk won't establish the session */ 00463 if (!initiator) { 00464 char c; 00465 char *t = lowerto = ast_strdupa(to); 00466 while (((c = *t) != '/') && (*t++ = tolower(c))); 00467 } 00468 iks_insert_attrib(gtalk, "initiator", initiator ? from : lowerto); 00469 iks_insert_attrib(gtalk, "id", sid); 00470 iks_insert_node(iq, gtalk); 00471 iks_insert_node(gtalk, dcodecs); 00472 iks_insert_node(dcodecs, payload_telephone); 00473 00474 ast_aji_send(client->connection, iq); 00475 00476 iks_delete(payload_telephone); 00477 iks_delete(transport); 00478 iks_delete(dcodecs); 00479 iks_delete(gtalk); 00480 iks_delete(iq); 00481 return 1; 00482 }
| static int gtalk_is_accepted | ( | struct gtalk * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 709 of file chan_gtalk.c.
References ast_debug, ast_log(), gtalk::connection, gtalk_response(), gtalk_update_stun(), aji_client::jid, LOG_NOTICE, gtalk::name, gtalk_pvt::next, gtalk::p, gtalk_pvt::parent, and gtalk_pvt::sid.
Referenced by gtalk_parser().
00710 { 00711 struct gtalk_pvt *tmp; 00712 char *from; 00713 00714 ast_debug(1, "The client is %s\n", client->name); 00715 /* find corresponding call */ 00716 for (tmp = client->p; tmp; tmp = tmp->next) { 00717 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) { 00718 break; 00719 } 00720 } 00721 00722 from = iks_find_attrib(pak->x, "to"); 00723 if (!from) { 00724 from = client->connection->jid->full; 00725 } 00726 00727 if (tmp) { 00728 gtalk_update_stun(tmp->parent, tmp); 00729 } else { 00730 ast_log(LOG_NOTICE, "Whoa, didn't find call during accept?!\n"); 00731 } 00732 00733 /* answer 'iq' packet to let the remote peer know that we're alive */ 00734 gtalk_response(client, from, pak, NULL, NULL); 00735 return 1; 00736 }
| static int gtalk_is_answered | ( | struct gtalk * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 631 of file chan_gtalk.c.
References AST_CONTROL_ANSWER, ast_debug, ast_format_cap_is_empty(), ast_format_cap_joint_copy(), 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::cap, gtalk::connection, gtalk_response(), gtalk_update_stun(), aji_client::jid, gtalk_pvt::jointcap, LOG_WARNING, gtalk::name, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, gtalk_pvt::parent, gtalk_pvt::peercap, gtalk_pvt::rtp, and gtalk_pvt::sid.
Referenced by gtalk_parser().
00632 { 00633 struct gtalk_pvt *tmp = NULL; 00634 char *from; 00635 iks *codec; 00636 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ]; 00637 int peernoncodeccapability; 00638 00639 ast_debug(1, "The client is %s\n", client->name); 00640 00641 /* Make sure our new call does exist */ 00642 for (tmp = client->p; tmp; tmp = tmp->next) { 00643 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) { 00644 break; 00645 } else if (iks_find_with_attrib(pak->x, "ses:session", "id", tmp->sid)) { 00646 break; 00647 } 00648 } 00649 00650 if (!tmp) { 00651 ast_log(LOG_WARNING, "Could not find session in iq\n"); 00652 return -1; 00653 } 00654 00655 /* codec points to the first <payload-type/> tag */ 00656 codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x))); 00657 while (codec) { 00658 char *codec_id = iks_find_attrib(codec, "id"); 00659 char *codec_name = iks_find_attrib(codec, "name"); 00660 if (!codec_id || !codec_name) { 00661 codec = iks_next_tag(codec); 00662 continue; 00663 } 00664 00665 ast_rtp_codecs_payloads_set_m_type( 00666 ast_rtp_instance_get_codecs(tmp->rtp), 00667 tmp->rtp, 00668 atoi(codec_id)); 00669 ast_rtp_codecs_payloads_set_rtpmap_type( 00670 ast_rtp_instance_get_codecs(tmp->rtp), 00671 tmp->rtp, 00672 atoi(codec_id), 00673 "audio", 00674 codec_name, 00675 0); 00676 codec = iks_next_tag(codec); 00677 } 00678 00679 /* Now gather all of the codecs that we are asked for */ 00680 ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(tmp->rtp), tmp->peercap, &peernoncodeccapability); 00681 00682 /* at this point, we received an answer from the remote Gtalk client, 00683 which allows us to compare capabilities */ 00684 ast_format_cap_joint_copy(tmp->cap, tmp->peercap, tmp->jointcap); 00685 if (ast_format_cap_is_empty(tmp->jointcap)) { 00686 ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->cap), 00687 ast_getformatname_multiple(s2, BUFSIZ, tmp->peercap), 00688 ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcap)); 00689 /* close session if capabilities don't match */ 00690 ast_queue_hangup(tmp->owner); 00691 00692 return -1; 00693 00694 } 00695 00696 from = iks_find_attrib(pak->x, "to"); 00697 if (!from) { 00698 from = client->connection->jid->full; 00699 } 00700 00701 if (tmp->owner) { 00702 ast_queue_control(tmp->owner, AST_CONTROL_ANSWER); 00703 } 00704 gtalk_update_stun(tmp->parent, tmp); 00705 gtalk_response(client, from, pak, NULL, NULL); 00706 return 1; 00707 }
| static int gtalk_load_config | ( | void | ) | [static] |
Definition at line 2161 of file chan_gtalk.c.
References gtalk::allowguest, ast_aji_client_destroy(), ast_aji_get_clients(), ast_calloc, ast_category_browse(), ast_config_load, ast_copy_string(), ast_format_cap_alloc_nolock(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_parse_allow_disallow(), ast_parse_arg(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, gtalk::cap, clients, CONFIG_STATUS_FILEINVALID, gtalk::connection, gtalk::context, DEFAULT_PARKINGLOT, global_jbconf, GOOGLE_CONFIG, GOOGLE_JINGLE_NS, GOOGLE_NS, gtalk_create_member(), gtalk_free_candidates(), gtalk_list, gtalk_member_destroy(), gtalk_parser(), gtalk_update_externip(), hp, LOG_ERROR, LOG_WARNING, gtalk::name, ast_variable::name, ast_variable::next, gtalk::parkinglot, PARSE_INADDR, gtalk::prefs, STANDARD_STUN_PORT, stunaddr, gtalk::user, ast_variable::value, and var.
Referenced by load_module().
02162 { 02163 char *cat = NULL; 02164 struct ast_config *cfg = NULL; 02165 struct ast_variable *var; 02166 struct gtalk *member; 02167 struct ast_codec_pref prefs; 02168 struct aji_client_container *clients; 02169 struct gtalk_candidate *global_candidates = NULL; 02170 struct hostent *hp; 02171 struct ast_hostent ahp; 02172 struct ast_flags config_flags = { 0 }; 02173 02174 cfg = ast_config_load(GOOGLE_CONFIG, config_flags); 02175 if (!cfg) { 02176 return 0; 02177 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02178 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", GOOGLE_CONFIG); 02179 return 0; 02180 } 02181 02182 /* Copy the default jb config over global_jbconf */ 02183 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 02184 02185 /* set defaults */ 02186 memset(&prefs, 0, sizeof(prefs)); 02187 memset(&stunaddr, 0, sizeof(stunaddr)); 02188 global_stunaddr = 0; 02189 global_allowguest = DEFAULT_ALLOWGUEST; 02190 ast_copy_string(global_context, DEFAULT_CONTEXT, sizeof(global_context)); 02191 ast_copy_string(global_parkinglot, DEFAULT_PARKINGLOT, sizeof(global_parkinglot)); 02192 02193 cat = ast_category_browse(cfg, NULL); 02194 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 02195 /* handle jb conf */ 02196 if (!ast_jb_read_conf(&global_jbconf, var->name, var->value)) { 02197 continue; 02198 } 02199 02200 if (!strcasecmp(var->name, "allowguest")) { 02201 global_allowguest = (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0; 02202 } else if (!strcasecmp(var->name, "disallow")) { 02203 ast_parse_allow_disallow(&prefs, global_capability, var->value, 0); 02204 } else if (!strcasecmp(var->name, "allow")) { 02205 ast_parse_allow_disallow(&prefs, global_capability, var->value, 1); 02206 } else if (!strcasecmp(var->name, "context")) { 02207 ast_copy_string(global_context, var->value, sizeof(global_context)); 02208 } else if (!strcasecmp(var->name, "externip")) { 02209 ast_copy_string(externip, var->value, sizeof(externip)); 02210 } else if (!strcasecmp(var->name, "parkinglot")) { 02211 ast_copy_string(global_parkinglot, var->value, sizeof(global_parkinglot)); 02212 } else if (!strcasecmp(var->name, "bindaddr")) { 02213 if (!(hp = ast_gethostbyname(var->value, &ahp))) { 02214 ast_log(LOG_WARNING, "Invalid address: %s\n", var->value); 02215 } else { 02216 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 02217 } 02218 } else if (!strcasecmp(var->name, "stunaddr")) { 02219 stunaddr.sin_port = htons(STANDARD_STUN_PORT); 02220 global_stunaddr = 1; 02221 if (ast_parse_arg(var->value, PARSE_INADDR, &stunaddr)) { 02222 ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", var->value); 02223 } 02224 } 02225 } 02226 while (cat) { 02227 if (strcasecmp(cat, "general")) { 02228 var = ast_variable_browse(cfg, cat); 02229 member = ast_calloc(1, sizeof(*member)); 02230 ASTOBJ_INIT(member); 02231 ASTOBJ_WRLOCK(member); 02232 member->cap = ast_format_cap_alloc_nolock(); 02233 if (!strcasecmp(cat, "guest")) { 02234 ast_copy_string(member->name, "guest", sizeof(member->name)); 02235 ast_copy_string(member->user, "guest", sizeof(member->user)); 02236 ast_copy_string(member->context, global_context, sizeof(member->context)); 02237 ast_copy_string(member->parkinglot, global_parkinglot, sizeof(member->parkinglot)); 02238 member->allowguest = global_allowguest; 02239 member->prefs = prefs; 02240 while (var) { 02241 if (!strcasecmp(var->name, "disallow")) { 02242 ast_parse_allow_disallow(&member->prefs, member->cap, 02243 var->value, 0); 02244 } else if (!strcasecmp(var->name, "allow")) { 02245 ast_parse_allow_disallow(&member->prefs, member->cap, 02246 var->value, 1); 02247 } else if (!strcasecmp(var->name, "context")) { 02248 ast_copy_string(member->context, var->value, 02249 sizeof(member->context)); 02250 } else if (!strcasecmp(var->name, "parkinglot")) { 02251 ast_copy_string(member->parkinglot, var->value, 02252 sizeof(member->parkinglot)); 02253 } 02254 var = var->next; 02255 } 02256 ASTOBJ_UNLOCK(member); 02257 clients = ast_aji_get_clients(); 02258 if (clients) { 02259 ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { 02260 ASTOBJ_WRLOCK(iterator); 02261 ASTOBJ_WRLOCK(member); 02262 if (member->connection) { 02263 ASTOBJ_UNREF(member->connection, ast_aji_client_destroy); 02264 } 02265 member->connection = NULL; 02266 iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_NS, IKS_RULE_DONE); 02267 iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_JINGLE_NS, IKS_RULE_DONE); 02268 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); 02269 ASTOBJ_UNLOCK(member); 02270 ASTOBJ_UNLOCK(iterator); 02271 }); 02272 ASTOBJ_CONTAINER_LINK(>alk_list, member); 02273 ASTOBJ_UNREF(member, gtalk_member_destroy); 02274 } else { 02275 ASTOBJ_UNLOCK(member); 02276 ASTOBJ_UNREF(member, gtalk_member_destroy); 02277 } 02278 } else { 02279 ASTOBJ_UNLOCK(member); 02280 if (gtalk_create_member(cat, var, global_allowguest, prefs, global_context, member)) { 02281 ASTOBJ_CONTAINER_LINK(>alk_list, member); 02282 } 02283 ASTOBJ_UNREF(member, gtalk_member_destroy); 02284 } 02285 } 02286 cat = ast_category_browse(cfg, cat); 02287 } 02288 02289 gtalk_update_externip(); 02290 gtalk_free_candidates(global_candidates); 02291 return 1; 02292 }
| static void gtalk_member_destroy | ( | struct gtalk * | obj | ) | [static] |
Definition at line 248 of file chan_gtalk.c.
References ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_format_cap_destroy(), ast_free, ASTOBJ_UNREF, gtalk::buddy, gtalk::cap, and gtalk::connection.
Referenced by gtalk_load_config(), gtalk_parser(), gtalk_request(), and unload_module().
00249 { 00250 obj->cap = ast_format_cap_destroy(obj->cap); 00251 if (obj->connection) { 00252 ASTOBJ_UNREF(obj->connection, ast_aji_client_destroy); 00253 } 00254 if (obj->buddy) { 00255 ASTOBJ_UNREF(obj->buddy, ast_aji_buddy_destroy); 00256 } 00257 ast_free(obj); 00258 }
| 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 1116 of file chan_gtalk.c.
References 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_name(), ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), ast_format_cap_add(), ast_format_cap_is_empty(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_format_copy(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_VIDEO, 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_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_channel::caller, gtalk::callgroup, ast_channel::callgroup, gtalk::callingpres, gtalk_pvt::cap, gtalk_pvt::cid_name, gtalk_pvt::cid_num, ast_channel::context, gtalk::context, ast_channel::dialed, EVENT_FLAG_SYSTEM, ast_channel::exten, gtalk_pvt::exten, global_jbconf, ast_channel::hangupcause, ast_party_caller::id, ast_format::id, gtalk_pvt::jointcap, gtalk::language, LOG_WARNING, manager_event, gtalk::musicclass, ast_party_id::name, ast_channel::nativeformats, ast_party_dialed::number, ast_party_id::number, gtalk_pvt::owner, gtalk::parkinglot, gtalk::pickupgroup, ast_channel::pickupgroup, gtalk_pvt::prefs, ast_party_number::presentation, ast_party_name::presentation, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, gtalk_pvt::rtp, gtalk_pvt::sid, ast_party_dialed::str, ast_channel::tech, ast_channel::tech_pvt, gtalk_pvt::us, gtalk_pvt::vrtp, and ast_channel::writeformat.
Referenced by gtalk_newcall(), and gtalk_request().
01117 { 01118 struct ast_channel *tmp; 01119 const char *n2; 01120 struct ast_format_cap *what; /* used as SHALLOW COPY DO NOT DESTROY */ 01121 struct ast_format tmpfmt; 01122 01123 if (title) 01124 n2 = title; 01125 else 01126 n2 = i->us; 01127 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); 01128 if (!tmp) { 01129 ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n"); 01130 return NULL; 01131 } 01132 tmp->tech = >alk_tech; 01133 01134 /* Select our native format based on codec preference until we receive 01135 something from another device to the contrary. */ 01136 if (!(ast_format_cap_is_empty(i->jointcap))) { 01137 what = i->jointcap; 01138 } else if (i->cap) { 01139 what = i->cap; 01140 } else { 01141 what = global_capability; 01142 } 01143 01144 /* Set Frame packetization */ 01145 if (i->rtp) { 01146 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs); 01147 } 01148 01149 ast_codec_choose(&i->prefs, what, 1, &tmpfmt); 01150 ast_format_cap_add(tmp->nativeformats, &tmpfmt); 01151 01152 ast_format_cap_iter_start(i->jointcap); 01153 while (!(ast_format_cap_iter_next(i->jointcap, &tmpfmt))) { 01154 if (AST_FORMAT_GET_TYPE(tmpfmt.id) == AST_FORMAT_TYPE_VIDEO) { 01155 ast_format_cap_add(tmp->nativeformats, &tmpfmt); 01156 } 01157 } 01158 ast_format_cap_iter_end(i->jointcap); 01159 01160 if (i->rtp) { 01161 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0)); 01162 ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1)); 01163 } 01164 if (i->vrtp) { 01165 ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0)); 01166 ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1)); 01167 } 01168 if (state == AST_STATE_RING) 01169 tmp->rings = 1; 01170 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 01171 01172 ast_best_codec(tmp->nativeformats, &tmpfmt); 01173 ast_format_copy(&tmp->writeformat, &tmpfmt); 01174 ast_format_copy(&tmp->rawwriteformat, &tmpfmt); 01175 ast_format_copy(&tmp->readformat, &tmpfmt); 01176 ast_format_copy(&tmp->rawreadformat, &tmpfmt); 01177 tmp->tech_pvt = i; 01178 01179 tmp->callgroup = client->callgroup; 01180 tmp->pickupgroup = client->pickupgroup; 01181 tmp->caller.id.name.presentation = client->callingpres; 01182 tmp->caller.id.number.presentation = client->callingpres; 01183 if (!ast_strlen_zero(client->accountcode)) 01184 ast_channel_accountcode_set(tmp, client->accountcode); 01185 if (client->amaflags) 01186 tmp->amaflags = client->amaflags; 01187 if (!ast_strlen_zero(client->language)) 01188 ast_channel_language_set(tmp, client->language); 01189 if (!ast_strlen_zero(client->musicclass)) 01190 ast_channel_musicclass_set(tmp, client->musicclass); 01191 if (!ast_strlen_zero(client->parkinglot)) 01192 ast_channel_parkinglot_set(tmp, client->parkinglot); 01193 i->owner = tmp; 01194 ast_module_ref(ast_module_info->self); 01195 ast_copy_string(tmp->context, client->context, sizeof(tmp->context)); 01196 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 01197 01198 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) { 01199 tmp->dialed.number.str = ast_strdup(i->exten); 01200 } 01201 tmp->priority = 1; 01202 if (i->rtp) 01203 ast_jb_configure(tmp, &global_jbconf); 01204 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 01205 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); 01206 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 01207 ast_hangup(tmp); 01208 tmp = NULL; 01209 } else { 01210 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 01211 "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n", 01212 i->owner ? ast_channel_name(i->owner) : "", "Gtalk", i->sid); 01213 } 01214 return tmp; 01215 }
| static int gtalk_newcall | ( | struct gtalk * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1296 of file chan_gtalk.c.
References gtalk_pvt::alreadygone, ast_aji_client_destroy(), ast_aji_get_client(), ast_channel_release(), ast_copy_string(), ast_format_cap_is_empty(), ast_format_cap_joint_copy(), 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, ASTOBJ_UNREF, gtalk_pvt::cap, gtalk::connection, gtalk_action(), gtalk_alloc(), gtalk_create_candidates(), gtalk_free_pvt(), gtalk_hangup(), gtalk_new(), gtalk_response(), aji_client::jid, gtalk_pvt::jointcap, gtalk_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, gtalk::name, gtalk_pvt::next, gtalk::p, gtalk_pvt::peercap, gtalk_pvt::rtp, S_OR, gtalk_pvt::sid, gtalk_pvt::them, gtalk_pvt::us, and gtalk_pvt::vrtp.
Referenced by gtalk_parser().
01297 { 01298 struct gtalk_pvt *p, *tmp = client->p; 01299 struct ast_channel *chan; 01300 int res; 01301 iks *codec; 01302 char *from = NULL; 01303 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ]; 01304 int peernoncodeccapability; 01305 char *sid; 01306 01307 /* Make sure our new call doesn't exist yet */ 01308 from = iks_find_attrib(pak->x,"to"); 01309 if (!from) { 01310 from = client->connection->jid->full; 01311 } 01312 01313 while (tmp) { 01314 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || 01315 (iks_find_attrib(pak->query, "id") && !strcmp(iks_find_attrib(pak->query, "id"), tmp->sid))) { 01316 ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid); 01317 gtalk_response(client, from, pak, "out-of-order", NULL); 01318 return -1; 01319 } 01320 tmp = tmp->next; 01321 } 01322 01323 if (!strcasecmp(client->name, "guest")){ 01324 /* the guest account is not tied to any configured XMPP client, 01325 let's set it now */ 01326 if (client->connection) { 01327 ASTOBJ_UNREF(client->connection, ast_aji_client_destroy); 01328 } 01329 client->connection = ast_aji_get_client(from); 01330 if (!client->connection) { 01331 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); 01332 return -1; 01333 } 01334 } 01335 01336 if (!(sid = iks_find_attrib(pak->query, "id"))) { 01337 ast_log(LOG_WARNING, "Received Initiate without id attribute. Can not start call.\n"); 01338 return -1; 01339 } 01340 01341 p = gtalk_alloc(client, from, pak->from->full, sid); 01342 if (!p) { 01343 ast_log(LOG_WARNING, "Unable to allocate gtalk structure!\n"); 01344 return -1; 01345 } 01346 01347 chan = gtalk_new(client, p, AST_STATE_DOWN, pak->from->user, NULL); 01348 if (!chan) { 01349 gtalk_free_pvt(client, p); 01350 return -1; 01351 } 01352 01353 ast_mutex_lock(&p->lock); 01354 ast_copy_string(p->them, pak->from->full, sizeof(p->them)); 01355 ast_copy_string(p->sid, sid, sizeof(p->sid)); 01356 01357 /* codec points to the first <payload-type/> tag */ 01358 codec = iks_first_tag(iks_first_tag(pak->query)); 01359 01360 while (codec) { 01361 char *codec_id = iks_find_attrib(codec, "id"); 01362 char *codec_name = iks_find_attrib(codec, "name"); 01363 if (!codec_id || !codec_name) { 01364 codec = iks_next_tag(codec); 01365 continue; 01366 } 01367 if (!strcmp(S_OR(iks_name(codec), ""), "vid:payload-type") && p->vrtp) { 01368 ast_rtp_codecs_payloads_set_m_type( 01369 ast_rtp_instance_get_codecs(p->vrtp), 01370 p->vrtp, 01371 atoi(codec_id)); 01372 ast_rtp_codecs_payloads_set_rtpmap_type( 01373 ast_rtp_instance_get_codecs(p->vrtp), 01374 p->vrtp, 01375 atoi(codec_id), 01376 "video", 01377 codec_name, 01378 0); 01379 } else { 01380 ast_rtp_codecs_payloads_set_m_type( 01381 ast_rtp_instance_get_codecs(p->rtp), 01382 p->rtp, 01383 atoi(codec_id)); 01384 ast_rtp_codecs_payloads_set_rtpmap_type( 01385 ast_rtp_instance_get_codecs(p->rtp), 01386 p->rtp, 01387 atoi(codec_id), 01388 "audio", 01389 codec_name, 01390 0); 01391 } 01392 codec = iks_next_tag(codec); 01393 } 01394 01395 /* Now gather all of the codecs that we are asked for */ 01396 ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(p->rtp), p->peercap, &peernoncodeccapability); 01397 ast_format_cap_joint_copy(p->cap, p->peercap, p->jointcap); 01398 ast_mutex_unlock(&p->lock); 01399 01400 ast_setstate(chan, AST_STATE_RING); 01401 if (ast_format_cap_is_empty(p->jointcap)) { 01402 ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->cap), 01403 ast_getformatname_multiple(s2, BUFSIZ, p->peercap), 01404 ast_getformatname_multiple(s3, BUFSIZ, p->jointcap)); 01405 /* close session if capabilities don't match */ 01406 gtalk_action(client, p, "reject"); 01407 p->alreadygone = 1; 01408 gtalk_hangup(chan); 01409 ast_channel_release(chan); 01410 return -1; 01411 } 01412 01413 res = ast_pbx_start(chan); 01414 01415 switch (res) { 01416 case AST_PBX_FAILED: 01417 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 01418 gtalk_response(client, from, pak, "service-unavailable", NULL); 01419 break; 01420 case AST_PBX_CALL_LIMIT: 01421 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 01422 gtalk_response(client, from, pak, "service-unavailable", NULL); 01423 break; 01424 case AST_PBX_SUCCESS: 01425 gtalk_response(client, from, pak, NULL, NULL); 01426 gtalk_create_candidates(client, p, p->sid, p->them, p->us); 01427 /* nothing to do */ 01428 break; 01429 } 01430 01431 return 1; 01432 }
| static int gtalk_parser | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
CLI command "gtalk reload".
Definition at line 2070 of file chan_gtalk.c.
References ast_debug, ast_log(), ast_strlen_zero(), ASTOBJ_REF, ASTOBJ_UNREF, gtalk_add_candidate(), gtalk_handle_dtmf(), gtalk_hangup_farend(), gtalk_is_accepted(), gtalk_is_answered(), gtalk_member_destroy(), gtalk_newcall(), LOG_NOTICE, LOG_WARNING, and S_OR.
Referenced by gtalk_create_member(), and gtalk_load_config().
02071 { 02072 struct gtalk *client = ASTOBJ_REF((struct gtalk *) data); 02073 int res; 02074 iks *tmp; 02075 02076 if (!strcasecmp(iks_name(pak->query), "jin:jingle") && (tmp = iks_next(pak->query)) && !strcasecmp(iks_name(tmp), "ses:session")) { 02077 ast_debug(1, "New method detected. Skipping jingle offer and using old gtalk method.\n"); 02078 pak->query = tmp; 02079 } 02080 02081 if (!strcmp(S_OR(iks_find_attrib(pak->x, "type"), ""), "error")) { 02082 ast_log(LOG_NOTICE, "Remote peer reported an error, trying to establish the call anyway\n"); 02083 } 02084 02085 if (ast_strlen_zero(iks_find_attrib(pak->query, "type"))) { 02086 ast_log(LOG_NOTICE, "No attribute \"type\" found. Ignoring message.\n"); 02087 } else if (!strcmp(iks_find_attrib(pak->query, "type"), "initiate")) { 02088 /* New call */ 02089 gtalk_newcall(client, pak); 02090 } else if (!strcmp(iks_find_attrib(pak->query, "type"), "candidates") || !strcmp(iks_find_attrib(pak->query, "type"), "transport-info")) { 02091 ast_debug(3, "About to add candidate!\n"); 02092 res = gtalk_add_candidate(client, pak); 02093 if (!res) { 02094 ast_log(LOG_WARNING, "Could not add any candidate\n"); 02095 } else { 02096 ast_debug(3, "Candidate Added!\n"); 02097 } 02098 } else if (!strcmp(iks_find_attrib(pak->query, "type"), "accept")) { 02099 gtalk_is_answered(client, pak); 02100 } else if (!strcmp(iks_find_attrib(pak->query, "type"), "transport-accept")) { 02101 gtalk_is_accepted(client, pak); 02102 } else if (!strcmp(iks_find_attrib(pak->query, "type"), "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) { 02103 gtalk_handle_dtmf(client, pak); 02104 } else if (!strcmp(iks_find_attrib(pak->query, "type"), "terminate")) { 02105 gtalk_hangup_farend(client, pak); 02106 } else if (!strcmp(iks_find_attrib(pak->query, "type"), "reject")) { 02107 gtalk_hangup_farend(client, pak); 02108 } 02109 ASTOBJ_UNREF(client, gtalk_member_destroy); 02110 return IKS_FILTER_EAT; 02111 }
| static struct ast_frame * gtalk_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 1644 of file chan_gtalk.c.
References ast_mutex_lock, ast_mutex_unlock, gtalk_rtp_read(), gtalk_pvt::lock, and ast_channel::tech_pvt.
01645 { 01646 struct ast_frame *fr; 01647 struct gtalk_pvt *p = ast->tech_pvt; 01648 01649 ast_mutex_lock(&p->lock); 01650 fr = gtalk_rtp_read(ast, p); 01651 ast_mutex_unlock(&p->lock); 01652 return fr; 01653 }
| static struct ast_channel * gtalk_request | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const struct ast_channel * | requestor, | |||
| const char * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Part of PBX interface.
Definition at line 1900 of file chan_gtalk.c.
References ast_aji_client_destroy(), ast_aji_get_client(), ast_channel_linkedid(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, gtalk::connection, find_gtalk(), gtalk_alloc(), gtalk_member_destroy(), gtalk_new(), aji_client::jid, LOG_ERROR, LOG_WARNING, gtalk::name, strsep(), and gtalk::user.
01901 { 01902 struct gtalk_pvt *p = NULL; 01903 struct gtalk *client = NULL; 01904 char *sender = NULL, *to = NULL, *s = NULL; 01905 struct ast_channel *chan = NULL; 01906 01907 if (data) { 01908 s = ast_strdupa(data); 01909 if (s) { 01910 sender = strsep(&s, "/"); 01911 if (sender && (sender[0] != '\0')) { 01912 to = strsep(&s, "/"); 01913 } 01914 if (!to) { 01915 ast_log(LOG_ERROR, "Bad arguments in Gtalk Dialstring: %s\n", data); 01916 return NULL; 01917 } 01918 } 01919 } 01920 01921 client = find_gtalk(to, sender); 01922 if (!client) { 01923 ast_log(LOG_WARNING, "Could not find recipient.\n"); 01924 return NULL; 01925 } 01926 if (!strcasecmp(client->name, "guest")){ 01927 /* the guest account is not tied to any configured XMPP client, 01928 let's set it now */ 01929 if (client->connection) { 01930 ASTOBJ_UNREF(client->connection, ast_aji_client_destroy); 01931 } 01932 client->connection = ast_aji_get_client(sender); 01933 if (!client->connection) { 01934 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender); 01935 ASTOBJ_UNREF(client, gtalk_member_destroy); 01936 return NULL; 01937 } 01938 } 01939 01940 ASTOBJ_WRLOCK(client); 01941 p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL); 01942 if (p) { 01943 chan = gtalk_new(client, p, AST_STATE_DOWN, to, requestor ? ast_channel_linkedid(requestor) : NULL); 01944 } 01945 ASTOBJ_UNLOCK(client); 01946 return chan; 01947 }
| static int gtalk_response | ( | struct gtalk * | client, | |
| char * | from, | |||
| ikspak * | pak, | |||
| const char * | reasonstr, | |||
| const char * | reasonstr2 | |||
| ) | [static] |
Definition at line 599 of file chan_gtalk.c.
References ast_aji_send(), gtalk::connection, and S_OR.
Referenced by gtalk_handle_dtmf(), gtalk_hangup_farend(), gtalk_is_accepted(), gtalk_is_answered(), and gtalk_newcall().
00600 { 00601 iks *response = NULL, *error = NULL, *reason = NULL; 00602 int res = -1; 00603 00604 response = iks_new("iq"); 00605 if (response) { 00606 iks_insert_attrib(response, "type", "result"); 00607 iks_insert_attrib(response, "from", from); 00608 iks_insert_attrib(response, "to", S_OR(iks_find_attrib(pak->x, "from"), "")); 00609 iks_insert_attrib(response, "id", S_OR(iks_find_attrib(pak->x, "id"), "")); 00610 if (reasonstr) { 00611 error = iks_new("error"); 00612 if (error) { 00613 iks_insert_attrib(error, "type", "cancel"); 00614 reason = iks_new(reasonstr); 00615 if (reason) 00616 iks_insert_node(error, reason); 00617 iks_insert_node(response, error); 00618 } 00619 } 00620 ast_aji_send(client->connection, response); 00621 res = 0; 00622 } 00623 00624 iks_delete(reason); 00625 iks_delete(error); 00626 iks_delete(response); 00627 00628 return res; 00629 }
| static int gtalk_ringing_ack | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 484 of file chan_gtalk.c.
References AST_CONTROL_RINGING, ast_copy_string(), ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_queue_control(), gtalk::connection, aji_client::f, gtalk_create_candidates(), gtalk_invite(), gtalk_pvt::lock, name, gtalk_pvt::owner, gtalk_pvt::parent, gtalk_pvt::ringrule, S_OR, gtalk_pvt::sid, gtalk_pvt::them, and gtalk_pvt::us.
Referenced by gtalk_call().
00485 { 00486 struct gtalk_pvt *p = data; 00487 struct ast_channel *owner; 00488 00489 ast_mutex_lock(&p->lock); 00490 00491 if (p->ringrule) { 00492 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 00493 } 00494 p->ringrule = NULL; 00495 00496 /* this may be a redirect */ 00497 if (!strcmp(S_OR(iks_find_attrib(pak->x, "type"), ""), "error")) { 00498 char *name = NULL; 00499 char *redirect = NULL; 00500 iks *traversenodes = NULL; 00501 traversenodes = pak->query; 00502 while (traversenodes) { 00503 if (!(name = iks_name(traversenodes))) { 00504 break; 00505 } 00506 if (!strcasecmp(name, "error") && 00507 ((redirect = iks_find_cdata(traversenodes, "redirect")) || 00508 (redirect = iks_find_cdata(traversenodes, "sta:redirect"))) && 00509 (redirect = strstr(redirect, "xmpp:"))) { 00510 redirect += 5; 00511 ast_debug(1, "redirect %s\n", redirect); 00512 ast_copy_string(p->them, redirect, sizeof(p->them)); 00513 00514 gtalk_invite(p, p->them, p->us, p->sid, 1); 00515 break; 00516 } 00517 traversenodes = iks_next_tag(traversenodes); 00518 } 00519 } 00520 gtalk_create_candidates(p->parent, p, p->sid, p->them, p->us); 00521 owner = p->owner; 00522 ast_mutex_unlock(&p->lock); 00523 00524 if (owner) { 00525 ast_queue_control(owner, AST_CONTROL_RINGING); 00526 } 00527 00528 return IKS_FILTER_EAT; 00529 }
| static struct ast_frame* gtalk_rtp_read | ( | struct ast_channel * | ast, | |
| struct gtalk_pvt * | p | |||
| ) | [static, read] |
Definition at line 1615 of file chan_gtalk.c.
References ast_debug, ast_format_cap_add(), ast_format_cap_iscompatible(), ast_format_cap_remove_bytype(), AST_FORMAT_TYPE_AUDIO, AST_FRAME_VOICE, ast_getformatname(), ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), f, ast_frame_subclass::format, 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().
01616 { 01617 struct ast_frame *f; 01618 01619 if (!p->rtp) { 01620 return &ast_null_frame; 01621 } 01622 f = ast_rtp_instance_read(p->rtp, 0); 01623 gtalk_update_stun(p->parent, p); 01624 if (p->owner) { 01625 /* We already hold the channel lock */ 01626 if (f->frametype == AST_FRAME_VOICE) { 01627 if (!ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format)) { 01628 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); 01629 ast_format_cap_remove_bytype(p->owner->nativeformats, AST_FORMAT_TYPE_AUDIO); 01630 ast_format_cap_add(p->owner->nativeformats, &f->subclass.format); 01631 ast_set_read_format(p->owner, &p->owner->readformat); 01632 ast_set_write_format(p->owner, &p->owner->writeformat); 01633 } 01634 /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { 01635 f = ast_dsp_process(p->owner, p->vad, f); 01636 if (option_debug && f && (f->frametype == AST_FRAME_DTMF)) 01637 ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass); 01638 } */ 01639 } 01640 } 01641 return f; 01642 }
| static int gtalk_sendhtml | ( | struct ast_channel * | ast, | |
| int | subclass, | |||
| const char * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 1846 of file chan_gtalk.c.
References ast_log(), and LOG_NOTICE.
01847 { 01848 ast_log(LOG_NOTICE, "XXX Implement gtalk sendhtml XXX\n"); 01849 01850 return -1; 01851 }
| static int gtalk_sendtext | ( | struct ast_channel * | ast, | |
| const char * | text | |||
| ) | [static] |
Definition at line 1736 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.
01737 { 01738 int res = 0; 01739 struct aji_client *client = NULL; 01740 struct gtalk_pvt *p = chan->tech_pvt; 01741 01742 if (!p->parent) { 01743 ast_log(LOG_ERROR, "Parent channel not found\n"); 01744 return -1; 01745 } 01746 if (!p->parent->connection) { 01747 ast_log(LOG_ERROR, "XMPP client not found\n"); 01748 return -1; 01749 } 01750 client = p->parent->connection; 01751 res = ast_aji_send_chat(client, p->them, text); 01752 return res; 01753 }
| 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, | |||
| const struct ast_format_cap * | cap, | |||
| int | nat_active | |||
| ) | [static] |
Definition at line 572 of file chan_gtalk.c.
References ast_mutex_lock, ast_mutex_unlock, gtalk_pvt::lock, and ast_channel::tech_pvt.
00573 { 00574 struct gtalk_pvt *p; 00575 00576 p = chan->tech_pvt; 00577 if (!p) 00578 return -1; 00579 ast_mutex_lock(&p->lock); 00580 00581 /* if (rtp) 00582 ast_rtp_get_peer(rtp, &p->redirip); 00583 else 00584 memset(&p->redirip, 0, sizeof(p->redirip)); 00585 p->redircodecs = codecs; */ 00586 00587 /* Reset lastrtprx timer */ 00588 ast_mutex_unlock(&p->lock); 00589 return 0; 00590 }
| 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 1950 of file chan_gtalk.c.
References AJI_MAX_JIDLEN, ast_cli_args::argc, ast_channel_name(), ast_cli(), ast_copy_string(), ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, gtalk_list, gtalklock, LOG_WARNING, gtalk_pvt::next, gtalk_pvt::owner, ast_channel::readformat, gtalk_pvt::them, ast_cli_entry::usage, and ast_channel::writeformat.
01951 { 01952 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" 01953 struct gtalk_pvt *p; 01954 struct ast_channel *chan; 01955 int numchans = 0; 01956 char them[AJI_MAX_JIDLEN]; 01957 char *jid = NULL; 01958 char *resource = NULL; 01959 01960 switch (cmd) { 01961 case CLI_INIT: 01962 e->command = "gtalk show channels"; 01963 e->usage = 01964 "Usage: gtalk show channels\n" 01965 " Shows current state of the Gtalk channels.\n"; 01966 return NULL; 01967 case CLI_GENERATE: 01968 return NULL; 01969 } 01970 01971 if (a->argc != 3) 01972 return CLI_SHOWUSAGE; 01973 01974 ast_mutex_lock(>alklock); 01975 ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); 01976 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { 01977 ASTOBJ_WRLOCK(iterator); 01978 p = iterator->p; 01979 while(p) { 01980 chan = p->owner; 01981 ast_copy_string(them, p->them, sizeof(them)); 01982 jid = them; 01983 resource = strchr(them, '/'); 01984 if (!resource) 01985 resource = "None"; 01986 else { 01987 *resource = '\0'; 01988 resource ++; 01989 } 01990 if (chan) 01991 ast_cli(a->fd, FORMAT, 01992 ast_channel_name(chan), 01993 jid, 01994 resource, 01995 ast_getformatname(&chan->readformat), 01996 ast_getformatname(&chan->writeformat) 01997 ); 01998 else 01999 ast_log(LOG_WARNING, "No available channel\n"); 02000 numchans ++; 02001 p = p->next; 02002 } 02003 ASTOBJ_UNLOCK(iterator); 02004 }); 02005 02006 ast_mutex_unlock(>alklock); 02007 02008 ast_cli(a->fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : ""); 02009 return CLI_SUCCESS; 02010 #undef FORMAT 02011 }
| static char * gtalk_show_settings | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
List global settings for the GoogleTalk channel.
Definition at line 2014 of file chan_gtalk.c.
References ast_cli_args::argc, ast_cli(), AST_CLI_YESNO, ast_getformatname_multiple(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, S_OR, stunaddr, and ast_cli_entry::usage.
02015 { 02016 char codec_buf[BUFSIZ]; 02017 switch (cmd) { 02018 case CLI_INIT: 02019 e->command = "gtalk show settings"; 02020 e->usage = 02021 "Usage: gtalk show settings\n" 02022 " Provides detailed list of the configuration on the GoogleTalk channel.\n"; 02023 return NULL; 02024 case CLI_GENERATE: 02025 return NULL; 02026 } 02027 02028 if (a->argc != 3) { 02029 return CLI_SHOWUSAGE; 02030 } 02031 02032 #define FORMAT " %-25.20s %-15.30s\n" 02033 02034 ast_cli(a->fd, "\nGlobal Settings:\n"); 02035 ast_cli(a->fd, "----------------\n"); 02036 ast_cli(a->fd, FORMAT, "UDP Bindaddress:", ast_inet_ntoa(bindaddr.sin_addr)); 02037 ast_cli(a->fd, FORMAT, "Stun Address:", global_stunaddr != 0 ? ast_inet_ntoa(stunaddr.sin_addr) : "Disabled"); 02038 ast_cli(a->fd, FORMAT, "External IP:", S_OR(externip, "Disabled")); 02039 ast_cli(a->fd, FORMAT, "Context:", global_context); 02040 ast_cli(a->fd, FORMAT, "Codecs:", ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, global_capability)); 02041 ast_cli(a->fd, FORMAT, "Parking Lot:", global_parkinglot); 02042 ast_cli(a->fd, FORMAT, "Allow Guest:", AST_CLI_YESNO(global_allowguest)); 02043 ast_cli(a->fd, "\n----\n"); 02044 02045 return CLI_SUCCESS; 02046 #undef FORMAT 02047 }
| static int gtalk_update_externip | ( | void | ) | [static] |
Definition at line 1434 of file chan_gtalk.c.
References ast_connect(), ast_inet_ntoa(), ast_log(), ast_sockaddr_from_sin, ast_sockaddr_stringify(), ast_strdupa, ast_stun_request(), errno, LOG_WARNING, and stunaddr.
Referenced by gtalk_create_candidates(), and gtalk_load_config().
01435 { 01436 int sock; 01437 char *newaddr; 01438 struct sockaddr_in answer = { 0, }; 01439 struct sockaddr_in *dst; 01440 struct ast_sockaddr tmp_dst; 01441 01442 if (!stunaddr.sin_addr.s_addr) { 01443 return -1; 01444 } 01445 dst = &stunaddr; 01446 01447 sock = socket(AF_INET, SOCK_DGRAM, 0); 01448 if (sock < 0) { 01449 ast_log(LOG_WARNING, "Unable to create STUN socket: %s\n", strerror(errno)); 01450 return -1; 01451 } 01452 01453 ast_sockaddr_from_sin(&tmp_dst, dst); 01454 if (ast_connect(sock, &tmp_dst) != 0) { 01455 ast_log(LOG_WARNING, "STUN Failed to connect to %s\n", ast_sockaddr_stringify(&tmp_dst)); 01456 close(sock); 01457 return -1; 01458 } 01459 01460 if ((ast_stun_request(sock, &stunaddr, NULL, &answer))) { 01461 close(sock); 01462 return -1; 01463 } 01464 01465 newaddr = ast_strdupa(ast_inet_ntoa(answer.sin_addr)); 01466 memcpy(externip, newaddr, sizeof(externip)); 01467 01468 close(sock); 01469 return 0; 01470 01471 }
Definition at line 1473 of file chan_gtalk.c.
References ast_debug, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_instance_get_remote_address(), ast_rtp_instance_stun_request(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, hp, gtalk_candidate::ip, gtalk_pvt::laststun, LOG_WARNING, gtalk_candidate::next, gtalk_pvt::ourcandidates, gtalk_candidate::port, gtalk_pvt::rtp, gtalk_pvt::theircandidates, and gtalk_candidate::username.
Referenced by gtalk_add_candidate(), gtalk_is_accepted(), gtalk_is_answered(), and gtalk_rtp_read().
01474 { 01475 struct gtalk_candidate *tmp; 01476 struct hostent *hp; 01477 struct ast_hostent ahp; 01478 struct sockaddr_in sin = { 0, }; 01479 struct sockaddr_in aux = { 0, }; 01480 struct ast_sockaddr sin_tmp; 01481 struct ast_sockaddr aux_tmp; 01482 01483 if (time(NULL) == p->laststun) 01484 return 0; 01485 01486 tmp = p->theircandidates; 01487 p->laststun = time(NULL); 01488 while (tmp) { 01489 char username[256]; 01490 01491 /* Find the IP address of the host */ 01492 if (!(hp = ast_gethostbyname(tmp->ip, &ahp))) { 01493 ast_log(LOG_WARNING, "Could not get host by name for %s\n", tmp->ip); 01494 tmp = tmp->next; 01495 continue; 01496 } 01497 sin.sin_family = AF_INET; 01498 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01499 sin.sin_port = htons(tmp->port); 01500 snprintf(username, sizeof(username), "%s%s", tmp->username, p->ourcandidates->username); 01501 01502 /* Find out the result of the STUN */ 01503 ast_rtp_instance_get_remote_address(p->rtp, &aux_tmp); 01504 ast_sockaddr_to_sin(&aux_tmp, &aux); 01505 01506 /* If the STUN result is different from the IP of the hostname, 01507 * lock on the stun IP of the hostname advertised by the 01508 * remote client */ 01509 if (aux.sin_addr.s_addr && (aux.sin_addr.s_addr != sin.sin_addr.s_addr)) { 01510 ast_rtp_instance_stun_request(p->rtp, &aux_tmp, username); 01511 } else { 01512 ast_sockaddr_from_sin(&sin_tmp, &sin); 01513 ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username); 01514 } 01515 if (aux.sin_addr.s_addr) { 01516 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); 01517 ast_debug(4, "Sending STUN request to %s\n", tmp->ip); 01518 } 01519 01520 tmp = tmp->next; 01521 } 01522 return 1; 01523 }
| static int gtalk_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | f | |||
| ) | [static] |
Send frame to media channel (rtp).
Definition at line 1656 of file chan_gtalk.c.
References ast_format_cap_iscompatible(), AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_frame_subclass::format, 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.
01657 { 01658 struct gtalk_pvt *p = ast->tech_pvt; 01659 int res = 0; 01660 char buf[256]; 01661 01662 switch (frame->frametype) { 01663 case AST_FRAME_VOICE: 01664 if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { 01665 ast_log(LOG_WARNING, 01666 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", 01667 ast_getformatname(&frame->subclass.format), 01668 ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), 01669 ast_getformatname(&ast->readformat), 01670 ast_getformatname(&ast->writeformat)); 01671 return 0; 01672 } 01673 if (p) { 01674 ast_mutex_lock(&p->lock); 01675 if (p->rtp) { 01676 res = ast_rtp_instance_write(p->rtp, frame); 01677 } 01678 ast_mutex_unlock(&p->lock); 01679 } 01680 break; 01681 case AST_FRAME_VIDEO: 01682 if (p) { 01683 ast_mutex_lock(&p->lock); 01684 if (p->vrtp) { 01685 res = ast_rtp_instance_write(p->vrtp, frame); 01686 } 01687 ast_mutex_unlock(&p->lock); 01688 } 01689 break; 01690 case AST_FRAME_IMAGE: 01691 return 0; 01692 break; 01693 default: 01694 ast_log(LOG_WARNING, "Can't send %d type frames with Gtalk write\n", 01695 frame->frametype); 01696 return 0; 01697 } 01698 01699 return res; 01700 }
| static int load_module | ( | void | ) | [static] |
Load module into PBX, register channel.
Definition at line 2295 of file chan_gtalk.c.
References __ourip, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), AST_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_add_all_by_type(), ast_format_cap_alloc(), AST_FORMAT_GSM, AST_FORMAT_H263, ast_format_set(), AST_FORMAT_TYPE_AUDIO, AST_FORMAT_ULAW, ast_log(), ast_module_helper(), AST_MODULE_LOAD_DECLINE, ast_rtp_glue_register, ast_sched_context_create(), ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ASTOBJ_CONTAINER_INIT, ast_channel_tech::capabilities, free, GOOGLE_CONFIG, gtalk_get_local_ip(), gtalk_list, gtalk_load_config(), io_context_create(), LOG_ERROR, LOG_WARNING, and ast_channel_tech::type.
02296 { 02297 struct ast_sockaddr bindaddr_tmp; 02298 struct ast_sockaddr ourip_tmp; 02299 char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); 02300 struct ast_format tmpfmt; 02301 02302 if (!(gtalk_tech.capabilities = ast_format_cap_alloc())) { 02303 return AST_MODULE_LOAD_DECLINE; 02304 } 02305 if (!(global_capability = ast_format_cap_alloc())) { 02306 return AST_MODULE_LOAD_DECLINE; 02307 } 02308 02309 ast_format_cap_add_all_by_type(gtalk_tech.capabilities, AST_FORMAT_TYPE_AUDIO); 02310 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); 02311 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0)); 02312 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); 02313 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_H263, 0)); 02314 02315 free(jabber_loaded); 02316 if (!jabber_loaded) { 02317 /* If embedded, check for a different module name */ 02318 jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0); 02319 free(jabber_loaded); 02320 if (!jabber_loaded) { 02321 ast_log(LOG_ERROR, "chan_gtalk.so depends upon res_jabber.so\n"); 02322 return AST_MODULE_LOAD_DECLINE; 02323 } 02324 } 02325 02326 ASTOBJ_CONTAINER_INIT(>alk_list); 02327 if (!gtalk_load_config()) { 02328 ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", GOOGLE_CONFIG); 02329 return 0; 02330 } 02331 02332 sched = ast_sched_context_create(); 02333 if (!sched) { 02334 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 02335 } 02336 02337 io = io_context_create(); 02338 if (!io) { 02339 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 02340 } 02341 02342 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 02343 if (gtalk_get_local_ip(&ourip_tmp)) { 02344 ast_log(LOG_WARNING, "Unable to get own IP address, Gtalk disabled\n"); 02345 return 0; 02346 } 02347 __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp)); 02348 02349 ast_rtp_glue_register(>alk_rtp_glue); 02350 ast_cli_register_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli)); 02351 02352 /* Make sure we can register our channel type */ 02353 if (ast_channel_register(>alk_tech)) { 02354 ast_log(LOG_ERROR, "Unable to register channel class %s\n", gtalk_tech.type); 02355 return -1; 02356 } 02357 return 0; 02358 }
| static int unload_module | ( | void | ) | [static] |
Reload module.
Definition at line 2369 of file chan_gtalk.c.
References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_format_cap_destroy(), 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, ast_channel_tech::capabilities, gtalk_list, gtalk_member_destroy(), gtalklock, LOG_WARNING, gtalk_pvt::next, and gtalk_pvt::owner.
02370 { 02371 struct gtalk_pvt *privates = NULL; 02372 ast_cli_unregister_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli)); 02373 /* First, take us out of the channel loop */ 02374 ast_channel_unregister(>alk_tech); 02375 ast_rtp_glue_unregister(>alk_rtp_glue); 02376 02377 if (!ast_mutex_lock(>alklock)) { 02378 /* Hangup all interfaces if they have an owner */ 02379 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { 02380 ASTOBJ_WRLOCK(iterator); 02381 privates = iterator->p; 02382 while(privates) { 02383 if (privates->owner) 02384 ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD); 02385 privates = privates->next; 02386 } 02387 iterator->p = NULL; 02388 ASTOBJ_UNLOCK(iterator); 02389 }); 02390 ast_mutex_unlock(>alklock); 02391 } else { 02392 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 02393 return -1; 02394 } 02395 ASTOBJ_CONTAINER_DESTROYALL(>alk_list, gtalk_member_destroy); 02396 ASTOBJ_CONTAINER_DESTROY(>alk_list); 02397 global_capability = ast_format_cap_destroy(global_capability); 02398 gtalk_tech.capabilities = ast_format_cap_destroy(gtalk_tech.capabilities); 02399 return 0; 02400 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static] |
Definition at line 2407 of file chan_gtalk.c.
struct in_addr __ourip [static] |
Definition at line 231 of file chan_gtalk.c.
Referenced by build_gateway(), config_load(), find_subchannel_and_lock(), load_module(), reload_config(), and skinny_register().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 2407 of file chan_gtalk.c.
struct sockaddr_in bindaddr = { 0, } [static] |
The address we bind to
Definition at line 227 of file chan_gtalk.c.
Referenced by __oh323_rtp_create(), __sip_subscribe_mwi_do(), ast_sip_ouraddrfor(), ast_sockaddr_resolve_first(), build_peer(), config_load(), config_parse_variables(), create_addr(), dialog_initialize_rtp(), handle_skinny_show_settings(), initialize_udptl(), load_module(), proxy_update(), realtime_peer_by_name(), reload_config(), sip_show_settings(), sipsock_read(), start_rtp(), and transmit_register().
const int DEFAULT_ALLOWGUEST = 1 [static] |
const char DEFAULT_CONTEXT[] = "default" [static] |
Definition at line 170 of file chan_gtalk.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 83 of file chan_gtalk.c.
const char desc[] = "Gtalk Channel" [static] |
Definition at line 169 of file chan_gtalk.c.
char externip[16] [static] |
Definition at line 239 of file chan_gtalk.c.
int global_allowguest [static] |
Definition at line 242 of file chan_gtalk.c.
struct ast_format_cap* global_capability [static] |
Definition at line 173 of file chan_gtalk.c.
char global_context[AST_MAX_CONTEXT] [static] |
Definition at line 240 of file chan_gtalk.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 91 of file chan_gtalk.c.
char global_parkinglot[AST_MAX_CONTEXT] [static] |
Definition at line 241 of file chan_gtalk.c.
int global_stunaddr [static] |
Definition at line 244 of file chan_gtalk.c.
struct ast_cli_entry gtalk_cli[] [static] |
Initial value:
{
AST_CLI_DEFINE(gtalk_show_channels, "Show GoogleTalk channels"),
AST_CLI_DEFINE(gtalk_show_settings, "Show GoogleTalk global settings"),
}
Definition at line 233 of file chan_gtalk.c.
struct gtalk_container gtalk_list [static] |
Definition at line 246 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 592 of file chan_gtalk.c.
struct ast_channel_tech gtalk_tech [static] |
ast_mutex_t gtalklock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static] |
Protect the interface list (of gtalk_pvt's)
Definition at line 175 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 230 of file chan_gtalk.c.
struct ast_sched_context* sched [static] |
The scheduling context
Definition at line 229 of file chan_gtalk.c.
struct sockaddr_in stunaddr [static] |
the stun server we get the externip from
Definition at line 243 of file chan_gtalk.c.
Referenced by gtalk_load_config(), gtalk_show_settings(), and gtalk_update_externip().
1.5.6