Logo Search packages:      
Sourcecode: jabberd14 version File versions  Download package

static mreturn mod_presence_out ( mapi  m,
void *  arg 
) [static]

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()
Parameters:
m the mapi structure
arg pointer to the modpres structure containing the module's data for this session
Returns:
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

Definition at line 361 of file mod_presence.cc.

References _mod_presence_broadcast(), modpres_struct::A, modpres_conf_struct::bcc, modpres_struct::conf, modpres_struct::I, udata_struct::id, session_struct::id, modpres_struct::invisible, jpacket_new(), jpacket_subtype(), js_session_from(), js_session_to(), js_trustees(), jutil_presnew(), jutil_priority(), jutil_timestamp(), log_notice(), M_HANDLED, M_IGNORE, M_PASS, mod_presence_roster(), mod_presence_store(), session_struct::next, mapi_struct::packet, modpres_conf_struct::pres_to_xdb, session_struct::presence, session_struct::priority, mapi_struct::s, udata_struct::sessions, mapi_struct::si, jsmi_struct::std_namespace_prefixes, mapi_struct::user, xmlnode_dup(), xmlnode_dup_pool(), xmlnode_free(), xmlnode_get_data(), xmlnode_get_list_item(), xmlnode_get_tags(), xmlnode_insert_tag_ns(), xmlnode_put_attrib_ns(), and xmlnode_serialize_string().

Referenced by mod_presence_deserialize(), and mod_presence_session().

                                                   {
    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), xmlnode_serialize_string(m->packet->x, xmppd::ns_decl_list(), 0));

    /* 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_data(xmlnode_get_list_item(xmlnode_get_tags(m->packet->x, "priority", m->si->std_namespace_prefixes), 0));
    if (priority == NULL) {
      newpri = 0;
    } else {
      newpri = j_atoi(priority, 0);
      if (newpri < -128 || newpri > 127) {
          log_notice(m->s->id->server, "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_ns(m->s->presence, "x", NULL, NS_DELAY);
    xmlnode_put_attrib_ns(delay, "from", NULL, NULL, jid_full(m->s->id));
    xmlnode_put_attrib_ns(delay, "stamp", NULL, NULL, 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;

    /* 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_ns(duplicated_presence, "to", NULL, NULL, 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;
}


Generated by  Doxygen 1.6.0   Back to index