jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2002-2003 Jeremie Miller, Thomas Muldowney, 00004 * Ryan Eatmon, Robert Norris 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00019 */ 00020 00021 #include "sm.h" 00022 00031 void dispatch(sm_t sm, pkt_t pkt) { 00032 user_t user; 00033 mod_ret_t ret; 00034 00035 /* handle broadcasts */ 00036 if(pkt->rtype == route_BROADCAST) { 00037 log_debug(ZONE, "can't handle broadcast routes (yet), dropping"); 00038 pkt_free(pkt); 00039 return; 00040 } 00041 00042 /* routing errors, add a im error */ 00043 if(pkt->rtype & route_ERROR) { 00044 int i, aerror, stanza_err; 00045 aerror = nad_find_attr(pkt->nad, 0, -1, "error", NULL); 00046 stanza_err = stanza_err_REMOTE_SERVER_NOT_FOUND; 00047 if(aerror >= 0) { 00048 for(i=0; _stanza_errors[i].code != NULL; i++) 00049 if(strncmp(_stanza_errors[i].code, NAD_AVAL(pkt->nad, aerror), NAD_AVAL_L(pkt->nad, aerror)) == 0) { 00050 stanza_err = stanza_err_BAD_REQUEST + i; 00051 break; 00052 } 00053 } 00054 if(pkt_error(pkt, stanza_err) == NULL) 00055 return; 00056 } 00057 00058 /* 00059 * - if its from the router (non-route) it goes straight to pkt_router 00060 * - hand it to in_router chain 00061 * - if its for the sm itself (no user), hand it to the pkt_sm chain 00062 * - find the user 00063 * - hand to pkt_user 00064 */ 00065 00066 /* non route packets are special-purpose things from the router */ 00067 if(!(pkt->rtype & route_UNICAST)) { 00068 ret = mm_pkt_router(pkt->sm->mm, pkt); 00069 switch(ret) { 00070 case mod_HANDLED: 00071 break; 00072 00073 case mod_PASS: 00074 default: 00075 /* don't ever bounce these */ 00076 pkt_free(pkt); 00077 00078 break; 00079 } 00080 00081 return; 00082 } 00083 00084 /* preprocessing */ 00085 if (pkt != NULL && pkt->sm != NULL) { 00086 ret = mm_in_router(pkt->sm->mm, pkt); 00087 switch(ret) { 00088 case mod_HANDLED: 00089 return; 00090 00091 case mod_PASS: 00092 break; 00093 00094 default: 00095 pkt_router(pkt_error(pkt, -ret)); 00096 return; 00097 } 00098 } 00099 00100 /* has to come from someone and be directed to someone */ 00101 if(pkt->from == NULL || pkt->to == NULL) { 00102 pkt_router(pkt_error(pkt, stanza_err_BAD_REQUEST)); 00103 return; 00104 } 00105 00106 /* packet is for the sm itself */ 00107 if(*pkt->to->node == '\0') { 00108 ret = mm_pkt_sm(pkt->sm->mm, pkt); 00109 switch(ret) { 00110 case mod_HANDLED: 00111 break; 00112 00113 case mod_PASS: 00114 /* ignore IQ result packets that haven't been handled - XMPP 9.2.3.4 */ 00115 if(pkt->type == pkt_IQ_RESULT) { 00116 pkt_free(pkt); 00117 break; 00118 } else 00119 ret = -stanza_err_FEATURE_NOT_IMPLEMENTED; 00120 00121 default: 00122 pkt_router(pkt_error(pkt, -ret)); 00123 00124 break; 00125 } 00126 00127 return; 00128 } 00129 00130 /* get the user */ 00131 user = user_load(sm, pkt->to); 00132 if(user == NULL) { 00133 if(pkt->type & pkt_PRESENCE && pkt->type != pkt_PRESENCE_PROBE) { 00134 pkt_free(pkt); 00135 return; 00136 } 00137 00138 if(pkt->type == pkt_PRESENCE_PROBE) { 00139 pkt_router(pkt_create(pkt->sm, "presence", "unsubscribed", jid_full(pkt->from), jid_full(pkt->to))); 00140 pkt_free(pkt); 00141 return; 00142 } 00143 00144 pkt_router(pkt_error(pkt, stanza_err_SERVICE_UNAVAILABLE)); 00145 return; 00146 } 00147 00148 if (pkt->sm != NULL) { 00149 ret = mm_pkt_user(pkt->sm->mm, user, pkt); 00150 switch(ret) { 00151 case mod_HANDLED: 00152 break; 00153 00154 case mod_PASS: 00155 /* ignore IQ result packets that haven't been handled - XMPP 9.2.3.4 */ 00156 if(pkt->type == pkt_IQ_RESULT) { 00157 pkt_free(pkt); 00158 break; 00159 } else 00160 ret = -stanza_err_FEATURE_NOT_IMPLEMENTED; 00161 00162 default: 00163 pkt_router(pkt_error(pkt, -ret)); 00164 00165 break; 00166 } 00167 } 00168 00169 /* if they have no sessions, they were only loaded to do delivery, so free them */ 00170 if(user->sessions == NULL) 00171 user_free(user); 00172 }