#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.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 "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/stringfields.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astobj.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/jabber.h"
Include dependency graph for chan_gtalk.c:

Go to the source code of this file.
Data Structures | |
| struct | gtalk |
| struct | gtalk_candidate |
| struct | gtalk_container |
| struct | gtalk_pvt |
Defines | |
| #define | FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
| #define | GOOGLE_CONFIG "gtalk.conf" |
| #define | GOOGLE_NS "http://www.google.com/session" |
Enumerations | |
| enum | gtalk_connect_type { AJI_CONNECT_STUN = 1, AJI_CONNECT_LOCAL = 2, AJI_CONNECT_RELAY = 3 } |
| enum | gtalk_protocol { AJI_PROTOCOL_UDP = 1, AJI_PROTOCOL_SSLTCP = 2 } |
Functions | |
| static int | add_codec_to_answer (const struct gtalk_pvt *p, int codec, iks *dcodecs) |
| AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Gtalk Channel Driver",.load=load_module,.unload=unload_module,.reload=reload,) | |
| AST_MUTEX_DEFINE_STATIC (gtalklock) | |
| static struct gtalk * | find_gtalk (char *name, char *connection) |
| static int | gtalk_action (struct gtalk *client, struct gtalk_pvt *p, const char *action) |
| static int | gtalk_add_candidate (struct gtalk *client, ikspak *pak) |
| static struct gtalk_pvt * | gtalk_alloc (struct gtalk *client, const char *us, const char *them, const char *sid) |
| static int | gtalk_answer (struct ast_channel *ast) |
| static int | gtalk_call (struct ast_channel *ast, char *dest, int timeout) |
| Initiate new call, part of PBX interface dest is the dial string. | |
| static int | gtalk_create_candidates (struct gtalk *client, struct gtalk_pvt *p, char *sid, char *from, char *to) |
| static int | gtalk_create_member (char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct gtalk *member) |
| static int | gtalk_digit (struct ast_channel *ast, char digit, unsigned int duration) |
| static int | gtalk_digit_begin (struct ast_channel *ast, char digit) |
| static int | gtalk_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| static int | gtalk_do_reload (int fd, int argc, char **argv) |
| CLI command "gtalk show channels". | |
| static int | gtalk_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static void | gtalk_free_candidates (struct gtalk_candidate *candidate) |
| static void | gtalk_free_pvt (struct gtalk *client, struct gtalk_pvt *p) |
| static int | gtalk_get_codec (struct ast_channel *chan) |
| static enum ast_rtp_get_result | gtalk_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
| static int | gtalk_handle_dtmf (struct gtalk *client, ikspak *pak) |
| static int | gtalk_hangup (struct ast_channel *ast) |
| Hangup a call through the gtalk proxy channel. | |
| static int | gtalk_hangup_farend (struct gtalk *client, ikspak *pak) |
| static int | gtalk_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen) |
| static int | gtalk_invite (struct gtalk_pvt *p, char *to, char *from, char *sid, int initiator) |
| static int | gtalk_invite_response (struct gtalk_pvt *p, char *to, char *from, char *sid, int initiator) |
| static int | gtalk_is_accepted (struct gtalk *client, ikspak *pak) |
| static int | gtalk_is_answered (struct gtalk *client, ikspak *pak) |
| static int | gtalk_load_config (void) |
| static void | gtalk_member_destroy (struct gtalk *obj) |
| static struct ast_channel * | gtalk_new (struct gtalk *client, struct gtalk_pvt *i, int state, const char *title) |
| Start new gtalk channel. | |
| static int | gtalk_newcall (struct gtalk *client, ikspak *pak) |
| static int | gtalk_parser (void *data, ikspak *pak) |
| static struct ast_frame * | gtalk_read (struct ast_channel *ast) |
| static struct ast_channel * | gtalk_request (const char *type, int format, void *data, int *cause) |
| Part of PBX interface. | |
| static int | gtalk_response (struct gtalk *client, char *from, ikspak *pak, const char *reasonstr, const char *reasonstr2) |
| static int | gtalk_ringing_ack (void *data, ikspak *pak) |
| static struct ast_frame * | gtalk_rtp_read (struct ast_channel *ast, struct gtalk_pvt *p) |
| static int | gtalk_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen) |
| static int | gtalk_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active) |
| static int | gtalk_show_channels (int fd, int argc, char **argv) |
| CLI command "gtalk show channels". | |
| static int | gtalk_update_stun (struct gtalk *client, struct gtalk_pvt *p) |
| static int | gtalk_write (struct ast_channel *ast, struct ast_frame *frame) |
| Send frame to media channel (rtp). | |
| static int | load_module (void) |
| Load module into PBX, register channel. | |
| static int | reload (void) |
| Reload module. | |
| static int | unload_module (void) |
| Unload the gtalk channel from Asterisk. | |
Variables | |
| static struct in_addr | __ourip |
| static struct sockaddr_in | bindaddr = { 0, } |
| static struct ast_jb_conf | default_jbconf |
| static const char | desc [] = "Gtalk Channel" |
| static char | externip [16] |
| static int | global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 |
| static struct ast_jb_conf | global_jbconf |
| static struct ast_cli_entry | gtalk_cli [] |
| static struct gtalk_container | gtalk_list |
| static struct ast_rtp_protocol | gtalk_rtp |
| RTP driver interface. | |
| static struct ast_channel_tech | gtalk_tech |
| PBX interface structure for channel registration. | |
| static struct io_context * | io |
| static char | reload_usage [] |
| static struct sched_context * | sched |
| static char | show_channels_usage [] |
Definition in file chan_gtalk.c.
| #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
| #define GOOGLE_CONFIG "gtalk.conf" |
| #define GOOGLE_NS "http://www.google.com/session" |
Definition at line 85 of file chan_gtalk.c.
| enum gtalk_connect_type |
Definition at line 103 of file chan_gtalk.c.
00103 { 00104 AJI_CONNECT_STUN = 1, 00105 AJI_CONNECT_LOCAL = 2, 00106 AJI_CONNECT_RELAY = 3, 00107 };
| enum gtalk_protocol |
Definition at line 98 of file chan_gtalk.c.
00098 { 00099 AJI_PROTOCOL_UDP = 1, 00100 AJI_PROTOCOL_SSLTCP = 2, 00101 };
| static int add_codec_to_answer | ( | const struct gtalk_pvt * | p, | |
| int | codec, | |||
| iks * | dcodecs | |||
| ) | [static] |
Definition at line 297 of file chan_gtalk.c.
References ast_getformatname(), ast_log(), ast_rtp_lookup_code(), format, LOG_WARNING, gtalk::p, and gtalk_pvt::rtp.
Referenced by gtalk_invite().
00298 { 00299 int res = 0; 00300 char *format = ast_getformatname(codec); 00301 00302 if (!strcasecmp("ulaw", format)) { 00303 iks *payload_eg711u, *payload_pcmu; 00304 payload_pcmu = iks_new("payload-type"); 00305 payload_eg711u = iks_new("payload-type"); 00306 00307 if(!payload_eg711u || !payload_pcmu) { 00308 if(payload_pcmu) 00309 iks_delete(payload_pcmu); 00310 if(payload_eg711u) 00311 iks_delete(payload_eg711u); 00312 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00313 return -1; 00314 } 00315 iks_insert_attrib(payload_pcmu, "id", "0"); 00316 iks_insert_attrib(payload_pcmu, "name", "PCMU"); 00317 iks_insert_attrib(payload_pcmu, "clockrate","8000"); 00318 iks_insert_attrib(payload_pcmu, "bitrate","64000"); 00319 iks_insert_attrib(payload_eg711u, "id", "100"); 00320 iks_insert_attrib(payload_eg711u, "name", "EG711U"); 00321 iks_insert_attrib(payload_eg711u, "clockrate","8000"); 00322 iks_insert_attrib(payload_eg711u, "bitrate","64000"); 00323 iks_insert_node(dcodecs, payload_pcmu); 00324 iks_insert_node(dcodecs, payload_eg711u); 00325 res ++; 00326 } 00327 if (!strcasecmp("alaw", format)) { 00328 iks *payload_eg711a, *payload_pcma; 00329 payload_pcma = iks_new("payload-type"); 00330 payload_eg711a = iks_new("payload-type"); 00331 if(!payload_eg711a || !payload_pcma) { 00332 if(payload_eg711a) 00333 iks_delete(payload_eg711a); 00334 if(payload_pcma) 00335 iks_delete(payload_pcma); 00336 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00337 return -1; 00338 } 00339 iks_insert_attrib(payload_pcma, "id", "8"); 00340 iks_insert_attrib(payload_pcma, "name", "PCMA"); 00341 iks_insert_attrib(payload_pcma, "clockrate","8000"); 00342 iks_insert_attrib(payload_pcma, "bitrate","64000"); 00343 payload_eg711a = iks_new("payload-type"); 00344 iks_insert_attrib(payload_eg711a, "id", "101"); 00345 iks_insert_attrib(payload_eg711a, "name", "EG711A"); 00346 iks_insert_attrib(payload_eg711a, "clockrate","8000"); 00347 iks_insert_attrib(payload_eg711a, "bitrate","64000"); 00348 iks_insert_node(dcodecs, payload_pcma); 00349 iks_insert_node(dcodecs, payload_eg711a); 00350 res ++; 00351 } 00352 if (!strcasecmp("ilbc", format)) { 00353 iks *payload_ilbc = iks_new("payload-type"); 00354 if(!payload_ilbc) { 00355 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00356 return -1; 00357 } 00358 iks_insert_attrib(payload_ilbc, "id", "97"); 00359 iks_insert_attrib(payload_ilbc, "name", "iLBC"); 00360 iks_insert_attrib(payload_ilbc, "clockrate","8000"); 00361 iks_insert_attrib(payload_ilbc, "bitrate","13300"); 00362 iks_insert_node(dcodecs, payload_ilbc); 00363 res ++; 00364 } 00365 if (!strcasecmp("g723", format)) { 00366 iks *payload_g723 = iks_new("payload-type"); 00367 if(!payload_g723) { 00368 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00369 return -1; 00370 } 00371 iks_insert_attrib(payload_g723, "id", "4"); 00372 iks_insert_attrib(payload_g723, "name", "G723"); 00373 iks_insert_attrib(payload_g723, "clockrate","8000"); 00374 iks_insert_attrib(payload_g723, "bitrate","6300"); 00375 iks_insert_node(dcodecs, payload_g723); 00376 res ++; 00377 } 00378 if (!strcasecmp("speex", format)) { 00379 iks *payload_speex = iks_new("payload-type"); 00380 if(!payload_speex) { 00381 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00382 return -1; 00383 } 00384 iks_insert_attrib(payload_speex, "id", "110"); 00385 iks_insert_attrib(payload_speex, "name", "speex"); 00386 iks_insert_attrib(payload_speex, "clockrate","8000"); 00387 iks_insert_attrib(payload_speex, "bitrate","11000"); 00388 iks_insert_node(dcodecs, payload_speex); 00389 res++; 00390 } 00391 if (!strcasecmp("gsm", format)) { 00392 iks *payload_gsm = iks_new("payload-type"); 00393 if(!payload_gsm) { 00394 ast_log(LOG_WARNING,"Failed to allocate iks node"); 00395 return -1; 00396 } 00397 iks_insert_attrib(payload_gsm, "id", "103"); 00398 iks_insert_attrib(payload_gsm, "name", "gsm"); 00399 iks_insert_node(dcodecs, payload_gsm); 00400 res++; 00401 } 00402 ast_rtp_lookup_code(p->rtp, 1, codec); 00403 return res; 00404 }
| AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
| AST_MODFLAG_DEFAULT | , | |||
| "Gtalk Channel Driver" | , | |||
| . | load = load_module, |
|||
| . | unload = unload_module, |
|||
| . | reload = reload | |||
| ) |
| AST_MUTEX_DEFINE_STATIC | ( | gtalklock | ) |
Protect the interface list (of gtalk_pvt's)
| static struct gtalk* find_gtalk | ( | char * | name, | |
| char * | connection | |||
| ) | [static] |
Definition at line 265 of file chan_gtalk.c.
References ast_strdupa, ast_verbose(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, gtalk_list, s, strsep(), and gtalk::user.
Referenced by gtalk_request().
00266 { 00267 struct gtalk *gtalk = NULL; 00268 char *domain = NULL , *s = NULL; 00269 00270 if(strchr(connection, '@')) { 00271 s = ast_strdupa(connection); 00272 domain = strsep(&s, "@"); 00273 ast_verbose("OOOOH domain = %s\n", domain); 00274 } 00275 gtalk = ASTOBJ_CONTAINER_FIND(>alk_list, name); 00276 if (!gtalk && strchr(name, '@')) 00277 gtalk = ASTOBJ_CONTAINER_FIND_FULL(>alk_list, name, user,,, strcasecmp); 00278 00279 if (!gtalk) { 00280 /* guest call */ 00281 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { 00282 ASTOBJ_RDLOCK(iterator); 00283 if (!strcasecmp(iterator->name, "guest")) { 00284 gtalk = iterator; 00285 } 00286 ASTOBJ_UNLOCK(iterator); 00287 00288 if (gtalk) 00289 break; 00290 }); 00291 00292 } 00293 return gtalk; 00294 }
| static int gtalk_action | ( | struct gtalk * | client, | |
| struct gtalk_pvt * | p, | |||
| const char * | action | |||
| ) | [static] |
Definition at line 1073 of file chan_gtalk.c.
References ast_aji_increment_mid(), gtalk::connection, gtalk_pvt::initiator, aji_client::mid, aji_client::p, gtalk_pvt::sid, gtalk_pvt::them, and gtalk_pvt::us.
Referenced by gtalk_hangup(), and gtalk_newcall().
01074 { 01075 iks *request, *session = NULL; 01076 int res = -1; 01077 01078 request = iks_new("iq"); 01079 if (request) { 01080 iks_insert_attrib(request, "type", "set"); 01081 iks_insert_attrib(request, "from", p->us); 01082 iks_insert_attrib(request, "to", p->them); 01083 iks_insert_attrib(request, "id", client->connection->mid); 01084 ast_aji_increment_mid(client->connection->mid); 01085 session = iks_new("session"); 01086 if (session) { 01087 iks_insert_attrib(session, "type", action); 01088 iks_insert_attrib(session, "id", p->sid); 01089 iks_insert_attrib(session, "initiator", p->initiator ? p->us : p->them); 01090 iks_insert_attrib(session, "xmlns", "http://www.google.com/session"); 01091 iks_insert_node(request, session); 01092 iks_send(client->connection->p, request); 01093 iks_delete(session); 01094 res = 0; 01095 } 01096 iks_delete(request); 01097 } 01098 return res; 01099 }
| static int gtalk_add_candidate | ( | struct gtalk * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1287 of file chan_gtalk.c.
References AJI_CONNECT_LOCAL, AJI_CONNECT_RELAY, AJI_CONNECT_STUN, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_calloc, gtalk::connection, gtalk_update_stun(), aji_client::jid, gtalk_pvt::laststun, gtalk_pvt::next, aji_client::p, gtalk::p, gtalk_pvt::parent, gtalk_candidate::receipt, and gtalk_pvt::theircandidates.
Referenced by gtalk_parser().
01288 { 01289 struct gtalk_pvt *p = NULL, *tmp = NULL; 01290 struct aji_client *c = client->connection; 01291 struct gtalk_candidate *newcandidate = NULL; 01292 iks *traversenodes = NULL, *receipt = NULL; 01293 char *from; 01294 01295 from = iks_find_attrib(pak->x,"to"); 01296 if(!from) 01297 from = c->jid->full; 01298 01299 for (tmp = client->p; tmp; tmp = tmp->next) { 01300 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) { 01301 p = tmp; 01302 break; 01303 } 01304 } 01305 01306 if (!p) 01307 return -1; 01308 01309 traversenodes = pak->query; 01310 while(traversenodes) { 01311 if(!strcasecmp(iks_name(traversenodes), "session")) { 01312 traversenodes = iks_child(traversenodes); 01313 continue; 01314 } 01315 if(!strcasecmp(iks_name(traversenodes), "transport")) { 01316 traversenodes = iks_child(traversenodes); 01317 continue; 01318 } 01319 if(!strcasecmp(iks_name(traversenodes), "candidate")) { 01320 newcandidate = ast_calloc(1, sizeof(*newcandidate)); 01321 if (!newcandidate) 01322 return 0; 01323 ast_copy_string(newcandidate->name, iks_find_attrib(traversenodes, "name"), 01324 sizeof(newcandidate->name)); 01325 ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "address"), 01326 sizeof(newcandidate->ip)); 01327 newcandidate->port = atoi(iks_find_attrib(traversenodes, "port")); 01328 ast_copy_string(newcandidate->username, iks_find_attrib(traversenodes, "username"), 01329 sizeof(newcandidate->username)); 01330 ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "password"), 01331 sizeof(newcandidate->password)); 01332 newcandidate->preference = atof(iks_find_attrib(traversenodes, "preference")); 01333 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp")) 01334 newcandidate->protocol = AJI_PROTOCOL_UDP; 01335 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp")) 01336 newcandidate->protocol = AJI_PROTOCOL_SSLTCP; 01337 01338 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "stun")) 01339 newcandidate->type = AJI_CONNECT_STUN; 01340 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "local")) 01341 newcandidate->type = AJI_CONNECT_LOCAL; 01342 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay")) 01343 newcandidate->type = AJI_CONNECT_RELAY; 01344 ast_copy_string(newcandidate->network, iks_find_attrib(traversenodes, "network"), 01345 sizeof(newcandidate->network)); 01346 newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation")); 01347 newcandidate->next = NULL; 01348 01349 newcandidate->next = p->theircandidates; 01350 p->theircandidates = newcandidate; 01351 p->laststun = 0; 01352 gtalk_update_stun(p->parent, p); 01353 newcandidate = NULL; 01354 } 01355 traversenodes = iks_next(traversenodes); 01356 } 01357 01358 receipt = iks_new("iq"); 01359 iks_insert_attrib(receipt, "type", "result"); 01360 iks_insert_attrib(receipt, "from", from); 01361 iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from")); 01362 iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id")); 01363 iks_send(c->p, receipt); 01364 iks_delete(receipt); 01365 01366 return 1; 01367 }
| static struct gtalk_pvt * gtalk_alloc | ( | struct gtalk * | client, | |
| const char * | us, | |||
| const char * | them, | |||
| const char * | sid | |||
| ) | [static] |
Definition at line 916 of file chan_gtalk.c.
References ast_calloc, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_new_with_bindaddr(), ast_rtp_pt_clear(), ast_strdupa, ASTOBJ_CONTAINER_FIND, bindaddr, aji_client::buddies, gtalk::buddy, aji_resource::cap, gtalk::capability, gtalk::connection, exten, free, global_capability, io, aji_version::jingle, LOG_DEBUG, LOG_ERROR, LOG_WARNING, aji_resource::next, option_debug, gtalk::p, aji_resource::resource, aji_buddy::resources, and strsep().
Referenced by gtalk_newcall(), and gtalk_request().
00917 { 00918 struct gtalk_pvt *tmp = NULL; 00919 struct aji_resource *resources = NULL; 00920 struct aji_buddy *buddy; 00921 char idroster[200]; 00922 char *data, *exten = NULL; 00923 00924 if (option_debug) 00925 ast_log(LOG_DEBUG, "The client is %s for alloc\n", client->name); 00926 if (!sid && !strchr(them, '/')) { /* I started call! */ 00927 if (!strcasecmp(client->name, "guest")) { 00928 buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, them); 00929 if (buddy) 00930 resources = buddy->resources; 00931 } else if (client->buddy) 00932 resources = client->buddy->resources; 00933 while (resources) { 00934 if (resources->cap->jingle) { 00935 break; 00936 } 00937 resources = resources->next; 00938 } 00939 if (resources) 00940 snprintf(idroster, sizeof(idroster), "%s/%s", them, resources->resource); 00941 else { 00942 ast_log(LOG_ERROR, "no gtalk capable clients to talk to.\n"); 00943 return NULL; 00944 } 00945 } 00946 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 00947 return NULL; 00948 } 00949 if (sid) { 00950 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid)); 00951 ast_copy_string(tmp->them, them, sizeof(tmp->them)); 00952 ast_copy_string(tmp->us, us, sizeof(tmp->us)); 00953 } else { 00954 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random()); 00955 ast_copy_string(tmp->them, idroster, sizeof(tmp->them)); 00956 ast_copy_string(tmp->us, us, sizeof(tmp->us)); 00957 tmp->initiator = 1; 00958 } 00959 /* clear codecs */ 00960 tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 00961 ast_rtp_pt_clear(tmp->rtp); 00962 00963 /* add user configured codec capabilites */ 00964 if (client->capability) 00965 tmp->capability = client->capability; 00966 else if (global_capability) 00967 tmp->capability = global_capability; 00968 00969 tmp->parent = client; 00970 if (!tmp->rtp) { 00971 ast_log(LOG_WARNING, "Out of RTP sessions?\n"); 00972 free(tmp); 00973 return NULL; 00974 } 00975 00976 /* Set CALLERID(name) to the full JID of the remote peer */ 00977 ast_copy_string(tmp->cid_name, tmp->them, sizeof(tmp->cid_name)); 00978 00979 if(strchr(tmp->us, '/')) { 00980 data = ast_strdupa(tmp->us); 00981 exten = strsep(&data, "/"); 00982 } else 00983 exten = tmp->us; 00984 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten)); 00985 ast_mutex_init(&tmp->lock); 00986 ast_mutex_lock(>alklock); 00987 tmp->next = client->p; 00988 client->p = tmp; 00989 ast_mutex_unlock(>alklock); 00990 return tmp; 00991 }
| static int gtalk_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 529 of file chan_gtalk.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), gtalk_invite(), gtalk_pvt::lock, LOG_DEBUG, option_debug, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.
00530 { 00531 struct gtalk_pvt *p = ast->tech_pvt; 00532 int res = 0; 00533 00534 if (option_debug) 00535 ast_log(LOG_DEBUG, "Answer!\n"); 00536 ast_mutex_lock(&p->lock); 00537 gtalk_invite(p, p->them, p->us,p->sid, 0); 00538 ast_mutex_unlock(&p->lock); 00539 return res; 00540 }
| static int gtalk_call | ( | struct ast_channel * | ast, | |
| char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Initiate new call, part of PBX interface dest is the dial string.
Definition at line 1572 of file chan_gtalk.c.
References ast_channel::_state, ast_log(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RING, gtalk::connection, aji_client::f, gtalk_create_candidates(), gtalk_invite(), gtalk_ringing_ack(), LOG_WARNING, aji_client::mid, gtalk_pvt::parent, gtalk_pvt::ring, gtalk_pvt::ringrule, gtalk_pvt::sid, ast_channel::tech_pvt, gtalk_pvt::them, and gtalk_pvt::us.
01573 { 01574 struct gtalk_pvt *p = ast->tech_pvt; 01575 01576 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 01577 ast_log(LOG_WARNING, "gtalk_call called on %s, neither down nor reserved\n", ast->name); 01578 return -1; 01579 } 01580 01581 ast_setstate(ast, AST_STATE_RING); 01582 if (!p->ringrule) { 01583 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring)); 01584 p->ringrule = iks_filter_add_rule(p->parent->connection->f, gtalk_ringing_ack, p, 01585 IKS_RULE_ID, p->ring, IKS_RULE_DONE); 01586 } else 01587 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n"); 01588 01589 gtalk_invite(p, p->them, p->us, p->sid, 1); 01590 gtalk_create_candidates(p->parent, p, p->sid, p->them, p->us); 01591 01592 return 0; 01593 }
| static int gtalk_create_candidates | ( | struct gtalk * | client, | |
| struct gtalk_pvt * | p, | |||
| char * | sid, | |||
| char * | from, | |||
| char * | to | |||
| ) | [static] |
Definition at line 788 of file chan_gtalk.c.
References __ourip, AJI_CONNECT_LOCAL, AJI_CONNECT_RELAY, AJI_CONNECT_STUN, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_increment_mid(), ast_calloc, ast_find_ourip(), ast_inet_ntoa(), ast_log(), ast_random(), ast_rtp_get_us(), ast_strlen_zero(), bindaddr, gtalk::connection, externip, free, GOOGLE_NS, gtalk_pvt::initiator, gtalk_candidate::ip, gtalk_pvt::laststun, LOG_ERROR, LOG_NOTICE, aji_client::mid, gtalk_candidate::name, gtalk_candidate::next, gtalk_pvt::next, gtalk_pvt::ourcandidates, aji_client::p, gtalk_candidate::password, gtalk_candidate::port, gtalk_candidate::preference, gtalk_candidate::protocol, gtalk_pvt::rtp, gtalk_pvt::sid, gtalk_candidate::type, and gtalk_candidate::username.
Referenced by gtalk_call(), and gtalk_newcall().
00789 { 00790 struct gtalk_candidate *tmp; 00791 struct aji_client *c = client->connection; 00792 struct gtalk_candidate *ours1 = NULL, *ours2 = NULL; 00793 struct sockaddr_in sin; 00794 struct sockaddr_in dest; 00795 struct in_addr us; 00796 iks *iq, *gtalk, *candidate, *transport; 00797 char user[17], pass[17], preference[5], port[7]; 00798 00799 00800 iq = iks_new("iq"); 00801 gtalk = iks_new("session"); 00802 candidate = iks_new("candidate"); 00803 transport = iks_new("transport"); 00804 if (!iq || !gtalk || !candidate || !transport) { 00805 ast_log(LOG_ERROR, "Memory allocation error\n"); 00806 goto safeout; 00807 } 00808 ours1 = ast_calloc(1, sizeof(*ours1)); 00809 ours2 = ast_calloc(1, sizeof(*ours2)); 00810 if (!ours1 || !ours2) 00811 goto safeout; 00812 00813 iks_insert_attrib(transport, "xmlns","http://www.google.com/transport/p2p"); 00814 iks_insert_node(iq, gtalk); 00815 iks_insert_node(gtalk,transport); 00816 iks_insert_node(transport, candidate); 00817 00818 for (; p; p = p->next) { 00819 if (!strcasecmp(p->sid, sid)) 00820 break; 00821 } 00822 00823 if (!p) { 00824 ast_log(LOG_NOTICE, "No matching gtalk session - SID %s!\n", sid); 00825 goto safeout; 00826 } 00827 00828 ast_rtp_get_us(p->rtp, &sin); 00829 ast_find_ourip(&us, bindaddr); 00830 00831 /* Setup our gtalk candidates */ 00832 ast_copy_string(ours1->name, "rtp", sizeof(ours1->name)); 00833 ours1->port = ntohs(sin.sin_port); 00834 ours1->preference = 1; 00835 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00836 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00837 ast_copy_string(ours1->username, user, sizeof(ours1->username)); 00838 ast_copy_string(ours1->password, pass, sizeof(ours1->password)); 00839 ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip)); 00840 ours1->protocol = AJI_PROTOCOL_UDP; 00841 ours1->type = AJI_CONNECT_LOCAL; 00842 ours1->generation = 0; 00843 p->ourcandidates = ours1; 00844 00845 if (!ast_strlen_zero(externip)) { 00846 /* XXX We should really stun for this one not just go with externip XXX */ 00847 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00848 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00849 ast_copy_string(ours2->username, user, sizeof(ours2->username)); 00850 ast_copy_string(ours2->password, pass, sizeof(ours2->password)); 00851 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip)); 00852 ast_copy_string(ours2->name, "rtp", sizeof(ours1->name)); 00853 ours2->port = ntohs(sin.sin_port); 00854 ours2->preference = 0.9; 00855 ours2->protocol = AJI_PROTOCOL_UDP; 00856 ours2->type = AJI_CONNECT_STUN; 00857 ours2->generation = 0; 00858 ours1->next = ours2; 00859 ours2 = NULL; 00860 } 00861 ours1 = NULL; 00862 dest.sin_addr = __ourip; 00863 dest.sin_port = sin.sin_port; 00864 00865 00866 for (tmp = p->ourcandidates; tmp; tmp = tmp->next) { 00867 snprintf(port, sizeof(port), "%d", tmp->port); 00868 snprintf(preference, sizeof(preference), "%.2f", tmp->preference); 00869 iks_insert_attrib(iq, "from", to); 00870 iks_insert_attrib(iq, "to", from); 00871 iks_insert_attrib(iq, "type", "set"); 00872 iks_insert_attrib(iq, "id", c->mid); 00873 ast_aji_increment_mid(c->mid); 00874 iks_insert_attrib(gtalk, "type", "transport-info"); 00875 iks_insert_attrib(gtalk, "id", sid); 00876 iks_insert_attrib(gtalk, "initiator", (p->initiator) ? to : from); 00877 iks_insert_attrib(gtalk, "xmlns", GOOGLE_NS); 00878 iks_insert_attrib(candidate, "name", tmp->name); 00879 iks_insert_attrib(candidate, "address", tmp->ip); 00880 iks_insert_attrib(candidate, "port", port); 00881 iks_insert_attrib(candidate, "username", tmp->username); 00882 iks_insert_attrib(candidate, "password", tmp->password); 00883 iks_insert_attrib(candidate, "preference", preference); 00884 if (tmp->protocol == AJI_PROTOCOL_UDP) 00885 iks_insert_attrib(candidate, "protocol", "udp"); 00886 if (tmp->protocol == AJI_PROTOCOL_SSLTCP) 00887 iks_insert_attrib(candidate, "protocol", "ssltcp"); 00888 if (tmp->type == AJI_CONNECT_STUN) 00889 iks_insert_attrib(candidate, "type", "stun"); 00890 if (tmp->type == AJI_CONNECT_LOCAL) 00891 iks_insert_attrib(candidate, "type", "local"); 00892 if (tmp->type == AJI_CONNECT_RELAY) 00893 iks_insert_attrib(candidate, "type", "relay"); 00894 iks_insert_attrib(candidate, "network", "0"); 00895 iks_insert_attrib(candidate, "generation", "0"); 00896 iks_send(c->p, iq); 00897 } 00898 p->laststun = 0; 00899 00900 safeout: 00901 if (ours1) 00902 free(ours1); 00903 if (ours2) 00904 free(ours2); 00905 if (iq) 00906 iks_delete(iq); 00907 if (gtalk) 00908 iks_delete(gtalk); 00909 if (candidate) 00910 iks_delete(candidate); 00911 if(transport) 00912 iks_delete(transport); 00913 return 1; 00914 }
| 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 1797 of file chan_gtalk.c.
References gtalk::allowguest, ast_aji_get_client(), ast_log(), ast_parse_allow_disallow(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, gtalk::buddy, gtalk::capability, gtalk::connection, gtalk::context, aji_client::f, gtalk_parser(), LOG_ERROR, LOG_WARNING, gtalk_candidate::next, prefs, gtalk::prefs, gtalk::user, and var.
01800 { 01801 struct aji_client *client; 01802 01803 if