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

void pres_update ( sess_t  sess,
pkt_t  pkt 
)

presence updates from a session

Definition at line 67 of file pres.c.

References _pres_top(), sess_st::A, sess_st::available, sess_st::E, pkt_st::from, sm_st::id, sess_st::invisible, sess_st::jid, sess_st::next, pkt_delay(), pkt_dup(), pkt_PRESENCE, pkt_PRESENCE_INVIS, pkt_PRESENCE_UN, sess_st::pres, pres_trust(), pkt_st::pri, sess_st::pri, user_st::roster, user_st::sessions, user_st::sm, pkt_st::sm, pkt_st::type, sess_st::user, and sm_st::users.

Referenced by _presence_in_sess().

                                         {
    item_t item;
    int self;
    jid_t scan, next;
    sess_t sscan;
    user_t user;
    int user_is_local;
    int user_connected = 0;

    switch(pkt->type) {
        case pkt_PRESENCE:
            log_debug(ZONE, "available presence for session %s", jid_full(sess->jid));

            /* cache packet for later */
            if(sess->pres != NULL)
                pkt_free(sess->pres);
            sess->pres = pkt;

            /* B1: forward to all in T, unless in E */

            /* loop the roster, looking for trusted */
            self = 0;
            if(xhash_iter_first(sess->user->roster))
            do {
                xhash_iter_get(sess->user->roster, NULL, (void *) &item);

            /* Is the user local ? */
                user_is_local = (strcmp(pkt->sm->id, item->jid->domain)==0);
                if (user_is_local) {
                  user = xhash_get(pkt->sm->users, jid_user(item->jid));
                  user_connected = ((user!=NULL) && (user->sessions != NULL));
                } 

                /* if we're coming available, and we can see them, we need to probe them */
                if(!sess->available && item->to) {

                    /* Shortcut */
                    if ((!user_is_local) || (user_is_local && user_connected)) {
                       log_debug(ZONE, "probing %s", jid_full(item->jid));
                       pkt_router(pkt_create(sess->user->sm, "presence", "probe", jid_full(item->jid), jid_user(sess->jid))); 
                    } else 
                       log_debug(ZONE, "skipping probe to local user %s - not connected", jid_full(item->jid));

                    /* flag if we probed ourselves */
                    if(strcmp(jid_user(sess->jid), jid_full(item->jid)) == 0)
                        self = 1;
                }

                /* if they can see us, forward */
                if(item->from && !jid_search(sess->E, item->jid)) {
                /* Shortcut: if the domain of this user's jid is the same as this sm,
                  and the user has no active sessions, don't send presence update */

                    if ((!user_is_local) || (user_is_local && user_connected)) {
                       log_debug(ZONE, "forwarding available to %s", jid_full(item->jid));
                       pkt_router(pkt_dup(pkt, jid_full(item->jid), jid_full(sess->jid)));
                    } else 
                       log_debug(ZONE, "skipping forwarding available to %s - not connected", jid_full(item->jid));
                }
            } while(xhash_iter_next(sess->user->roster));

            /* probe ourselves if we need to and didn't already */
            if(!self && !sess->available) {
                log_debug(ZONE, "probing ourselves");
                pkt_router(pkt_create(sess->user->sm, "presence", "probe", jid_user(sess->jid), jid_user(sess->jid)));
            }

            /* forward to our active sessions */
            for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
                if(sscan != sess && sscan->available) {
                    log_debug(ZONE, "forwarding available to our session %s", jid_full(sscan->jid));
                    pkt_router(pkt_dup(pkt, jid_full(sscan->jid), jid_full(sess->jid)));
                }
            }

            /* update vars */
            sess->available = 1;
            sess->invisible = 0;

            /* new priority */
            sess->pri = pkt->pri;

            /* stamp the saved presence so future probes know how old it is */
            pkt_delay(pkt, time(NULL), jid_full(pkt->from));

            break;

        case pkt_PRESENCE_UN:
            log_debug(ZONE, "unavailable presence for session %s", jid_full(sess->jid));

            /* free cached presence */
            if(sess->pres != NULL) {
                pkt_free(sess->pres);
                sess->pres = NULL;
            }

            /* B2: forward to all in T and A, unless in E */

            /* loop the roster, looking for trusted */
            if(xhash_iter_first(sess->user->roster))
            do {
                xhash_iter_get(sess->user->roster, NULL, (void *) &item);

            /* Is the user local ? */
                user_is_local = (strcmp(pkt->sm->id, item->jid->domain)==0);
                if (user_is_local) {
                  user = xhash_get(pkt->sm->users, jid_user(item->jid));
                  user_connected = ((user!=NULL) && (user->sessions != NULL));
                } 

                /* forward if they're trusted and they're not E */
                if(item->from && !jid_search(sess->E, item->jid)) {

                    /* Shortcut: same technique as for presence available above */
                    if (!user_is_local || (user_is_local && user_connected)) {
                       log_debug(ZONE, "forwarding unavailable to %s", jid_full(item->jid));
                       pkt_router(pkt_dup(pkt, jid_full(item->jid), jid_full(sess->jid)));
                    } else
                       log_debug(ZONE, "skipping forwarding unavailable to %s - not connected", jid_full(item->jid));
                }
            } while(xhash_iter_next(sess->user->roster));

            /* walk A and forward to untrusted */
            for(scan = sess->A; scan != NULL; scan = scan->next)
                if(!pres_trust(sess->user, scan)) {
                    log_debug(ZONE, "forwarding unavailable to %s", jid_full(scan));
                    pkt_router(pkt_dup(pkt, jid_full(scan), jid_full(sess->jid)));
                }

            /* forward to our active sessions */
            for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
                if(sscan != sess && sscan->available) {
                    log_debug(ZONE, "forwarding available to our session %s", jid_full(sscan->jid));
                    pkt_router(pkt_dup(pkt, jid_full(sscan->jid), jid_full(sess->jid)));
                }
            }

            /* drop A, E */
            scan = sess->A;
            while(scan != NULL) {
                next = scan->next;
                jid_free(scan);
                scan = next;
            }
            sess->A = NULL;

            scan = sess->E;
            while(scan != NULL) {
                next = scan->next;
                jid_free(scan);
                scan = next;
            }
            sess->E = NULL;

            /* update vars */
            sess->available = 0;
            sess->invisible = 0;

            /* done */
            pkt_free(pkt);

            break;

        case pkt_PRESENCE_INVIS:
            log_debug(ZONE, "invisible presence for session %s", jid_full(sess->jid));
            
            /* only process if we're not already invisible */
            if(!sess->invisible) {
                /* B3: forward to all in T, unless in A or E */

                /* loop the roster, looking for trusted */
                if(xhash_iter_first(sess->user->roster))
                do {
                    xhash_iter_get(sess->user->roster, NULL, (void *) &item);

                    /* if they can see us, and we haven't sent directed to them, then tell them we're gone */
                    if(item->from && !jid_search(sess->A, item->jid) && !jid_search(sess->E, item->jid)) {
                        log_debug(ZONE, "sending unavailable (invisible) to %s", jid_full(item->jid));
                        pkt_router(pkt_create(sess->user->sm, "presence", "unavailable", jid_full(item->jid), jid_full(sess->jid)));
                    }
                } while(xhash_iter_next(sess->user->roster));

                /* forward to our active sessions */
                for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
                    if(sscan != sess && sscan->available) {
                        log_debug(ZONE, "sending unavailable (invisible) to our session %s", jid_full(sscan->jid));
                        pkt_router(pkt_create(sess->user->sm, "presence", "unavailable", jid_full(sscan->jid), jid_full(sess->jid)));
                    }
                }
            }

            /* update vars */
            sess->invisible = 1;

            /* done */
            pkt_free(pkt);

            break;
        
        default:
            log_debug(ZONE, "pres_update got packet type %d, this shouldn't happen", pkt->type);
            pkt_free(pkt);
            return;
    }

    /* reset the top session */
    _pres_top(sess->user);
}


Generated by  Doxygen 1.6.0   Back to index