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