⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_disco.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, *                    Ryan Eatmon, Robert Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA */#include "sm.h"/** @file sm/mod_disco.c  * @brief service discovery  * @author Robert Norris  * $Date: 2003/11/30 22:02:25 $  * $Revision: 1.28 $  *//** holder for a single service */typedef struct service_st *service_t;struct service_st {    jid_t       jid;    char        name[257];    char        category[257];    char        type[257];    xht         features;};/** all the current disco data */typedef struct disco_st *disco_t;struct disco_st {    /** identity */    char        *category;    char        *type;    char        *name;    /** compatibility */    int         agents;    int         browse;    /** the lists */    xht         dyn;    xht         stat;    /** unified list */    xht         un;    /** cached result packets */    pkt_t       disco_info_result;    pkt_t       disco_items_result;    pkt_t       agents_result;    pkt_t       browse_result;};/** put val into arg */static void _disco_unify_walker(xht list, const char *key, void *val, void *arg) {    service_t svc = (service_t) val;    xht dest = (xht) arg;    /* if its already there, skip this one */    if(xhash_get(dest, jid_full(svc->jid)) != NULL)        return;    log_debug(ZONE, "unify: %s", jid_full(svc->jid));    xhash_put(dest, jid_full(svc->jid), (void *) svc);}/** unify the contest of dyn and stat */static void _disco_unify_lists(disco_t d) {    log_debug(ZONE, "unifying lists");    if(d->un != NULL)        xhash_free(d->un);        d->un = xhash_new(101);    /* dynamic overrieds static */    xhash_walk(d->dyn, _disco_unify_walker, (void *) d->un);    xhash_walk(d->stat, _disco_unify_walker, (void *) d->un);}/** build a disco items result, known services */static pkt_t _disco_items_result(module_t mod, disco_t d) {    pkt_t pkt;    int ns;    service_t svc;    pkt = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);    ns = nad_add_namespace(pkt->nad, uri_DISCO_ITEMS, NULL);    nad_append_elem(pkt->nad, ns, "query", 2);    if(xhash_iter_first(d->un))        do {            xhash_iter_get(d->un, NULL, (void **) &svc);            nad_append_elem(pkt->nad, ns, "item", 3);            nad_append_attr(pkt->nad, -1, "jid", jid_full(svc->jid));            if(svc->name[0] != '\0')                nad_append_attr(pkt->nad, -1, "name", svc->name);        } while(xhash_iter_next(d->un));    return pkt;}/** build a disco info result */static pkt_t _disco_info_result(module_t mod, disco_t d) {    pkt_t pkt;    int ns;    const char *key;    pkt = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);    ns = nad_add_namespace(pkt->nad, uri_DISCO_INFO, NULL);    nad_append_elem(pkt->nad, ns, "query", 2);    /* identity */    nad_append_elem(pkt->nad, ns, "identity", 3);    nad_append_attr(pkt->nad, -1, "category", d->category);    nad_append_attr(pkt->nad, -1, "type", d->type);    nad_append_attr(pkt->nad, -1, "name", d->name);    /* fill in our features */    if(xhash_iter_first(mod->mm->sm->features))        do {            xhash_iter_get(mod->mm->sm->features, &key, NULL);                        nad_append_elem(pkt->nad, ns, "feature", 3);            nad_append_attr(pkt->nad, -1, "var", (char *) key);        } while(xhash_iter_next(mod->mm->sm->features));    return pkt;}/** build an agents result */static pkt_t _disco_agents_result(module_t mod, disco_t d) {    pkt_t pkt;    int ns;    const char *key;    service_t svc;    pkt = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);    ns = nad_add_namespace(pkt->nad, uri_AGENTS, NULL);    nad_append_elem(pkt->nad, ns, "query", 2);    /* fill in the items */    if(xhash_iter_first(d->un))        do {            xhash_iter_get(d->un, &key, (void **) &svc);            nad_append_elem(pkt->nad, ns, "agent", 3);            nad_append_attr(pkt->nad, -1, "jid", jid_full(svc->jid));            if(svc->name[0] != '\0') {                nad_append_elem(pkt->nad, ns, "name", 4);                nad_append_cdata(pkt->nad, svc->name, strlen(svc->name), 5);            }            nad_append_elem(pkt->nad, ns, "service", 4);            nad_append_cdata(pkt->nad, svc->type, strlen(svc->type), 5);            /* map features to the old agent flags */            if(xhash_get(svc->features, uri_REGISTER) != NULL)                nad_append_elem(pkt->nad, ns, "register", 4);            if(xhash_get(svc->features, uri_SEARCH) != NULL)                nad_append_elem(pkt->nad, ns, "search", 4);            if(xhash_get(svc->features, uri_GATEWAY) != NULL)                nad_append_elem(pkt->nad, ns, "transport", 4);            /* conference gets special treatment */            if(strcmp(svc->category, "conference") == 0)                nad_append_elem(pkt->nad, ns, "groupchat", 4);        } while(xhash_iter_next(d->un));    return pkt;}/** build a browse result */static pkt_t _disco_browse_result(module_t mod, disco_t d) {    pkt_t pkt;    int ns;    const char *key;    service_t svc;    pkt = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);    ns = nad_add_namespace(pkt->nad, uri_BROWSE, NULL);    nad_append_elem(pkt->nad, ns, "service", 2);    nad_append_attr(pkt->nad, -1, "jid", mod->mm->sm->id);    nad_append_attr(pkt->nad, -1, "type", "jabber");    /* fill in our features */    if(xhash_iter_first(mod->mm->sm->features))        do {            xhash_iter_get(mod->mm->sm->features, &key, NULL);                        /* hackishly seperate generic features from namespaces */            if(!((strlen(key) >= 7 && (strncmp(key, "jabber:", 7) == 0 || strncmp(key, "http://", 7) == 0)) || strcmp(key, "vcard-temp") == 0))                continue;            nad_append_elem(pkt->nad, ns, "ns", 3);            nad_append_cdata(pkt->nad, (char *) key, strlen(key), 4);        } while(xhash_iter_next(mod->mm->sm->features));    /* fill in the items */    if(xhash_iter_first(d->un))        do {            xhash_iter_get(d->un, NULL, (void **) &svc);            if(strcmp(svc->category, "gateway") == 0)                nad_append_elem(pkt->nad, ns, "service", 3);            else                nad_append_elem(pkt->nad, ns, svc->category, 3);            nad_append_attr(pkt->nad, -1, "jid", jid_full(svc->jid));            if(svc->name[0] != '\0')                nad_append_attr(pkt->nad, -1, "name", svc->name);            nad_append_attr(pkt->nad, -1, "type", svc->type);            /* service features */            if(xhash_iter_first(svc->features))                do {                    xhash_iter_get(svc->features, &key, NULL);                                /* hackishly seperate generic features from namespaces */                    if(!((strlen(key) >= 7 && (strncmp(key, "jabber:", 7) == 0 || strncmp(key, "http://", 7) == 0)) || strcmp(key, "vcard-temp") == 0))                        continue;                    nad_append_elem(pkt->nad, ns, "ns", 4);                    nad_append_cdata(pkt->nad, (char *) key, strlen(key), 5);                } while(xhash_iter_next(svc->features));        } while(xhash_iter_next(d->un));    return pkt;}/** generate cached result packets */static void _disco_generate_packets(module_t mod, disco_t d) {    log_debug(ZONE, "regenerating packets");    if(d->disco_items_result != NULL)        pkt_free(d->disco_items_result);    d->disco_items_result = _disco_items_result(mod, d);    if(d->disco_info_result != NULL)        pkt_free(d->disco_info_result);    d->disco_info_result = _disco_info_result(mod, d);    if(d->agents) {        if(d->agents_result != NULL)            pkt_free(d->agents_result);        d->agents_result = _disco_agents_result(mod, d);    }    if(d->browse) {        if(d->browse_result != NULL)            pkt_free(d->browse_result);        d->browse_result = _disco_browse_result(mod, d);    }}/** catch responses and populate the table */static mod_ret_t _disco_pkt_sm_populate(mod_instance_t mi, pkt_t pkt){    module_t mod = mi->mod;    disco_t d = (disco_t) mod->private;    int ns, qelem, elem, attr;    service_t svc;    /* it has to come from the service itself - don't want any old user messing with the table */    if(pkt->from->node[0] != '\0' || pkt->from->resource[0] != '\0')    {        log_debug(ZONE, "disco response from %s, not allowed", jid_full(pkt->from));        return -stanza_err_NOT_ALLOWED;    }    ns = nad_find_scoped_namespace(pkt->nad, uri_DISCO_INFO, NULL);    qelem = nad_find_elem(pkt->nad, 1, ns, "query", 1);        elem = nad_find_elem(pkt->nad, qelem, ns, "identity", 1);    if(elem < 0)        return -stanza_err_BAD_REQUEST;    /* see if we already have this service */    svc = xhash_get(d->dyn, jid_full(pkt->from));    if(svc == NULL)    {        /* make a new one */        svc = (service_t) malloc(sizeof(struct service_st));        memset(svc, 0, sizeof(struct service_st));        svc->jid = jid_dup(pkt->from);        svc->features = xhash_new(9);        /* link it in */        xhash_put(d->dyn, jid_full(svc->jid), (void *) svc);        /* unify */        _disco_unify_lists(d);    }    /* fill in the name */    attr = nad_find_attr(pkt->nad, elem, -1, "name", NULL);    if(attr < 0)        svc->name[0] = '\0';    else        snprintf(svc->name, 257, "%.*s", NAD_AVAL_L(pkt->nad, attr), NAD_AVAL(pkt->nad, attr));    /* category and type */    attr = nad_find_attr(pkt->nad, elem, -1, "category", NULL);    if(attr >= 0)        snprintf(svc->category, 257, "%.*s", NAD_AVAL_L(pkt->nad, attr), NAD_AVAL(pkt->nad, attr));    else        strcpy(svc->category, "unknown");    attr = nad_find_attr(pkt->nad, elem, -1, "type", NULL);    if(attr >= 0)        snprintf(svc->type, 257, "%.*s", NAD_AVAL_L(pkt->nad, attr), NAD_AVAL(pkt->nad, attr));    else        strcpy(svc->type, "unknown");    /* features */    elem = nad_find_elem(pkt->nad, qelem, -1, "feature", 1);    while(elem >= 0)    {        attr = nad_find_attr(pkt->nad, elem, -1, "var", NULL);        if(attr < 0)        {            elem = nad_find_elem(pkt->nad, elem, -1, "feature", 0);            continue;        }        xhash_put(svc->features, pstrdupx(xhash_pool(svc->features), NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr)), (void *) 1);        elem = nad_find_elem(pkt->nad, elem, -1, "feature", 0);    }    /* regenerate packets */    _disco_generate_packets(mod, d);    pkt_free(pkt);    return mod_HANDLED;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -