📄 pres.c
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002-2003 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/pres.c * @brief presence tracker * @author Robert Norris * $Date: 2004/12/09 15:12:23 $ * $Revision: 1.33.2.4 $ *//* * there are four entry points * * pres_update(sess, pkt) - presence updates from a session (T1, T2, T3) * pres_in(user, pkt) - presence updates from a remote jid (T4, T5) * pres_error(sess, jid) - remote jid bounced an update (T6) * pres_deliver(sess, pkt) - outgoing directed presence (T7, T8) *//** select a new top session based on current session presence */void _pres_top(user_t user) { sess_t scan; user->top = NULL; /* loop the active sessions */ for(scan = user->sessions; scan != NULL; scan = scan->next) { /* non available and/or negative presence can't become top session */ if(!scan->available || scan->pri < 0) continue; /* if we don't have one, then this is it */ if(user->top == NULL) user->top = scan; /* if we have higher priority than current top, we're the new top */ if(scan->pri >= user->top->pri) user->top = scan; } if(user->top == NULL) { log_debug(ZONE, "no priority >= 0 sessions, so no top session"); } else { log_debug(ZONE, "top session for %s is now %s (priority %d)", jid_user(user->jid), jid_full(user->top->jid), user->top->pri); }}/** presence updates from a session */void pres_update(sess_t sess, pkt_t pkt) { item_t item; int self; jid_t scan, next; sess_t sscan; user_t user; int user_is_local; int user_connected; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -