📄 chan_gtalk.c
字号:
ASTOBJ_UNLOCK(client); return chan;}/*! \brief CLI command "gtalk show channels" */static int gtalk_show_channels(int fd, int argc, char **argv){#define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" struct gtalk_pvt *p; struct ast_channel *chan; int numchans = 0; char them[AJI_MAX_JIDLEN]; char *jid = NULL; char *resource = NULL; if (argc != 3) return RESULT_SHOWUSAGE; ast_mutex_lock(>alklock); ast_cli(fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { ASTOBJ_WRLOCK(iterator); p = iterator->p; while(p) { chan = p->owner; ast_copy_string(them, p->them, sizeof(them)); jid = them; resource = strchr(them, '/'); if (!resource) resource = "None"; else { *resource = '\0'; resource ++; } if (chan) ast_cli(fd, FORMAT, chan->name, jid, resource, ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat) ); else ast_log(LOG_WARNING, "No available channel\n"); numchans ++; p = p->next; } ASTOBJ_UNLOCK(iterator); }); ast_mutex_unlock(>alklock); ast_cli(fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : ""); return RESULT_SUCCESS;#undef FORMAT}/*! \brief CLI command "gtalk show channels" */static int gtalk_do_reload(int fd, int argc, char **argv){ ast_verbose("IT DOES WORK!\n"); return RESULT_SUCCESS;}static int gtalk_parser(void *data, ikspak *pak){ struct gtalk *client = ASTOBJ_REF((struct gtalk *) data); if (iks_find_with_attrib(pak->x, "session", "type", "initiate")) { /* New call */ gtalk_newcall(client, pak); } else if (iks_find_with_attrib(pak->x, "session", "type", "candidates") || iks_find_with_attrib(pak->x, "session", "type", "transport-info")) { if (option_debug > 2) ast_log(LOG_DEBUG, "About to add candidate!\n"); gtalk_add_candidate(client, pak); if (option_debug > 2) ast_log(LOG_DEBUG, "Candidate Added!\n"); } else if (iks_find_with_attrib(pak->x, "session", "type", "accept")) { gtalk_is_answered(client, pak); } else if (iks_find_with_attrib(pak->x, "session", "type", "transport-accept")) { gtalk_is_accepted(client, pak); } else if (iks_find_with_attrib(pak->x, "session", "type", "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) { gtalk_handle_dtmf(client, pak); } else if (iks_find_with_attrib(pak->x, "session", "type", "terminate")) { gtalk_hangup_farend(client, pak); } else if (iks_find_with_attrib(pak->x, "session", "type", "reject")) { gtalk_hangup_farend(client, pak); } ASTOBJ_UNREF(client, gtalk_member_destroy); return IKS_FILTER_EAT;}/* Not using this anymore probably take out soon static struct gtalk_candidate *gtalk_create_candidate(char *args){ char *name, *type, *preference, *protocol; struct gtalk_candidate *res; res = malloc(sizeof(struct gtalk_candidate)); memset(res, 0, sizeof(struct gtalk_candidate)); if (args) name = args; if ((args = strchr(args, ','))) { *args = '\0'; args++; preference = args; } if ((args = strchr(args, ','))) { *args = '\0'; args++; protocol = args; } if ((args = strchr(args, ','))) { *args = '\0'; args++; type = args; } if (name) ast_copy_string(res->name, name, sizeof(res->name)); if (preference) { res->preference = atof(preference); } if (protocol) { if (!strcasecmp("udp", protocol)) res->protocol = AJI_PROTOCOL_UDP; if (!strcasecmp("ssltcp", protocol)) res->protocol = AJI_PROTOCOL_SSLTCP; } if (type) { if (!strcasecmp("stun", type)) res->type = AJI_CONNECT_STUN; if (!strcasecmp("local", type)) res->type = AJI_CONNECT_LOCAL; if (!strcasecmp("relay", type)) res->type = AJI_CONNECT_RELAY; } return res;}*/static int gtalk_create_member(char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct gtalk *member){ struct aji_client *client; if (!member) ast_log(LOG_WARNING, "Out of memory.\n"); ast_copy_string(member->name, label, sizeof(member->name)); ast_copy_string(member->user, label, sizeof(member->user)); ast_copy_string(member->context, context, sizeof(member->context)); member->allowguest = allowguest; member->prefs = prefs; while (var) {#if 0 struct gtalk_candidate *candidate = NULL;#endif if (!strcasecmp(var->name, "username")) ast_copy_string(member->user, var->value, sizeof(member->user)); else if (!strcasecmp(var->name, "disallow")) ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0); else if (!strcasecmp(var->name, "allow")) ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1); else if (!strcasecmp(var->name, "context")) ast_copy_string(member->context, var->value, sizeof(member->context));#if 0 else if (!strcasecmp(var->name, "candidate")) { candidate = gtalk_create_candidate(var->value); if (candidate) { candidate->next = member->ourcandidates; member->ourcandidates = candidate; } }#endif else if (!strcasecmp(var->name, "connection")) { if ((client = ast_aji_get_client(var->value))) { member->connection = client; iks_filter_add_rule(client->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_FROM_PARTIAL, member->user, IKS_RULE_NS, "http://www.google.com/session", IKS_RULE_DONE); } else { ast_log(LOG_ERROR, "connection referenced not found!\n"); return 0; } } var = var->next; } if (member->connection && member->user) member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); else { ast_log(LOG_ERROR, "No Connection or Username!\n"); } return 1;}static int gtalk_load_config(void){ char *cat = NULL; struct ast_config *cfg = NULL; char context[AST_MAX_CONTEXT]; int allowguest = 1; struct ast_variable *var; struct gtalk *member; struct ast_codec_pref prefs; struct aji_client_container *clients; struct gtalk_candidate *global_candidates = NULL; struct hostent *hp; struct ast_hostent ahp; cfg = ast_config_load(GOOGLE_CONFIG); if (!cfg) return 0; /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); cat = ast_category_browse(cfg, NULL); for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { /* handle jb conf */ if (!ast_jb_read_conf(&global_jbconf, var->name, var->value)) continue; if (!strcasecmp(var->name, "allowguest")) allowguest = (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0; else if (!strcasecmp(var->name, "disallow")) ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0); else if (!strcasecmp(var->name, "allow")) ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1); else if (!strcasecmp(var->name, "context")) ast_copy_string(context, var->value, sizeof(context)); else if (!strcasecmp(var->name, "bindaddr")) { if (!(hp = ast_gethostbyname(var->value, &ahp))) { ast_log(LOG_WARNING, "Invalid address: %s\n", var->value); } else { memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); } }/* Idea to allow for custom candidates *//* else if (!strcasecmp(var->name, "candidate")) { candidate = gtalk_create_candidate(var->value); if (candidate) { candidate->next = global_candidates; global_candidates = candidate; } }*/ } while (cat) { if (strcasecmp(cat, "general")) { var = ast_variable_browse(cfg, cat); member = (struct gtalk *) malloc(sizeof(struct gtalk)); memset(member, 0, sizeof(struct gtalk)); ASTOBJ_INIT(member); ASTOBJ_WRLOCK(member); if (!strcasecmp(cat, "guest")) { ast_copy_string(member->name, "guest", sizeof(member->name)); ast_copy_string(member->user, "guest", sizeof(member->user)); ast_copy_string(member->context, context, sizeof(member->context)); member->allowguest = allowguest; member->prefs = prefs; while (var) { if (!strcasecmp(var->name, "disallow")) ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0); else if (!strcasecmp(var->name, "allow")) ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1); else if (!strcasecmp(var->name, "context")) ast_copy_string(member->context, var->value, sizeof(member->context));/* Idea to allow for custom candidates *//* else if (!strcasecmp(var->name, "candidate")) { candidate = gtalk_create_candidate(var->value); if (candidate) { candidate->next = member->ourcandidates; member->ourcandidates = candidate; } }*/ var = var->next; } ASTOBJ_UNLOCK(member); clients = ast_aji_get_clients(); if (clients) { ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { ASTOBJ_WRLOCK(iterator); ASTOBJ_WRLOCK(member); member->connection = NULL; 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); 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); ASTOBJ_UNLOCK(member); ASTOBJ_UNLOCK(iterator); }); ASTOBJ_CONTAINER_LINK(>alk_list, member); ASTOBJ_UNREF(member, gtalk_member_destroy); } else { ASTOBJ_UNLOCK(member); ASTOBJ_UNREF(member, gtalk_member_destroy); } } else { ASTOBJ_UNLOCK(member); if (gtalk_create_member(cat, var, allowguest, prefs, context, member)) ASTOBJ_CONTAINER_LINK(>alk_list, member); ASTOBJ_UNREF(member, gtalk_member_destroy); } } cat = ast_category_browse(cfg, cat); } gtalk_free_candidates(global_candidates); return 1;}/*! \brief Load module into PBX, register channel */static int load_module(void){ char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); free(jabber_loaded); if (!jabber_loaded) { /* If embedded, check for a different module name */ jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0); free(jabber_loaded); if (!jabber_loaded) { ast_log(LOG_ERROR, "chan_gtalk.so depends upon res_jabber.so\n"); return AST_MODULE_LOAD_DECLINE; } }#ifdef HAVE_GNUTLS gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);#endif /* HAVE_GNUTLS */ ASTOBJ_CONTAINER_INIT(>alk_list); if (!gtalk_load_config()) { ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", GOOGLE_CONFIG); return 0; } sched = sched_context_create(); if (!sched) ast_log(LOG_WARNING, "Unable to create schedule context\n"); io = io_context_create(); if (!io) ast_log(LOG_WARNING, "Unable to create I/O context\n"); if (ast_find_ourip(&__ourip, bindaddr)) { ast_log(LOG_WARNING, "Unable to get own IP address, Gtalk disabled\n"); return 0; } ast_rtp_proto_register(>alk_rtp); ast_cli_register_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0])); /* Make sure we can register our channel type */ if (ast_channel_register(>alk_tech)) { ast_log(LOG_ERROR, "Unable to register channel class %s\n", gtalk_tech.type); return -1; } return 0;}/*! \brief Reload module */static int reload(void){ return 0;}/*! \brief Unload the gtalk channel from Asterisk */static int unload_module(void){ struct gtalk_pvt *privates = NULL; ast_cli_unregister_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0])); /* First, take us out of the channel loop */ ast_channel_unregister(>alk_tech); ast_rtp_proto_unregister(>alk_rtp); if (!ast_mutex_lock(>alklock)) { /* Hangup all interfaces if they have an owner */ ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { ASTOBJ_WRLOCK(iterator); privates = iterator->p; while(privates) { if (privates->owner) ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD); privates = privates->next; } iterator->p = NULL; ASTOBJ_UNLOCK(iterator); }); ast_mutex_unlock(>alklock); } else { ast_log(LOG_WARNING, "Unable to lock the monitor\n"); return -1; } ASTOBJ_CONTAINER_DESTROYALL(>alk_list, gtalk_member_destroy); ASTOBJ_CONTAINER_DESTROY(>alk_list); return 0;}AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Gtalk Channel Driver", .load = load_module, .unload = unload_module, .reload = reload, );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -