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

📄 mod_presence.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 2 页
字号:
 * * @param m the mapi structure * @param arg pointer to the modpres structure containing the module's data for this session * @return M_IGNORE if the stanza is no presence, M_PASS if the presence has a to attribute, is a probe, or is an error presence, M_HANDLED else */mreturn mod_presence_out(mapi m, void *arg){    xmlnode pnew, delay;    modpres mp = (modpres)arg;    session cur = NULL;    int oldpri, newpri;    char *priority;    if(m->packet->type != JPACKET_PRESENCE) return M_IGNORE;    if(m->packet->to != NULL || jpacket_subtype(m->packet) == JPACKET__PROBE || jpacket_subtype(m->packet) == JPACKET__ERROR) return M_PASS;    log_debug2(ZONE, LOGT_DELIVER, "new presence from %s of %s",jid_full(m->s->id),xmlnode2str(m->packet->x));    /* pre-existing conditions (no, we are not an insurance company) */    oldpri = m->s->priority;    /* check that the priority is in the valid range */    priority = xmlnode_get_tag_data(m->packet->x, "priority");    if (priority == NULL) {	newpri = 0;    } else {	newpri = j_atoi(priority, 0);	if (newpri < -128 || newpri > 127) {	    log_notice("mod_presence", "got presence with invalid priority value from %s", jid_full(m->s->id));	    xmlnode_free(m->packet->x);	    return M_HANDLED;	}    }    /* invisible mode is special, don't you wish you were special too? */    if(jpacket_subtype(m->packet) == JPACKET__INVISIBLE)    {        log_debug2(ZONE, LOGT_DELIVER, "handling invisible mode request");        /* if we get this and we're available, it means go unavail first then reprocess this packet, nifty trick :) */        if(oldpri >= -128)	{            js_session_from(m->s, jpacket_new(jutil_presnew(JPACKET__UNAVAILABLE,NULL,NULL)));            js_session_from(m->s, m->packet);            return M_HANDLED;	}        /* now, pretend we come online :) */	/* (this is the handling of the reinjected invisible presence	 * or an initial invisible presence) */        mp->invisible = 1;        mod_presence_roster(m, NULL); /* send out probes to users we are subscribed to */        m->s->priority = newpri;	/* store presence in xdb? */	if (mp->conf->pres_to_xdb > 0)	    mod_presence_store(m);        xmlnode_free(m->packet->x); /* we do not broadcast invisible presences without a to attribute */        return M_HANDLED;    }    /* our new presence, keep it */    xmlnode_free(m->s->presence);    m->s->presence = xmlnode_dup(m->packet->x);    m->s->priority = jutil_priority(m->packet->x);    /* store presence in xdb? */    if (mp->conf->pres_to_xdb > 0)	mod_presence_store(m);    /* stamp the sessions presence */    delay = xmlnode_insert_tag(m->s->presence,"x");    xmlnode_put_attrib(delay,"xmlns",NS_DELAY);    xmlnode_put_attrib(delay,"from",jid_full(m->s->id));    xmlnode_put_attrib(delay,"stamp",jutil_timestamp());    log_debug2(ZONE, LOGT_DELIVER, "presence oldp %d newp %d",oldpri,m->s->priority);    /* if we're going offline now, let everyone know */    if(m->s->priority < -128) {        /* jutil_priority returns -129 in case the "type" attribute is missing */        if(!mp->invisible) /* bcc's don't get told if we were invisible */            _mod_presence_broadcast(m->s,mp->conf->bcc,m->packet->x,NULL);        _mod_presence_broadcast(m->s,mp->A,m->packet->x,NULL);        _mod_presence_broadcast(m->s,mp->I,m->packet->x,NULL);        /* reset vars */        mp->invisible = 0;        if(mp->A != NULL)            mp->A->next = NULL;        mp->I = NULL;        xmlnode_free(m->packet->x);        return M_HANDLED;    }    /* available presence updates, intersection of A and T */    if(oldpri >= -128 && !mp->invisible)    {        _mod_presence_broadcast(m->s,mp->A,m->packet->x,js_trustees(m->user));        xmlnode_free(m->packet->x);        return M_HANDLED;    }    /* at this point we're coming out of the closet */    mp->invisible = 0;    /* make sure we get notified for any presence about ourselves */    /* XXX: the following is the original code: it caused existing presences     * to be stamped several times and the presence to be sent out twice.    pnew = jutil_presnew(JPACKET__PROBE,jid_full(jid_user(m->s->id)),NULL);    xmlnode_put_attrib(pnew,"from",jid_full(jid_user(m->s->id)));    js_session_from(m->s, jpacket_new(pnew));    */    /* XXX: I think this should be okay as well: */    /* send us all presences of our other resources */    for (cur = m->user->sessions; cur != NULL; cur=cur->next) {	pool pool_for_existing_presence = NULL;	xmlnode duplicated_presence = NULL;	jpacket packet = NULL;		/* skip our own session (and sanity check) */	if (cur == m->s || cur->presence == NULL) {	    continue;	}	/* send the presence to us: we need a new pool as js_session_to() will free the packet's pool  */	pool_for_existing_presence = pool_new();	duplicated_presence = xmlnode_dup_pool(pool_for_existing_presence, cur->presence);	xmlnode_put_attrib(duplicated_presence, "to", jid_full(m->user->id));	packet = jpacket_new(duplicated_presence);	js_session_to(m->s, packet);    }    /* probe s10ns and populate A */    mod_presence_roster(m,mp->A);    /* we broadcast this baby! */    _mod_presence_broadcast(m->s,mp->conf->bcc,m->packet->x,NULL);    _mod_presence_broadcast(m->s,mp->A,m->packet->x,NULL);    xmlnode_free(m->packet->x);    return M_HANDLED;}/** * update the A and I list, because we send a new presence out * * If we sent out an invisible presence, add the destination to the I list. * * If we sent out an available presence, add the destination to the A list and remove from the I list. * * If we sent out an unavailable presence, remove from both A and I lists. * * @note this is our first callback for outgoing presences, mod_presence_out() is the second, that should be called afterwards * * @param m the mapi structure * @param arg pointer to the modpres structure containing the modules session data (especially the lists A and I) * @return M_IGNORE if the stanza is no presence, else always M_PASS */mreturn mod_presence_avails(mapi m, void *arg){    modpres mp = (modpres)arg;    if(m->packet->type != JPACKET_PRESENCE) return M_IGNORE;    if(m->packet->to == NULL) return M_PASS;    log_debug2(ZONE, LOGT_DELIVER, "track presence sent to jids");    /* handle invisibles: put in I and remove from A */    if(jpacket_subtype(m->packet) == JPACKET__INVISIBLE)    {        if(mp->I == NULL)            mp->I = jid_new(m->s->p,jid_full(m->packet->to));        else            jid_append(mp->I, m->packet->to);        mp->A = _mod_presence_whack(m->packet->to,mp->A);        return M_PASS;    }    /* ensure not invisible from before */    mp->I = _mod_presence_whack(m->packet->to,mp->I);    /* avails to A */    if(jpacket_subtype(m->packet) == JPACKET__AVAILABLE)        jid_append(mp->A, m->packet->to);    /* unavails from A */    if(jpacket_subtype(m->packet) == JPACKET__UNAVAILABLE)        mp->A = _mod_presence_whack(m->packet->to,mp->A);    return M_PASS;}/** * callback, that gets called if a session ends * * The session manager has set the presence of the user to unavailable, we have to broadcast this presence * to everybody that thinks we are available. * * @param m the mapi structure * @param arg pointer to the modpres structure containing the lists for this session * @return always M_PASS */mreturn mod_presence_avails_end(mapi m, void *arg){    modpres mp = (modpres)arg;    log_debug2(ZONE, LOGT_DELIVER, "avail tracker guarantee checker");    /* send  the current presence (which the server set to unavail) */    xmlnode_put_attrib(m->s->presence, "from",jid_full(m->s->id));    _mod_presence_broadcast(m->s, mp->conf->bcc, m->s->presence, NULL);    _mod_presence_broadcast(m->s, mp->A, m->s->presence, NULL);    _mod_presence_broadcast(m->s, mp->I, m->s->presence, NULL);    /* store presence in xdb? */    if (mp->conf->pres_to_xdb > 0)	mod_presence_store(m);    return M_PASS;}/** * callback, that gets called if a new session is establisched, registers all session oriented callbacks * * This callback is responsible for initializing a new instance of the _modpres structure, that holds * the list of entites that know that a user is available. * * @param m the mapi structure * @param arg the list of JabberIDs that get a bcc of all presences * @return always M_PASS */mreturn mod_presence_session(mapi m, void *arg){    modpres_conf conf = (modpres_conf)arg;    modpres mp;    /* track our session stuff */    mp = pmalloco(m->s->p, sizeof(_modpres));    mp->A = jid_user(m->s->id);    mp->conf = conf; /* no no, it's ok, these live longer than us */    js_mapi_session(es_IN, m->s, mod_presence_in, mp);    js_mapi_session(es_OUT, m->s, mod_presence_avails, mp); /* must come first, it passes, _out handles */    js_mapi_session(es_OUT, m->s, mod_presence_out, mp);    js_mapi_session(es_END, m->s, mod_presence_avails_end, mp);    return M_PASS;}/** * deliver presence stanzas to local users * * This callback ignores all stanzas but presence stanzas. presences sent to a user (without specifying a resource) have to * be delivered to all sessions of this user. * * Presences sent to a specified resource are not handled. * * @param m the mapi structure * @param arg ignored/unused * @return M_IGNORED if not a presence stanza, M_PASS if the presence has not been handled, M_HANDLED if the presence has been handled */mreturn mod_presence_deliver(mapi m, void *arg){    session cur;    if(m->packet->type != JPACKET_PRESENCE) return M_IGNORE;    log_debug2(ZONE, LOGT_DELIVER, "deliver phase");    /* only if we HAVE a user, and it was sent to ONLY the user@server, and there is at least one session available */    if(m->user != NULL && m->packet->to->resource == NULL && js_session_primary(m->user) != NULL)    {        log_debug2(ZONE, LOGT_DELIVER, "broadcasting to %s",m->user->user);        /* broadcast */        for(cur = m->user->sessions; cur != NULL; cur = cur->next)        {            if(cur->priority < -128) continue;            js_session_to(cur, jpacket_new(xmlnode_dup(m->packet->x)));        }        if(jpacket_subtype(m->packet) != JPACKET__PROBE)        { /* probes get handled by the offline thread as well? */            xmlnode_free(m->packet->x);            return M_HANDLED;        }    }    return M_PASS;}/** * init the module, register callbacks * * builds a list of JabberIDs where presences should be blind carbon copied to. * (Enclosing each in a <bcc/> element, which are contained in one <presence/> * element in the session manager configuration.) * * registers mod_presence_session() as a callback, that gets notified on new sessions * and mod_presence_deliver() as a callback to deliver presence stanzas locally. * * @param si the session manager instance */void mod_presence(jsmi si){    xmlnode cfg = js_config(si, "presence");    modpres_conf conf = (modpres_conf)pmalloco(si->p, sizeof(_modpres_conf));    log_debug2(ZONE, LOGT_INIT, "init");    for(cfg = xmlnode_get_firstchild(cfg); cfg != NULL; cfg = xmlnode_get_nextsibling(cfg))    {	char *element_name = NULL;        if(xmlnode_get_type(cfg) != NTYPE_TAG)	    continue;	element_name = xmlnode_get_name(cfg);	if (j_strcmp(element_name, "bcc") == 0) {	    if(conf->bcc == NULL)		conf->bcc = jid_new(si->p,xmlnode_get_data(cfg));	    else		jid_append(conf->bcc,jid_new(si->p,xmlnode_get_data(cfg)));	} else if (j_strcmp(element_name, "presence2xdb") == 0) {	    conf->pres_to_xdb++;	}    }    js_mapi_register(si,e_DELIVER, mod_presence_deliver, NULL);    js_mapi_register(si,e_SESSION, mod_presence_session, (void*)conf);}

⌨️ 快捷键说明

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