#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 <gcrypt.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"
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 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 ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct in_addr | __ourip |
static const 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] |
GCRY_THREAD_OPTION_PTHREAD_IMPL | |
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_MUTEX_INITIALIZER ) |
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 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 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 }
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, 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, ast_copy_string(), 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_copy_string(), 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, gtalklock, io, aji_version::jingle, LOG_DEBUG, LOG_ERROR, LOG_WARNING, gtalk::name, aji_resource::next, option_debug, gtalk::p, aji_resource::resource, and aji_buddy::resources.
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_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.
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_copy_string(), 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_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, prefs, gtalk::prefs, gtalk::user, and var.
01800 { 01801 struct aji_client *client; 01802 01803 if (!member) 01804 ast_log(LOG_WARNING, "Out of memory.\n"); 01805 01806 ast_copy_string(member->name, label, sizeof(member->name)); 01807 ast_copy_string(member->user, label, sizeof(member->user)); 01808 ast_copy_string(member->context, context, sizeof(member->context)); 01809 member->allowguest = allowguest; 01810 member->prefs = prefs; 01811 while (var) { 01812 #if 0 01813 struct gtalk_candidate *candidate = NULL; 01814 #endif 01815 if (!strcasecmp(var->name, "username")) 01816 ast_copy_string(member->user, var->value, sizeof(member->user)); 01817 else if (!strcasecmp(var->name, "disallow")) 01818 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0); 01819 else if (!strcasecmp(var->name, "allow")) 01820 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1); 01821 else if (!strcasecmp(var->name, "context")) 01822 ast_copy_string(member->context, var->value, sizeof(member->context)); 01823 #if 0 01824 else if (!strcasecmp(var->name, "candidate")) { 01825 candidate = gtalk_create_candidate(var->value); 01826 if (candidate) { 01827 candidate->next = member->ourcandidates; 01828 member->ourcandidates = candidate; 01829 } 01830 } 01831 #endif 01832 else if (!strcasecmp(var->name, "connection")) { 01833 if ((client = ast_aji_get_client(var->value))) { 01834 member->connection = client; 01835 iks_filter_add_rule(client->f, gtalk_parser, member, 01836 IKS_RULE_TYPE, IKS_PAK_IQ, 01837 IKS_RULE_FROM_PARTIAL, member->user, 01838 IKS_RULE_NS, "http://www.google.com/session", 01839 IKS_RULE_DONE); 01840 01841 } else { 01842 ast_log(LOG_ERROR, "connection referenced not found!\n"); 01843 return 0; 01844 } 01845 } 01846 var = var->next; 01847 } 01848 if (member->connection && member->user) 01849 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); 01850 else { 01851 ast_log(LOG_ERROR, "No Connection or Username!\n"); 01852 } 01853 return 1; 01854 }
static int gtalk_digit | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1497 of file chan_gtalk.c.
References ast_aji_increment_mid(), 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, aji_client::p, 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().
01498 { 01499 struct gtalk_pvt *p = ast->tech_pvt; 01500 struct gtalk *client = p->parent; 01501 iks *iq, *gtalk, *dtmf; 01502 char buffer[2] = {digit, '\0'}; 01503 iq = iks_new("iq"); 01504 gtalk = iks_new("gtalk"); 01505 dtmf = iks_new("dtmf"); 01506 if(!iq || !gtalk || !dtmf) { 01507 if(iq) 01508 iks_delete(iq); 01509 if(gtalk) 01510 iks_delete(gtalk); 01511 if(dtmf) 01512 iks_delete(dtmf); 01513 ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n"); 01514 return -1; 01515 } 01516 01517 iks_insert_attrib(iq, "type", "set"); 01518 iks_insert_attrib(iq, "to", p->them); 01519 iks_insert_attrib(iq, "from", p->us); 01520 iks_insert_attrib(iq, "id", client->connection->mid); 01521 ast_aji_increment_mid(client->connection->mid); 01522 iks_insert_attrib(gtalk, "xmlns", "http://jabber.org/protocol/gtalk"); 01523 iks_insert_attrib(gtalk, "action", "session-info"); 01524 iks_insert_attrib(gtalk, "initiator", p->initiator ? p->us: p->them); 01525 iks_insert_attrib(gtalk, "sid", p->sid); 01526 iks_insert_attrib(dtmf, "xmlns", "http://jabber.org/protocol/gtalk/info/dtmf"); 01527 iks_insert_attrib(dtmf, "code", buffer); 01528 iks_insert_node(iq, gtalk); 01529 iks_insert_node(gtalk, dtmf); 01530 01531 ast_mutex_lock(&p->lock); 01532 if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) { 01533 iks_insert_attrib(dtmf, "action", "button-down"); 01534 } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) { 01535 iks_insert_attrib(dtmf, "action", "button-up"); 01536 } 01537 iks_send(client->connection->p, iq); 01538 iks_delete(iq); 01539 iks_delete(gtalk); 01540 iks_delete(dtmf); 01541 ast_mutex_unlock(&p->lock); 01542 return 0; 01543 }
static int gtalk_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1487 of file chan_gtalk.c.
References gtalk_digit().
01488 { 01489 return gtalk_digit(chan, digit, 0); 01490 }
static int gtalk_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1492 of file chan_gtalk.c.
References gtalk_digit().
01493 { 01494 return gtalk_digit(chan, digit, duration); 01495 }
static int gtalk_do_reload | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
CLI command "gtalk show channels".
Definition at line 1715 of file chan_gtalk.c.
References ast_verbose(), and RESULT_SUCCESS.
01716 { 01717 ast_verbose("IT DOES WORK!\n"); 01718 return RESULT_SUCCESS; 01719 }
static int gtalk_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 1453 of file chan_gtalk.c.
References ast_mutex_lock(), ast_mutex_unlock(), gtalk_pvt::lock, gtalk_pvt::owner, and ast_channel::tech_pvt.
01454 { 01455 struct gtalk_pvt *p = newchan->tech_pvt; 01456 ast_mutex_lock(&p->lock); 01457 01458 if ((p->owner != oldchan)) { 01459 ast_mutex_unlock(&p->lock); 01460 return -1; 01461 } 01462 if (p->owner == oldchan) 01463 p->owner = newchan; 01464 ast_mutex_unlock(&p->lock); 01465 return 0; 01466 }
static void gtalk_free_candidates | ( | struct gtalk_candidate * | candidate | ) | [static] |
Definition at line 1101 of file chan_gtalk.c.
References free, last, and gtalk_candidate::next.
Referenced by gtalk_free_pvt().
01102 { 01103 struct gtalk_candidate *last; 01104 while (candidate) { 01105 last = candidate; 01106 candidate = candidate->next; 01107 free(last); 01108 } 01109 }
Definition at line 1111 of file chan_gtalk.c.
References ast_log(), ast_rtp_destroy(), gtalk::connection, aji_client::f, free, 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().
01112 { 01113 struct gtalk_pvt *cur, *prev = NULL; 01114 cur = client->p; 01115 while (cur) { 01116 if (cur == p) { 01117 if (prev) 01118 prev->next = p->next; 01119 else 01120 client->p = p->next; 01121 break; 01122 } 01123 prev = cur; 01124 cur = cur->next; 01125 } 01126 if (p->ringrule) 01127 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 01128 if (p->owner) 01129 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n"); 01130 if (p->rtp) 01131 ast_rtp_destroy(p->rtp); 01132 if (p->vrtp) 01133 ast_rtp_destroy(p->vrtp); 01134 gtalk_free_candidates(p->theircandidates); 01135 free(p); 01136 }
static int gtalk_get_codec | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 560 of file chan_gtalk.c.
References gtalk_pvt::peercapability, and ast_channel::tech_pvt.
00561 { 00562 struct gtalk_pvt *p = chan->tech_pvt; 00563 return p->peercapability; 00564 }
static enum ast_rtp_get_result gtalk_get_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp ** | rtp | |||
) | [static] |
Definition at line 542 of file chan_gtalk.c.
References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_PARTIAL, gtalk_pvt::lock, gtalk_pvt::rtp, and ast_channel::tech_pvt.
00543 { 00544 struct gtalk_pvt *p = chan->tech_pvt; 00545 enum ast_rtp_get_result res = AST_RTP_GET_FAILED; 00546 00547 if (!p) 00548 return res; 00549 00550 ast_mutex_lock(&p->lock); 00551 if (p->rtp){ 00552 *rtp = p->rtp; 00553 res = AST_RTP_TRY_PARTIAL; 00554 } 00555 ast_mutex_unlock(&p->lock); 00556 00557 return res; 00558 }
static int gtalk_handle_dtmf | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 695 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().
00696 { 00697 struct gtalk_pvt *tmp; 00698 iks *dtmfnode = NULL, *dtmfchild = NULL; 00699 char *dtmf; 00700 char *from; 00701 /* Make sure our new call doesn't exist yet */ 00702 for (tmp = client->p; tmp; tmp = tmp->next) { 00703 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || iks_find_with_attrib(pak->x, "gtalk", "sid", tmp->sid)) 00704 break; 00705 } 00706 from = iks_find_attrib(pak->x, "to"); 00707 if(!from) 00708 from = client->connection->jid->full; 00709 00710 00711 if (tmp) { 00712 if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) { 00713 gtalk_response(client, from, pak, 00714 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", 00715 "unsupported-dtmf-method xmlns='http://jabber.org/protocol/gtalk/info/dtmf#errors'"); 00716 return -1; 00717 } 00718 if ((dtmfnode = iks_find(pak->x, "dtmf"))) { 00719 if((dtmf = iks_find_attrib(dtmfnode, "code"))) { 00720 if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) { 00721 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00722 f.subclass = dtmf[0]; 00723 ast_queue_frame(tmp->owner, &f); 00724 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00725 } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) { 00726 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00727 f.subclass = dtmf[0]; 00728 ast_queue_frame(tmp->owner, &f); 00729 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00730 } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */ 00731 struct ast_frame f = {AST_FRAME_DTMF, }; 00732 f.subclass = dtmf[0]; 00733 ast_queue_frame(tmp->owner, &f); 00734 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00735 } 00736 } 00737 } else if ((dtmfnode = iks_find_with_attrib(pak->x, "gtalk", "action", "session-info"))) { 00738 if((dtmfchild = iks_find(dtmfnode, "dtmf"))) { 00739 if((dtmf = iks_find_attrib(dtmfchild, "code"))) { 00740 if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) { 00741 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00742 f.subclass = dtmf[0]; 00743 ast_queue_frame(tmp->owner, &f); 00744 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00745 } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) { 00746 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00747 f.subclass = dtmf[0]; 00748 ast_queue_frame(tmp->owner, &f); 00749 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); 00750 } 00751 } 00752 } 00753 } 00754 gtalk_response(client, from, pak, NULL, NULL); 00755 return 1; 00756 } else 00757 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00758 00759 gtalk_response(client, from, pak, NULL, NULL); 00760 return 1; 00761 }
static int gtalk_hangup | ( | struct ast_channel * | ast | ) | [static] |
Hangup a call through the gtalk proxy channel.
Definition at line 1596 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().
01597 { 01598 struct gtalk_pvt *p = ast->tech_pvt; 01599 struct gtalk *client; 01600 01601 ast_mutex_lock(&p->lock); 01602 client = p->parent; 01603 p->owner = NULL; 01604 ast->tech_pvt = NULL; 01605 if (!p->alreadygone) 01606 gtalk_action(client, p, "terminate"); 01607 ast_mutex_unlock(&p->lock); 01608 01609 gtalk_free_pvt(client, p); 01610 ast_module_unref(ast_module_info->self); 01611 01612 return 0; 01613 }
static int gtalk_hangup_farend | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 763 of file chan_gtalk.c.
References gtalk_pvt::alreadygone, ast_log(), ast_queue_hangup(), gtalk::connection, gtalk_response(), aji_client::jid, LOG_DEBUG, LOG_NOTICE, gtalk::name, gtalk_pvt::next, gtalk_pvt::owner, gtalk::p, and gtalk_pvt::sid.
Referenced by gtalk_parser().
00764 { 00765 struct gtalk_pvt *tmp; 00766 char *from; 00767 00768 ast_log(LOG_DEBUG, "The client is %s\n", client->name); 00769 /* Make sure our new call doesn't exist yet */ 00770 for (tmp = client->p; tmp; tmp = tmp->next) { 00771 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) 00772 break; 00773 } 00774 from = iks_find_attrib(pak->x, "to"); 00775 if(!from) 00776 from = client->connection->jid->full; 00777 00778 if (tmp) { 00779 tmp->alreadygone = 1; 00780 if (tmp->owner) 00781 ast_queue_hangup(tmp->owner); 00782 } else 00783 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00784 gtalk_response(client, from, pak, NULL, NULL); 00785 return 1; 00786 }
static int gtalk_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 1468 of file chan_gtalk.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), and LOG_NOTICE.
01469 { 01470 int res = 0; 01471 01472 switch (condition) { 01473 case AST_CONTROL_HOLD: 01474 ast_moh_start(ast, data, NULL); 01475 break; 01476 case AST_CONTROL_UNHOLD: 01477 ast_moh_stop(ast); 01478 break; 01479 default: 01480 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition); 01481 res = -1; 01482 } 01483 01484 return res; 01485 }
static int gtalk_invite | ( | struct gtalk_pvt * | p, | |
char * | to, | |||
char * | from, | |||
char * | sid, | |||
int | initiator | |||
) | [static] |
Definition at line 406 of file chan_gtalk.c.
References add_codec_to_answer(), ast_aji_increment_mid(), ast_codec_pref_index(), ast_log(), gtalk::capability, gtalk::connection, LOG_ERROR, aji_client::mid, aji_client::p, gtalk::p, gtalk_pvt::parent, and gtalk::prefs.
Referenced by gtalk_answer(), and gtalk_call().
00407 { 00408 struct gtalk *client = p->parent; 00409 iks *iq, *gtalk, *dcodecs, *payload_telephone, *transport; 00410 int x; 00411 int pref_codec = 0; 00412 int alreadysent = 0; 00413 int codecs_num = 0; 00414 00415 iq = iks_new("iq"); 00416 gtalk = iks_new("session"); 00417 dcodecs = iks_new("description"); 00418 transport = iks_new("transport"); 00419 payload_telephone = iks_new("payload-type"); 00420 if (!(iq && gtalk && dcodecs && transport && payload_telephone)){ 00421 if(iq) 00422 iks_delete(iq); 00423 if(gtalk) 00424 iks_delete(gtalk); 00425 if(dcodecs) 00426 iks_delete(dcodecs); 00427 if(transport) 00428 iks_delete(transport); 00429 if(payload_telephone) 00430 iks_delete(payload_telephone); 00431 00432 ast_log(LOG_ERROR, "Could not allocate iksemel nodes\n"); 00433 return 0; 00434 } 00435 iks_insert_attrib(dcodecs, "xmlns", "http://www.google.com/session/phone"); 00436 iks_insert_attrib(dcodecs, "xml:lang", "en"); 00437 00438 for (x = 0; x < 32; x++) { 00439 if (!(pref_codec = ast_codec_pref_index(&client->prefs, x))) 00440 break; 00441 if (!(client->capability & pref_codec)) 00442 continue; 00443 if (alreadysent & pref_codec) 00444 continue; 00445 codecs_num = add_codec_to_answer(p, pref_codec, dcodecs); 00446 alreadysent |= pref_codec; 00447 } 00448 00449 if (codecs_num) { 00450 /* only propose DTMF within an audio session */ 00451 iks_insert_attrib(payload_telephone, "id", "106"); 00452 iks_insert_attrib(payload_telephone, "name", "telephone-event"); 00453 iks_insert_attrib(payload_telephone, "clockrate", "8000"); 00454 } 00455 iks_insert_attrib(transport,"xmlns","http://www.google.com/transport/p2p"); 00456 00457 iks_insert_attrib(iq, "type", "set"); 00458 iks_insert_attrib(iq, "to", to); 00459 iks_insert_attrib(iq, "from", from); 00460 iks_insert_attrib(iq, "id", client->connection->mid); 00461 ast_aji_increment_mid(client->connection->mid); 00462 00463 iks_insert_attrib(gtalk, "xmlns", "http://www.google.com/session"); 00464 iks_insert_attrib(gtalk, "type",initiator ? "initiate": "accept"); 00465 iks_insert_attrib(gtalk, "initiator", initiator ? from : to); 00466 iks_insert_attrib(gtalk, "id", sid); 00467 iks_insert_node(iq, gtalk); 00468 iks_insert_node(gtalk, dcodecs); 00469 iks_insert_node(gtalk, transport); 00470 iks_insert_node(dcodecs, payload_telephone); 00471 00472 iks_send(client->connection->p, iq); 00473 iks_delete(payload_telephone); 00474 iks_delete(transport); 00475 iks_delete(dcodecs); 00476 iks_delete(gtalk); 00477 iks_delete(iq); 00478 return 1; 00479 }
static int gtalk_invite_response | ( | struct gtalk_pvt * | p, | |
char * | to, | |||
char * | from, | |||
char * | sid, | |||
int | initiator | |||
) | [static] |
Definition at line 481 of file chan_gtalk.c.
References ast_aji_increment_mid(), ast_log(), gtalk::connection, LOG_ERROR, aji_client::mid, aji_client::p, gtalk::p, and gtalk_pvt::parent.
Referenced by gtalk_newcall().
00482 { 00483 iks *iq, *session, *transport; 00484 iq = iks_new("iq"); 00485 session = iks_new("session"); 00486 transport = iks_new("transport"); 00487 if(!(iq && session && transport)) { 00488 if(iq) 00489 iks_delete(iq); 00490 if(session) 00491 iks_delete(session); 00492 if(transport) 00493 iks_delete(transport); 00494 ast_log(LOG_ERROR, " Unable to allocate IKS node\n"); 00495 return -1; 00496 } 00497 iks_insert_attrib(iq, "from", from); 00498 iks_insert_attrib(iq, "to", to); 00499 iks_insert_attrib(iq, "type", "set"); 00500 iks_insert_attrib(iq, "id",p->parent->connection->mid); 00501 ast_aji_increment_mid(p->parent->connection->mid); 00502 iks_insert_attrib(session, "type", "transport-accept"); 00503 iks_insert_attrib(session, "id", sid); 00504 iks_insert_attrib(session, "initiator", initiator ? from : to); 00505 iks_insert_attrib(session, "xmlns", "http://www.google.com/session"); 00506 iks_insert_attrib(transport, "xmlns", "http://www.google.com/transport/p2p"); 00507 iks_insert_node(iq,session); 00508 iks_insert_node(session,transport); 00509 iks_send(p->parent->connection->p, iq); 00510 iks_delete(transport); 00511 iks_delete(session); 00512 iks_delete(iq); 00513 return 1; 00514 00515 }
static int gtalk_is_accepted | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 671 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().
00672 { 00673 struct gtalk_pvt *tmp; 00674 char *from; 00675 00676 ast_log(LOG_DEBUG, "The client is %s\n", client->name); 00677 /* find corresponding call */ 00678 for (tmp = client->p; tmp; tmp = tmp->next) { 00679 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) 00680 break; 00681 } 00682 00683 from = iks_find_attrib(pak->x, "to"); 00684 if(!from) 00685 from = client->connection->jid->full; 00686 00687 if (!tmp) 00688 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00689 00690 /* answer 'iq' packet to let the remote peer know that we're alive */ 00691 gtalk_response(client, from, pak, NULL, NULL); 00692 return 1; 00693 }
static int gtalk_is_answered | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 618 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().
00619 { 00620 struct gtalk_pvt *tmp; 00621 char *from; 00622 iks *codec; 00623 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ]; 00624 int peernoncodeccapability; 00625 00626 ast_log(LOG_DEBUG, "The client is %s\n", client->name); 00627 /* Make sure our new call doesn't exist yet */ 00628 for (tmp = client->p; tmp; tmp = tmp->next) { 00629 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) 00630 break; 00631 } 00632 00633 /* codec points to the first <payload-type/> tag */ 00634 codec = iks_child(iks_child(iks_child(pak->x))); 00635 while (codec) { 00636 ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id"))); 00637 ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); 00638 codec = iks_next(codec); 00639 } 00640 00641 /* Now gather all of the codecs that we are asked for */ 00642 ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability); 00643 00644 /* at this point, we received an awser from the remote Gtalk client, 00645 which allows us to compare capabilities */ 00646 tmp->jointcapability = tmp->capability & tmp->peercapability; 00647 if (!tmp->jointcapability) { 00648 ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->capability), 00649 ast_getformatname_multiple(s2, BUFSIZ, tmp->peercapability), 00650 ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcapability)); 00651 /* close session if capabilities don't match */ 00652 ast_queue_hangup(tmp->owner); 00653 00654 return -1; 00655 00656 } 00657 00658 from = iks_find_attrib(pak->x, "to"); 00659 if(!from) 00660 from = client->connection->jid->full; 00661 00662 if (tmp) { 00663 if (tmp->owner) 00664 ast_queue_control(tmp->owner, AST_CONTROL_ANSWER); 00665 } else 00666 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00667 gtalk_response(client, from, pak, NULL, NULL); 00668 return 1; 00669 }
static int gtalk_load_config | ( | void | ) | [static] |
Definition at line 1856 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, context, default_jbconf, global_capability, global_jbconf, GOOGLE_CONFIG, hp, LOG_WARNING, prefs, and var.
Referenced by load_module().
01857 { 01858 char *cat = NULL; 01859 struct ast_config *cfg = NULL; 01860 char context[AST_MAX_CONTEXT]; 01861 int allowguest = 1; 01862 struct ast_variable *var; 01863 struct gtalk *member; 01864 struct ast_codec_pref prefs; 01865 struct aji_client_container *clients; 01866 struct gtalk_candidate *global_candidates = NULL; 01867 struct hostent *hp; 01868 struct ast_hostent ahp; 01869 01870 cfg = ast_config_load(GOOGLE_CONFIG); 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, "bindaddr")) { 01893 if (!(hp = ast_gethostbyname(var->value, &ahp))) { 01894 ast_log(LOG_WARNING, "Invalid address: %s\n", var->value); 01895 } else { 01896 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 01897 } 01898 } 01899 /* Idea to allow for custom candidates */ 01900 /* 01901 else if (!strcasecmp(var->name, "candidate")) { 01902 candidate = gtalk_create_candidate(var->value); 01903 if (candidate) { 01904 candidate->next = global_candidates; 01905 global_candidates = candidate; 01906 } 01907 } 01908 */ 01909 } 01910 while (cat) { 01911 if (strcasecmp(cat, "general")) { 01912 var = ast_variable_browse(cfg, cat); 01913 member = (struct gtalk *) malloc(sizeof(struct gtalk)); 01914 memset(member, 0, sizeof(struct gtalk)); 01915 ASTOBJ_INIT(member); 01916 ASTOBJ_WRLOCK(member); 01917 if (!strcasecmp(cat, "guest")) { 01918 ast_copy_string(member->name, "guest", sizeof(member->name)); 01919 ast_copy_string(member->user, "guest", sizeof(member->user)); 01920 ast_copy_string(member->context, context, sizeof(member->context)); 01921 member->allowguest = allowguest; 01922 member->prefs = prefs; 01923 while (var) { 01924 if (!strcasecmp(var->name, "disallow")) 01925 ast_parse_allow_disallow(&member->prefs, &member->capability, 01926 var->value, 0); 01927 else if (!strcasecmp(var->name, "allow")) 01928 ast_parse_allow_disallow(&member->prefs, &member->capability, 01929 var->value, 1); 01930 else if (!strcasecmp(var->name, "context")) 01931 ast_copy_string(member->context, var->value, 01932 sizeof(member->context)); 01933 /* Idea to allow for custom candidates */ 01934 /* 01935 else if (!strcasecmp(var->name, "candidate")) { 01936 candidate = gtalk_create_candidate(var->value); 01937 if (candidate) { 01938 candidate->next = member->ourcandidates; 01939 member->ourcandidates = candidate; 01940 } 01941 } 01942 */ 01943 var = var->next; 01944 } 01945 ASTOBJ_UNLOCK(member); 01946 clients = ast_aji_get_clients(); 01947 if (clients) { 01948 ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { 01949 ASTOBJ_WRLOCK(iterator); 01950 ASTOBJ_WRLOCK(member); 01951 member->connection = NULL; 01952 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); 01953 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); 01954 ASTOBJ_UNLOCK(member); 01955 ASTOBJ_UNLOCK(iterator); 01956 }); 01957 ASTOBJ_CONTAINER_LINK(>alk_list, member); 01958 ASTOBJ_UNREF(member, gtalk_member_destroy); 01959 } else { 01960 ASTOBJ_UNLOCK(member); 01961 ASTOBJ_UNREF(member, gtalk_member_destroy); 01962 } 01963 } else { 01964 ASTOBJ_UNLOCK(member); 01965 if (gtalk_create_member(cat, var, allowguest, prefs, context, member)) 01966 ASTOBJ_CONTAINER_LINK(>alk_list, member); 01967 ASTOBJ_UNREF(member, gtalk_member_destroy); 01968 } 01969 } 01970 cat = ast_category_browse(cfg, cat); 01971 } 01972 gtalk_free_candidates(global_candidates); 01973 return 1; 01974 }
static void gtalk_member_destroy | ( | struct gtalk * | obj | ) | [static] |
Definition at line 260 of file chan_gtalk.c.
References free.
Referenced by gtalk_parser(), gtalk_request(), and unload_module().
00261 { 00262 free(obj); 00263 }
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 994 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_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_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, ast_channel::exten, gtalk_pvt::exten, ast_channel::fds, global_capability, global_jbconf, gtalk_tech, ast_channel::hangupcause, gtalk_pvt::jointcapability, language, gtalk::language, LOG_WARNING, musicclass, gtalk::musicclass, ast_channel::name, ast_channel::nativeformats, gtalk_pvt::owner, 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, ast_channel::tech, ast_channel::tech_pvt, gtalk_pvt::us, gtalk_pvt::vrtp, and ast_channel::writeformat.
Referenced by gtalk_newcall(), and gtalk_request().
00995 { 00996 struct ast_channel *tmp; 00997 int fmt; 00998 int what; 00999 const char *n2; 01000 01001 if (title) 01002 n2 = title; 01003 else 01004 n2 = i->us; 01005 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); 01006 if (!tmp) { 01007 ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n"); 01008 return NULL; 01009 } 01010 tmp->tech = >alk_tech; 01011 01012 /* Select our native format based on codec preference until we receive 01013 something from another device to the contrary. */ 01014 if (i->jointcapability) 01015 what = i->jointcapability; 01016 else if (i->capability) 01017 what = i->capability; 01018 else 01019 what = global_capability; 01020 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK); 01021 fmt = ast_best_codec(tmp->nativeformats); 01022 01023 if (i->rtp) { 01024 ast_rtp_setstun(i->rtp, 1); 01025 tmp->fds[0] = ast_rtp_fd(i->rtp); 01026 tmp->fds[1] = ast_rtcp_fd(i->rtp); 01027 } 01028 if (i->vrtp) { 01029 ast_rtp_setstun(i->rtp, 1); 01030 tmp->fds[2] = ast_rtp_fd(i->vrtp); 01031 tmp->fds[3] = ast_rtcp_fd(i->vrtp); 01032 } 01033 if (state == AST_STATE_RING) 01034 tmp->rings = 1; 01035 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 01036 tmp->writeformat = fmt; 01037 tmp->rawwriteformat = fmt; 01038 tmp->readformat = fmt; 01039 tmp->rawreadformat = fmt; 01040 tmp->tech_pvt = i; 01041 01042 tmp->callgroup = client->callgroup; 01043 tmp->pickupgroup = client->pickupgroup; 01044 tmp->cid.cid_pres = client->callingpres; 01045 if (!ast_strlen_zero(client->accountcode)) 01046 ast_string_field_set(tmp, accountcode, client->accountcode); 01047 if (client->amaflags) 01048 tmp->amaflags = client->amaflags; 01049 if (!ast_strlen_zero(client->language)) 01050 ast_string_field_set(tmp, language, client->language); 01051 if (!ast_strlen_zero(client->musicclass)) 01052 ast_string_field_set(tmp, musicclass, client->musicclass); 01053 i->owner = tmp; 01054 ast_module_ref(ast_module_info->self); 01055 ast_copy_string(tmp->context, client->context, sizeof(tmp->context)); 01056 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 01057 01058 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) 01059 tmp->cid.cid_dnid = ast_strdup(i->exten); 01060 tmp->priority = 1; 01061 if (i->rtp) 01062 ast_jb_configure(tmp, &global_jbconf); 01063 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 01064 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 01065 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 01066 ast_hangup(tmp); 01067 tmp = NULL; 01068 } 01069 01070 return tmp; 01071 }
static int gtalk_newcall | ( | struct gtalk * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1139 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, 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().
01140 { 01141 struct gtalk_pvt *p, *tmp = client->p; 01142 struct ast_channel *chan; 01143 int res; 01144 iks *codec; 01145 char *from = NULL; 01146 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ]; 01147 int peernoncodeccapability; 01148 01149 /* Make sure our new call doesn't exist yet */ 01150 from = iks_find_attrib(pak->x,"to"); 01151 if(!from) 01152 from = client->connection->jid->full; 01153 01154 while (tmp) { 01155 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) { 01156 ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid); 01157 gtalk_response(client, from, pak, "out-of-order", NULL); 01158 return -1; 01159 } 01160 tmp = tmp->next; 01161 } 01162 01163 if (!strcasecmp(client->name, "guest")){ 01164 /* the guest account is not tied to any configured XMPP client, 01165 let's set it now */ 01166 client->connection = ast_aji_get_client(from); 01167 if (!client->connection) { 01168 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); 01169 return -1; 01170 } 01171 } 01172 01173 p = gtalk_alloc(client, from, pak->from->full, iks_find_attrib(pak->query, "id")); 01174 if (!p) { 01175 ast_log(LOG_WARNING, "Unable to allocate gtalk structure!\n"); 01176 return -1; 01177 } 01178 01179 chan = gtalk_new(client, p, AST_STATE_DOWN, pak->from->user); 01180 if (!chan) { 01181 gtalk_free_pvt(client, p); 01182 return -1; 01183 } 01184 01185 ast_mutex_lock(&p->lock); 01186 ast_copy_string(p->them, pak->from->full, sizeof(p->them)); 01187 if (iks_find_attrib(pak->query, "id")) { 01188 ast_copy_string(p->sid, iks_find_attrib(pak->query, "id"), 01189 sizeof(p->sid)); 01190 } 01191 01192 /* codec points to the first <payload-type/> tag */ 01193 codec = iks_child(iks_child(iks_child(pak->x))); 01194 01195 while (codec) { 01196 ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id"))); 01197 ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); 01198 codec = iks_next(codec); 01199 } 01200 01201 /* Now gather all of the codecs that we are asked for */ 01202 ast_rtp_get_current_formats(p->rtp, &p->peercapability, &peernoncodeccapability); 01203 p->jointcapability = p->capability & p->peercapability; 01204 ast_mutex_unlock(&p->lock); 01205 01206 ast_setstate(chan, AST_STATE_RING); 01207 if (!p->jointcapability) { 01208 ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->capability), 01209 ast_getformatname_multiple(s2, BUFSIZ, p->peercapability), 01210 ast_getformatname_multiple(s3, BUFSIZ, p->jointcapability)); 01211 /* close session if capabilities don't match */ 01212 gtalk_action(client, p, "reject"); 01213 p->alreadygone = 1; 01214 gtalk_hangup(chan); 01215 ast_channel_free(chan); 01216 return -1; 01217 } 01218 01219 res = ast_pbx_start(chan); 01220 01221 switch (res) { 01222 case AST_PBX_FAILED: 01223 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 01224 gtalk_response(client, from, pak, "service-unavailable", NULL); 01225 break; 01226 case AST_PBX_CALL_LIMIT: 01227 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 01228 gtalk_response(client, from, pak, "service-unavailable", NULL); 01229 break; 01230 case AST_PBX_SUCCESS: 01231 gtalk_response(client, from, pak, NULL, NULL); 01232 gtalk_invite_response(p, p->them, p->us,p->sid, 0); 01233 gtalk_create_candidates(client, p, p->sid, p->them, p->us); 01234 /* nothing to do */ 01235 break; 01236 } 01237 01238 return 1; 01239 }
static int gtalk_parser | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1721 of file chan_gtalk.c.
References 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(), LOG_DEBUG, and option_debug.
Referenced by gtalk_create_member().
01722 { 01723 struct gtalk *client = ASTOBJ_REF((struct gtalk *) data); 01724 01725 if (iks_find_with_attrib(pak->x, "session", "type", "initiate")) { 01726 /* New call */ 01727 gtalk_newcall(client, pak); 01728 } else if (iks_find_with_attrib(pak->x, "session", "type", "candidates") || iks_find_with_attrib(pak->x, "session", "type", "transport-info")) { 01729 if (option_debug > 2) 01730 ast_log(LOG_DEBUG, "About to add candidate!\n"); 01731 gtalk_add_candidate(client, pak); 01732 if (option_debug > 2) 01733 ast_log(LOG_DEBUG, "Candidate Added!\n"); 01734 } else if (iks_find_with_attrib(pak->x, "session", "type", "accept")) { 01735 gtalk_is_answered(client, pak); 01736 } else if (iks_find_with_attrib(pak->x, "session", "type", "transport-accept")) { 01737 gtalk_is_accepted(client, pak); 01738 } else if (iks_find_with_attrib(pak->x, "session", "type", "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) { 01739 gtalk_handle_dtmf(client, pak); 01740 } else if (iks_find_with_attrib(pak->x, "session", "type", "terminate")) { 01741 gtalk_hangup_farend(client, pak); 01742 } else if (iks_find_with_attrib(pak->x, "session", "type", "reject")) { 01743 gtalk_hangup_farend(client, pak); 01744 } 01745 ASTOBJ_UNREF(client, gtalk_member_destroy); 01746 return IKS_FILTER_EAT; 01747 }
static struct ast_frame * gtalk_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1398 of file chan_gtalk.c.
References ast_mutex_lock(), ast_mutex_unlock(), gtalk_rtp_read(), gtalk_pvt::lock, and ast_channel::tech_pvt.
01399 { 01400 struct ast_frame *fr; 01401 struct gtalk_pvt *p = ast->tech_pvt; 01402 01403 ast_mutex_lock(&p->lock); 01404 fr = gtalk_rtp_read(ast, p); 01405 ast_mutex_unlock(&p->lock); 01406 return fr; 01407 }
static struct ast_channel * gtalk_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Part of PBX interface.
Definition at line 1616 of file chan_gtalk.c.
References ast_aji_get_client(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, gtalk::connection, find_gtalk(), gtalk_alloc(), gtalk_member_destroy(), gtalk_new(), aji_client::jid, LOG_ERROR, LOG_WARNING, gtalk::name, s, and gtalk::user.
01617 { 01618 struct gtalk_pvt *p = NULL; 01619 struct gtalk *client = NULL; 01620 char *sender = NULL, *to = NULL, *s = NULL; 01621 struct ast_channel *chan = NULL; 01622 01623 if (data) { 01624 s = ast_strdupa(data); 01625 if (s) { 01626 sender = strsep(&s, "/"); 01627 if (sender && (sender[0] != '\0')) 01628 to = strsep(&s, "/"); 01629 if (!to) { 01630 ast_log(LOG_ERROR, "Bad arguments in Gtalk Dialstring: %s\n", (char*) data); 01631 return NULL; 01632 } 01633 } 01634 } 01635 01636 client = find_gtalk(to, sender); 01637 if (!client) { 01638 ast_log(LOG_WARNING, "Could not find recipient.\n"); 01639 return NULL; 01640 } 01641 if (!strcasecmp(client->name, "guest")){ 01642 /* the guest account is not tied to any configured XMPP client, 01643 let's set it now */ 01644 client->connection = ast_aji_get_client(sender); 01645 if (!client->connection) { 01646 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender); 01647 ASTOBJ_UNREF(client, gtalk_member_destroy); 01648 return NULL; 01649 } 01650 } 01651 01652 ASTOBJ_WRLOCK(client); 01653 p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL); 01654 if (p) 01655 chan = gtalk_new(client, p, AST_STATE_DOWN, to); 01656 01657 ASTOBJ_UNLOCK(client); 01658 return chan; 01659 }
static int gtalk_response | ( | struct gtalk * | client, | |
char * | from, | |||
ikspak * | pak, | |||
const char * | reasonstr, | |||
const char * | reasonstr2 | |||
) | [static] |
Definition at line 586 of file chan_gtalk.c.
References gtalk::connection, and aji_client::p.
Referenced by gtalk_handle_dtmf(), gtalk_hangup_farend(), gtalk_is_accepted(), gtalk_is_answered(), and gtalk_newcall().
00587 { 00588 iks *response = NULL, *error = NULL, *reason = NULL; 00589 int res = -1; 00590 00591 response = iks_new("iq"); 00592 if (response) { 00593 iks_insert_attrib(response, "type", "result"); 00594 iks_insert_attrib(response, "from", from); 00595 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from")); 00596 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id")); 00597 if (reasonstr) { 00598 error = iks_new("error"); 00599 if (error) { 00600 iks_insert_attrib(error, "type", "cancel"); 00601 reason = iks_new(reasonstr); 00602 if (reason) 00603 iks_insert_node(error, reason); 00604 iks_insert_node(response, error); 00605 } 00606 } 00607 iks_send(client->connection->p, response); 00608 if (reason) 00609 iks_delete(reason); 00610 if (error) 00611 iks_delete(error); 00612 iks_delete(response); 00613 res = 0; 00614 } 00615 return res; 00616 }
static int gtalk_ringing_ack | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 517 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().
00518 { 00519 struct gtalk_pvt *p = data; 00520 00521 if (p->ringrule) 00522 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 00523 p->ringrule = NULL; 00524 if (p->owner) 00525 ast_queue_control(p->owner, AST_CONTROL_RINGING); 00526 return IKS_FILTER_EAT; 00527 }
static struct ast_frame* gtalk_rtp_read | ( | struct ast_channel * | ast, | |
struct gtalk_pvt * | p | |||
) | [static] |
Definition at line 1369 of file chan_gtalk.c.
References AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_VOICE, ast_log(), ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), f, gtalk_update_stun(), LOG_DEBUG, ast_channel::nativeformats, option_debug, gtalk_pvt::owner, gtalk_pvt::parent, ast_channel::readformat, gtalk_pvt::rtp, and ast_channel::writeformat.
Referenced by gtalk_read().
01370 { 01371 struct ast_frame *f; 01372 01373 if (!p->rtp) 01374 return &ast_null_frame; 01375 f = ast_rtp_read(p->rtp); 01376 gtalk_update_stun(p->parent, p); 01377 if (p->owner) { 01378 /* We already hold the channel lock */ 01379 if (f->frametype == AST_FRAME_VOICE) { 01380 if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { 01381 if (option_debug) 01382 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass); 01383 p->owner->nativeformats = 01384 (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass; 01385 ast_set_read_format(p->owner, p->owner->readformat); 01386 ast_set_write_format(p->owner, p->owner->writeformat); 01387 } 01388 /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { 01389 f = ast_dsp_process(p->owner, p->vad, f); 01390 if (option_debug && f && (f->frametype == AST_FRAME_DTMF)) 01391 ast_log(LOG_DEBUG, "* Detected inband DTMF '%c'\n", f->subclass); 01392 } */ 01393 } 01394 } 01395 return f; 01396 }
static int gtalk_sendhtml | ( | struct ast_channel * | ast, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 1545 of file chan_gtalk.c.
References ast_log(), and LOG_NOTICE.
01546 { 01547 ast_log(LOG_NOTICE, "XXX Implement gtalk sendhtml XXX\n"); 01548 01549 return -1; 01550 }
static int gtalk_set_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
struct ast_rtp * | vrtp, | |||
int | codecs, | |||
int | nat_active | |||
) | [static] |
Definition at line 566 of file chan_gtalk.c.
References ast_mutex_lock(), ast_mutex_unlock(), gtalk_pvt::lock, and ast_channel::tech_pvt.
00567 { 00568 struct gtalk_pvt *p; 00569 00570 p = chan->tech_pvt; 00571 if (!p) 00572 return -1; 00573 ast_mutex_lock(&p->lock); 00574 00575 /* if (rtp) 00576 ast_rtp_get_peer(rtp, &p->redirip); 00577 else 00578 memset(&p->redirip, 0, sizeof(p->redirip)); 00579 p->redircodecs = codecs; */ 00580 00581 /* Reset lastrtprx timer */ 00582 ast_mutex_unlock(&p->lock); 00583 return 0; 00584 }
static int gtalk_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
CLI command "gtalk show channels".
Definition at line 1662 of file chan_gtalk.c.
References AJI_MAX_JIDLEN, ast_cli(), ast_copy_string(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, FORMAT, gtalk_list, gtalklock, LOG_WARNING, ast_channel::name, gtalk_pvt::next, gtalk_pvt::owner, ast_channel::readformat, RESULT_SHOWUSAGE, RESULT_SUCCESS, gtalk_pvt::them, and ast_channel::writeformat.
01663 { 01664 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" 01665 struct gtalk_pvt *p; 01666 struct ast_channel *chan; 01667 int numchans = 0; 01668 char them[AJI_MAX_JIDLEN]; 01669 char *jid = NULL; 01670 char *resource = NULL; 01671 01672 if (argc != 3) 01673 return RESULT_SHOWUSAGE; 01674 01675 ast_mutex_lock(>alklock); 01676 ast_cli(fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); 01677 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { 01678 ASTOBJ_WRLOCK(iterator); 01679 p = iterator->p; 01680 while(p) { 01681 chan = p->owner; 01682 ast_copy_string(them, p->them, sizeof(them)); 01683 jid = them; 01684 resource = strchr(them, '/'); 01685 if (!resource) 01686 resource = "None"; 01687 else { 01688 *resource = '\0'; 01689 resource ++; 01690 } 01691 if (chan) 01692 ast_cli(fd, FORMAT, 01693 chan->name, 01694 jid, 01695 resource, 01696 ast_getformatname(chan->readformat), 01697 ast_getformatname(chan->writeformat) 01698 ); 01699 else 01700 ast_log(LOG_WARNING, "No available channel\n"); 01701 numchans ++; 01702 p = p->next; 01703 } 01704 ASTOBJ_UNLOCK(iterator); 01705 }); 01706 01707 ast_mutex_unlock(>alklock); 01708 01709 ast_cli(fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : ""); 01710 return RESULT_SUCCESS; 01711 #undef FORMAT 01712 }
Definition at line 1241 of file chan_gtalk.c.
References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_stun_request(), hp, gtalk_candidate::ip, gtalk_pvt::laststun, LOG_DEBUG, gtalk_candidate::next, option_debug, gtalk_pvt::ourcandidates, gtalk_candidate::port, gtalk_pvt::rtp, gtalk_pvt::theircandidates, gtalk_candidate::username, and username.
Referenced by gtalk_add_candidate(), and gtalk_rtp_read().
01242 { 01243 struct gtalk_candidate *tmp; 01244 struct hostent *hp; 01245 struct ast_hostent ahp; 01246 struct sockaddr_in sin; 01247 struct sockaddr_in aux; 01248 01249 if (time(NULL) == p->laststun) 01250 return 0; 01251 01252 tmp = p->theircandidates; 01253 p->laststun = time(NULL); 01254 while (tmp) { 01255 char username[256]; 01256 01257 /* Find the IP address of the host */ 01258 hp = ast_gethostbyname(tmp->ip, &ahp); 01259 sin.sin_family = AF_INET; 01260 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01261 sin.sin_port = htons(tmp->port); 01262 snprintf(username, sizeof(username), "%s%s", tmp->username, 01263 p->ourcandidates->username); 01264 01265 /* Find out the result of the STUN */ 01266 ast_rtp_get_peer(p->rtp, &aux); 01267 01268 /* If the STUN result is different from the IP of the hostname, 01269 lock on the stun IP of the hostname advertised by the 01270 remote client */ 01271 if (aux.sin_addr.s_addr && 01272 aux.sin_addr.s_addr != sin.sin_addr.s_addr) 01273 ast_rtp_stun_request(p->rtp, &aux, username); 01274 else 01275 ast_rtp_stun_request(p->rtp, &sin, username); 01276 01277 if (aux.sin_addr.s_addr && option_debug > 3) { 01278 ast_log(LOG_DEBUG, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip); 01279 ast_log(LOG_DEBUG, "Sending STUN request to %s\n", tmp->ip); 01280 } 01281 01282 tmp = tmp->next; 01283 } 01284 return 1; 01285 }
static int gtalk_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Send frame to media channel (rtp).
Definition at line 1410 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.
01411 { 01412 struct gtalk_pvt *p = ast->tech_pvt; 01413 int res = 0; 01414 01415 switch (frame->frametype) { 01416 case AST_FRAME_VOICE: 01417 if (!(frame->subclass & ast->nativeformats)) { 01418 ast_log(LOG_WARNING, 01419 "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", 01420 frame->subclass, ast->nativeformats, ast->readformat, 01421 ast->writeformat); 01422 return 0; 01423 } 01424 if (p) { 01425 ast_mutex_lock(&p->lock); 01426 if (p->rtp) { 01427 res = ast_rtp_write(p->rtp, frame); 01428 } 01429 ast_mutex_unlock(&p->lock); 01430 } 01431 break; 01432 case AST_FRAME_VIDEO: 01433 if (p) { 01434 ast_mutex_lock(&p->lock); 01435 if (p->vrtp) { 01436 res = ast_rtp_write(p->vrtp, frame); 01437 } 01438 ast_mutex_unlock(&p->lock); 01439 } 01440 break; 01441 case AST_FRAME_IMAGE: 01442 return 0; 01443 break; 01444 default: 01445 ast_log(LOG_WARNING, "Can't send %d type frames with Gtalk write\n", 01446 frame->frametype); 01447 return 0; 01448 } 01449 01450 return res; 01451 }
static int load_module | ( | void | ) | [static] |
Load module into PBX, register channel.
Definition at line 1977 of file chan_gtalk.c.
References __ourip, 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.
01978 { 01979 char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); 01980 free(jabber_loaded); 01981 if (!jabber_loaded) { 01982 /* If embedded, check for a different module name */ 01983 jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0); 01984 free(jabber_loaded); 01985 if (!jabber_loaded) { 01986 ast_log(LOG_ERROR, "chan_gtalk.so depends upon res_jabber.so\n"); 01987 return AST_MODULE_LOAD_DECLINE; 01988 } 01989 } 01990 01991 #ifdef HAVE_GNUTLS 01992 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); 01993 #endif /* HAVE_GNUTLS */ 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, sizeof(gtalk_cli) / sizeof(gtalk_cli[0])); 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 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, sizeof(gtalk_cli) / sizeof(gtalk_cli[0])); 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 | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .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 229 of file chan_gtalk.c.
const 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 225 of file chan_gtalk.c.
Referenced by gtalk_alloc(), gtalk_create_candidates(), gtalk_load_config(), load_module(), reload_config(), sip_alloc(), sip_show_settings(), start_rtp(), and transmit_register().
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 89 of file chan_gtalk.c.
const char desc[] = "Gtalk Channel" [static] |
Definition at line 173 of file chan_gtalk.c.
Referenced by ast_cause2str(), ast_codec2str(), load_rpt_vars(), misdn_cfg_get_desc(), and show_config_description().
char externip[16] [static] |
Definition at line 55 of file chan_gtalk.c.
int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 [static] |
Definition at line 175 of file chan_gtalk.c.
Referenced by gtalk_alloc(), gtalk_load_config(), and gtalk_new().
struct ast_jb_conf global_jbconf [static] |
Definition at line 96 of file chan_gtalk.c.
struct ast_cli_entry gtalk_cli[] [static] |
Initial value:
{ {{ "gtalk", "reload", NULL}, gtalk_do_reload, "Reload GoogleTalk configuration", reload_usage }, {{ "gtalk", "show", "channels", NULL}, gtalk_show_channels, "Show GoogleTalk channels", show_channels_usage }, }
Definition at line 249 of file chan_gtalk.c.
Referenced by load_module(), and unload_module().
struct gtalk_container gtalk_list [static] |
Definition at line 258 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 233 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 205 of file chan_gtalk.c.
Referenced by gtalk_new(), load_module(), and unload_module().
ast_mutex_t gtalklock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the interface list (of gtalk_pvt's)
Definition at line 177 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 228 of file chan_gtalk.c.
Referenced by __oh323_rtp_create(), ast_expr(), ast_rtp_new(), ast_udptl_new(), ast_udptl_new_with_bindaddr(), do_monitor(), gtalk_alloc(), load_module(), network_thread(), peer_set_srcaddr(), reload(), reload_config(), set_config(), sip_alloc(), siptcpsock_accept(), start_rtp(), and unload_module().
char reload_usage[] [static] |
Initial value:
"Usage: gtalk reload\n" " Reload gtalk channel driver.\n"
Definition at line 244 of file chan_gtalk.c.
struct sched_context* sched [static] |
The scheduling context
Definition at line 227 of file chan_gtalk.c.
char show_channels_usage[] [static] |
Initial value:
"Usage: gtalk show channels\n" " Shows current state of the Gtalk channels.\n"
Definition at line 240 of file chan_gtalk.c.