jabberd2  2.2.17
dispatch.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002-2003 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "sm.h"
22 
31 void dispatch(sm_t sm, pkt_t pkt) {
32  user_t user;
33  mod_ret_t ret;
34 
35  /* handle broadcasts */
36  if(pkt->rtype == route_BROADCAST) {
37  log_debug(ZONE, "can't handle broadcast routes (yet), dropping");
38  pkt_free(pkt);
39  return;
40  }
41 
42  /* routing errors, add a im error */
43  if(pkt->rtype & route_ERROR) {
44  int i, aerror, stanza_err;
45  aerror = nad_find_attr(pkt->nad, 0, -1, "error", NULL);
47  if(aerror >= 0) {
48  for(i=0; _stanza_errors[i].code != NULL; i++)
49  if(strncmp(_stanza_errors[i].code, NAD_AVAL(pkt->nad, aerror), NAD_AVAL_L(pkt->nad, aerror)) == 0) {
50  stanza_err = stanza_err_BAD_REQUEST + i;
51  break;
52  }
53  }
54  if(pkt_error(pkt, stanza_err) == NULL)
55  return;
56  }
57 
58  /*
59  * - if its from the router (non-route) it goes straight to pkt_router
60  * - hand it to in_router chain
61  * - if its for the sm itself (no user), hand it to the pkt_sm chain
62  * - find the user
63  * - hand to pkt_user
64  */
65 
66  /* non route packets are special-purpose things from the router */
67  if(!(pkt->rtype & route_UNICAST)) {
68  ret = mm_pkt_router(pkt->sm->mm, pkt);
69  switch(ret) {
70  case mod_HANDLED:
71  break;
72 
73  case mod_PASS:
74  default:
75  /* don't ever bounce these */
76  pkt_free(pkt);
77 
78  break;
79  }
80 
81  return;
82  }
83 
84  /* preprocessing */
85  if (pkt != NULL && pkt->sm != NULL) {
86  ret = mm_in_router(pkt->sm->mm, pkt);
87  switch(ret) {
88  case mod_HANDLED:
89  return;
90 
91  case mod_PASS:
92  break;
93 
94  default:
95  pkt_router(pkt_error(pkt, -ret));
96  return;
97  }
98  }
99 
100  /* has to come from someone and be directed to someone */
101  if(pkt->from == NULL || pkt->to == NULL) {
103  return;
104  }
105 
106  /* packet is for the sm itself */
107  if(*pkt->to->node == '\0') {
108  ret = mm_pkt_sm(pkt->sm->mm, pkt);
109  switch(ret) {
110  case mod_HANDLED:
111  break;
112 
113  case mod_PASS:
114  /* ignore IQ result packets that haven't been handled - XMPP 9.2.3.4 */
115  if(pkt->type == pkt_IQ_RESULT) {
116  pkt_free(pkt);
117  break;
118  } else
120 
121  default:
122  pkt_router(pkt_error(pkt, -ret));
123 
124  break;
125  }
126 
127  return;
128  }
129 
130  /* get the user */
131  user = user_load(sm, pkt->to);
132  if(user == NULL) {
133  if(pkt->type & pkt_PRESENCE && pkt->type != pkt_PRESENCE_PROBE) {
134  pkt_free(pkt);
135  return;
136  }
137 
138  if(pkt->type == pkt_PRESENCE_PROBE) {
139  pkt_router(pkt_create(pkt->sm, "presence", "unsubscribed", jid_full(pkt->from), jid_full(pkt->to)));
140  pkt_free(pkt);
141  return;
142  }
143 
145  return;
146  }
147 
148  if (pkt->sm != NULL) {
149  ret = mm_pkt_user(pkt->sm->mm, user, pkt);
150  switch(ret) {
151  case mod_HANDLED:
152  break;
153 
154  case mod_PASS:
155  /* ignore IQ result packets that haven't been handled - XMPP 9.2.3.4 */
156  if(pkt->type == pkt_IQ_RESULT) {
157  pkt_free(pkt);
158  break;
159  } else
161 
162  default:
163  pkt_router(pkt_error(pkt, -ret));
164 
165  break;
166  }
167  }
168 
169  /* if they have no sessions, they were only loaded to do delivery, so free them */
170  if(user->sessions == NULL)
171  user_free(user);
172 }