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

📄 mod_presence.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL").  You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/.   * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights *  * Portions created by or assigned to Jabber.com, Inc. are  * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. *  * Acknowledgements *  * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. *  * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above.  If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL.  If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL.  *  *  * --------------------------------------------------------------------------*/#include "jsm.h"/** * @file mod_presence.c * @brief handles presences: send to subscribers, send offline on session end, probe for subscribed presences * * This module is responsible for sending presences to all contacts that subscribed to the user's presence. * It will send an unavailable presence to everybudy that got an available presence. It will send * probes to the contacts to which we have subscribed presence. * * This module is NOT responsible for handling subscriptions, they are handled in mod_roster.c. * * We have three sets of jids for each user: * - T: trusted (roster s10ns) * - A: availables (who knows were available) - stored in modpres_struct * - I: invisibles (who were invisible to) - stored in modpres_struct * * action points: * - broadcasting available presence: intersection of T and A *   (don't broadcast updates to them if they don't think we're *   available any more, either we told them that or their jidd i *   returned a presence error) * - broadcasting unavailable presence: union of A and I *   (even invisible jids need to be notified when going unavail, *   since invisible is still technically an available presence *   and may be used as such by a transport or other remote service) * - allowed to return presence to a probe when available: compliment *   of I in T (all trusted jids, except the ones were invisible to, *   may poll our presence any time) * - allowed to return presence to a probe when invisible: *   intersection of T and A (of the trusted jids, only the ones *   we've sent availability to can poll, and we return a generic *   available presence) * - individual avail presence: forward, add to A, remove from I  * - individual unavail presence: forward and remove from A, remove from I * - individual invisible presence: add to I, remove from A * - first avail: populate A with T and broadcast *//** * @brief hold configuration data for this module instance * * This structure holds all information about the configuration of this module. */typedef struct modpres_conf_struct {    jid bcc;		/**< who gets a blind carbon copy of our presences */    int pres_to_xdb;	/**< if the (primary) presence of a user should be stored in xdb */} *modpres_conf, _modpres_conf;/** * @brief hold all data belonging to this module and a single (online) user * * This structure holds the A and I (see description of mod_presence.c) list for a user, * a flag if a user is invisible, and a list of JIDs we have to send a blind carbon copy * of each presence */typedef struct modpres_struct{    int invisible;	/**< flags that the user is invisible */    jid A;		/**< who knows the user is available */    jid I;		/**< who knows the user is invisible */    modpres_conf conf;	/**< configuration of this module's instance */} *modpres, _modpres;/** * util to check if someone knows about us * * checks if the JID id is contained in the JID list ids * * @param id the JabberID that should be checked * @param ids the list of JabberIDs * @return 1 if it is contained, 0 else */int _mod_presence_search(jid id, jid ids){    jid cur;    for(cur = ids; cur != NULL; cur = cur->next)        if(jid_cmp(cur,id) == 0)            return 1;    return 0;}/** * remove a jid from a list, returning the new list * * @param id the JabberID that should be removed * @param ids the list of JabberIDs * @return the new list */jid _mod_presence_whack(jid id, jid ids){    jid curr;    if(id == NULL || ids == NULL) return NULL;    /* check first */    if(jid_cmp(id,ids) == 0) return ids->next;    /* check through the list, stopping at the previous list entry to a matching one */    for(curr = ids;curr != NULL && jid_cmp(curr->next,id) != 0;curr = curr->next);    /* clip it out if found */    if(curr != NULL)        curr->next = curr->next->next;    return ids;}/** * broadcast a presence stanza to a list of JabberIDs * * this function broadcasts the stanza given as x to all users that are in the notify list of JabberIDs * as well as in the intersect list of JabberIDs. If intersect is a NULL pointer the presences are * broadcasted to all JabberIDs in the notify list. * * @param s the session of the user owning the presence * @param notify list of JabberIDs that should be notified * @param x the presence that should be broadcasted * @param intersect if non-NULL only send presence to the intersection of notify and intersect */void _mod_presence_broadcast(session s, jid notify, xmlnode x, jid intersect){    jid cur;    xmlnode pres;    for(cur = notify; cur != NULL; cur = cur->next)    {        if(intersect != NULL && !_mod_presence_search(cur,intersect)) continue; /* perform insersection search, must be in both */        s->c_out++;        pres = xmlnode_dup(x);        xmlnode_put_attrib(pres, "to",jid_full(cur));        js_deliver(s->si,jpacket_new(pres));    }}/** * filter the incoming presence to this session * * incoming presence probes get handled and replied if the sender is allowed to see the user's presence and there is a session (presence) * * filters presences which are sent by the user itself * * removes JabberIDs from the list of entites that know a user is online if a presence bounced * * converts incoming invisible presences to unavailable presences as users should not get invisible presences at all * * @param m the mapi structure * @param arg the modpres structure containing the module data belonging to the user's session * @return M_IGNORE if stanza is no presence, M_HANDLED if a presence should not be delivered or has been completely handled, M_PASS else */mreturn mod_presence_in(mapi m, void *arg){    modpres mp = (modpres)arg;    xmlnode pres;    if(m->packet->type != JPACKET_PRESENCE) return M_IGNORE;    log_debug2(ZONE, LOGT_DELIVER, "incoming filter for %s",jid_full(m->s->id));    if(jpacket_subtype(m->packet) == JPACKET__PROBE)    { /* reply with our presence */        if(m->s->presence == NULL)        {            log_debug2(ZONE, LOGT_DELIVER, "probe from %s and no presence to return",jid_full(m->packet->from));        }else if(!mp->invisible && js_trust(m->user,m->packet->from) && !_mod_presence_search(m->packet->from,mp->I)){ /* compliment of I in T */            log_debug2(ZONE, LOGT_DELIVER, "got a probe, responding to %s",jid_full(m->packet->from));            pres = xmlnode_dup(m->s->presence);            xmlnode_put_attrib(pres,"to",jid_full(m->packet->from));            js_session_from(m->s, jpacket_new(pres));        }else if(mp->invisible && js_trust(m->user,m->packet->from) && _mod_presence_search(m->packet->from,mp->A)){ /* when invisible, intersection of A and T */            log_debug2(ZONE, LOGT_DELIVER, "got a probe when invisible, responding to %s",jid_full(m->packet->from));            pres = jutil_presnew(JPACKET__AVAILABLE,jid_full(m->packet->from),NULL);            js_session_from(m->s, jpacket_new(pres));        }else{            log_debug2(ZONE, LOGT_DELIVER, "%s attempted to probe by someone not qualified",jid_full(m->packet->from));        }        xmlnode_free(m->packet->x);        return M_HANDLED;    }    if(m->packet->from == NULL || jid_cmp(m->packet->from,m->s->id) == 0)    { /* this is our presence, don't send to ourselves */        xmlnode_free(m->packet->x);        return M_HANDLED;    }    /* if a presence packet bounced, remove from the A list */    if(jpacket_subtype(m->packet) == JPACKET__ERROR)        mp->A = _mod_presence_whack(m->packet->from, mp->A);    /* doh! this is a user, they should see invisibles as unavailables */    if(jpacket_subtype(m->packet) == JPACKET__INVISIBLE)        xmlnode_put_attrib(m->packet->x,"type","unavailable");    return M_PASS;}/** * process the roster to probe outgoing s10ns, and populate a list of the jids that should be notified * * this function requests the roster from xdb and does for each contact: * - if the user is subscribed to the contacts presence: send a presence probe * - if the user has a subscription from the contact: adds the contacts JabberID to the existing list given as parameter \a notify *   (if this parameter is NULL, than this function does not care about other users that have subscribed to us) * * @note the argument given as \a notify is the list A, this list is initialized to contain the user itself, therefore * there is always already a first element in the list and we can just append new items. Still I don't like that we do * not pass back a pointer to the resulting list, that would allow use to handle an empty initial list as well. * * @param m the mapi structure * @param notify list where contacts that are subscribed to the users presences should be added, if this is NULL we don't add anything */void mod_presence_roster(mapi m, jid notify){    xmlnode roster, cur, pnew;    jid id;    int to, from;    /* do our roster setup stuff */    roster = xdb_get(m->si->xc, m->user->id, NS_ROSTER);    for(cur = xmlnode_get_firstchild(roster); cur != NULL; cur = xmlnode_get_nextsibling(cur))    {        id = jid_new(m->packet->p,xmlnode_get_attrib(cur,"jid"));        if(id == NULL) continue;        log_debug2(ZONE, LOGT_DELIVER, "roster item %s s10n=%s",jid_full(id),xmlnode_get_attrib(cur,"subscription"));        /* vars */        to = from = 0;        if(j_strcmp(xmlnode_get_attrib(cur,"subscription"),"to") == 0)            to = 1;        if(j_strcmp(xmlnode_get_attrib(cur,"subscription"),"from") == 0)            from = 1;        if(j_strcmp(xmlnode_get_attrib(cur,"subscription"),"both") == 0)            to = from = 1;        /* curiosity phase */        if(to)        {            log_debug2(ZONE, LOGT_DELIVER, "we're new here, probe them");            pnew = jutil_presnew(JPACKET__PROBE,jid_full(id),NULL);            xmlnode_put_attrib(pnew,"from",jid_full(jid_user(m->s->id)));            js_session_from(m->s, jpacket_new(pnew));        }        /* notify phase, only if it's global presence */        if(from && notify != NULL)        {            log_debug2(ZONE, LOGT_DELIVER, "we need to notify them");            jid_append(notify, id);        }    }    xmlnode_free(roster);}/** * store the top presence information to xdb * * @param m the mapi struct */void mod_presence_store(mapi m) {    /* get the top session */    session top = js_session_primary(m->user);    /* store to xdb */    xdb_set(m->si->xc, m->user->id, NS_JABBERD_STOREDPRESENCE, top ? top->presence : NULL);}/** * handles undirected outgoing presences (presences with no to attribute) * * checks that the presence's priority is in the valid range * * if the outgoing presence is an invisible presence and we are available, * we inject an unavailable presence first and reinject the unavailable * presence afterwards again (we are then not available anymore and therefore * will not do this twice for the same presence) * * If the outgoing presence is not an invisible presence, it is stored in the structure * of this session in the session manager and the presence is stamped with the * current timestamp. * * Unavailable presences are broadcasted to everyone that thinks we are online, * available presence are broadcasted to everyone that has subscribed to our presence. * * If we are already online with other resources, our existing presences are sent to * our new resource. * * Presence probes are sent out to our contacts we are subscribed to. * * @note this is our second callback for outgoing presences, mod_presence_avails() should have handled the presence first * * @todo think about if we shouldn't check the presence's priority earlier, maybe in mod_presence_avails()

⌨️ 快捷键说明

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