jabberd2
2.2.17
Main Page
Data Structures
Files
File List
Globals
sm
mod_presence.c
Go to the documentation of this file.
1
/*
2
* jabberd - Jabber Open Source Server
3
* Copyright (c) 2002 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
static
mod_ret_t
_presence_in_sess
(
mod_instance_t
mi,
sess_t
sess,
pkt_t
pkt) {
32
/* only handle presence */
33
if
(!(pkt->
type
&
pkt_PRESENCE
))
34
return
mod_PASS
;
35
36
/* reset from if necessary */
37
if
(pkt->
from
== NULL ||
jid_compare_user
(pkt->
from
, sess->
jid
) != 0) {
38
if
(pkt->
from
!= NULL)
39
jid_free
(pkt->
from
);
40
41
pkt->
from
=
jid_dup
(sess->
jid
);
42
nad_set_attr
(pkt->
nad
, 1, -1,
"from"
,
jid_full
(pkt->
from
), 0);
43
}
44
45
/* presence broadcast (T1, T2, T3) */
46
if
(pkt->
to
== NULL)
47
pres_update
(sess, pkt);
48
49
/* directed presence (T7, T8) */
50
else
51
pres_deliver
(sess, pkt);
52
53
return
mod_HANDLED
;
54
}
55
56
/* drop incoming presence if the user isn't around,
57
* so we don't have to load them during broadcasts */
58
mod_ret_t
_presence_in_router
(
mod_instance_t
mi,
pkt_t
pkt) {
59
user_t
user;
60
sess_t
sess;
61
62
/* only check presence to users, pass presence to sm and probes */
63
if
(!(pkt->
type
&
pkt_PRESENCE
) || pkt->
to
->
node
[0] ==
'\0'
|| pkt->
type
==
pkt_PRESENCE_PROBE
)
64
return
mod_PASS
;
65
66
/* get the user _without_ doing a load */
67
user =
xhash_get
(mi->
mod
->
mm
->
sm
->
users
,
jid_user
(pkt->
to
));
68
69
/* no user, or no sessions, bail */
70
if
(user == NULL || user->
sessions
== NULL) {
71
pkt_free
(pkt);
72
return
mod_HANDLED
;
73
}
74
75
/* only pass if there's at least one available session */
76
for
(sess = user->
sessions
; sess != NULL; sess = sess->
next
)
77
if
(sess->
available
)
78
return
mod_PASS
;
79
80
/* no available sessions, drop */
81
pkt_free
(pkt);
82
83
return
mod_HANDLED
;
84
}
85
87
static
mod_ret_t
_presence_pkt_user
(
mod_instance_t
mi,
user_t
user,
pkt_t
pkt) {
88
sess_t
sess;
89
90
/* only handle presence */
91
if
(!(pkt->
type
&
pkt_PRESENCE
))
92
return
mod_PASS
;
93
94
/* errors get tracked, but still delivered (T6) */
95
if
(pkt->
type
&
pkt_ERROR
) {
96
/* find the session */
97
sess =
sess_match
(user, pkt->
to
->
resource
);
98
if
(sess == NULL) {
99
log_debug
(
ZONE
,
"bounced presence, but no corresponding session anymore, dropping"
);
100
pkt_free
(pkt);
101
return
mod_HANDLED
;
102
}
103
104
log_debug
(
ZONE
,
"bounced presence, tracking"
);
105
pres_error
(sess, pkt->
from
);
106
107
/* bounced probes get dropped */
108
if
((pkt->
type
&
pkt_PRESENCE_PROBE
) ==
pkt_PRESENCE_PROBE
) {
109
pkt_free
(pkt);
110
return
mod_HANDLED
;
111
}
112
}
113
114
/* if there's a resource, send it direct */
115
if
(pkt->
to
->
resource
[0] !=
'\0'
) {
116
sess =
sess_match
(user, pkt->
to
->
resource
);
117
if
(sess == NULL) {
118
/* resource isn't online - XMPP-IM 11.3 requires we ignore it*/
119
pkt_free
(pkt);
120
return
mod_HANDLED
;
121
}
122
123
pkt_sess
(pkt, sess);
124
return
mod_HANDLED
;
125
}
126
127
/* remote presence updates (T4, T5) */
128
pres_in
(user, pkt);
129
130
return
mod_HANDLED
;
131
}
132
133
/* presence packets to the sm */
134
static
mod_ret_t
_presence_pkt_sm
(
mod_instance_t
mi,
pkt_t
pkt) {
135
module_t
mod = mi->
mod
;
136
jid_t
smjid;
137
138
/* only check presence/subs to server JID */
139
if
(!(pkt->
type
&
pkt_PRESENCE
|| pkt->
type
&
pkt_S10N
))
140
return
mod_PASS
;
141
142
smjid =
jid_new
(
jid_user
(pkt->
to
), -1);
143
144
/* handle subscription requests */
145
if
(pkt->
type
==
pkt_S10N
) {
146
log_debug
(
ZONE
,
"accepting subscription request from %s"
,
jid_full
(pkt->
from
));
147
148
/* accept request */
149
pkt_router
(
pkt_create
(mod->
mm
->
sm
,
"presence"
,
"subscribed"
,
jid_user
(pkt->
from
),
jid_user
(smjid)));
150
151
/* and subscribe back to theirs */
152
pkt_router
(
pkt_create
(mod->
mm
->
sm
,
"presence"
,
"subscribe"
,
jid_user
(pkt->
from
),
jid_user
(smjid)));
153
154
pkt_free
(pkt);
155
jid_free
(smjid);
156
return
mod_HANDLED
;
157
}
158
159
/* handle unsubscribe requests */
160
if
(pkt->
type
==
pkt_S10N_UN
) {
161
log_debug
(
ZONE
,
"accepting unsubscribe request from %s"
,
jid_full
(pkt->
from
));
162
163
/* ack the request */
164
pkt_router
(
pkt_create
(mod->
mm
->
sm
,
"presence"
,
"unsubscribed"
,
jid_user
(pkt->
from
),
jid_user
(smjid)));
165
166
pkt_free
(pkt);
167
jid_free
(smjid);
168
return
mod_HANDLED
;
169
}
170
171
/* drop the rest */
172
log_debug
(
ZONE
,
"dropping presence from %s"
,
jid_full
(pkt->
from
));
173
pkt_free
(pkt);
174
jid_free
(smjid);
175
return
mod_HANDLED
;
176
177
}
178
179
static
void
_presence_free
(
module_t
mod) {
180
feature_unregister
(mod->
mm
->
sm
,
"presence"
);
181
}
182
183
DLLEXPORT
int
module_init
(
mod_instance_t
mi,
char
*arg) {
184
module_t
mod = mi->
mod
;
185
186
if
(mod->
init
)
return
0;
187
188
mod->
in_sess
=
_presence_in_sess
;
189
mod->
in_router
=
_presence_in_router
;
190
mod->
pkt_user
=
_presence_pkt_user
;
191
mod->
pkt_sm
=
_presence_pkt_sm
;
192
mod->
free
=
_presence_free
;
193
194
feature_register
(mod->
mm
->
sm
,
"presence"
);
195
196
return
0;
197
}
Generated by
1.8.1.1