/** * {@inheritDoc} <br> * <br> * Performs processing of <em>presence</em> packets and calls different methods for particular * {@link PresenceType} */ @SuppressWarnings({"unchecked", "fallthrough"}) @Override public void process( final Packet packet, final XMPPResourceConnection session, final NonAuthUserRepository repo, final Queue<Packet> results, final Map<String, Object> settings) throws XMPPException { if (session == null) { if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "Session is null, ignoring packet: {0}", packet); } return; } // end of if (session == null) if (!session.isAuthorized()) { if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "Session is not authorized, ignoring packet: {0}", packet); } return; } // Synchronization to avoid conflict with login/logout events // processed in the SessionManager asynchronously synchronized (session) { try { RosterAbstract.PresenceType pres_type = roster_util.getPresenceType(session, packet); if (pres_type == null) { log.log(Level.INFO, "Invalid presence found: {0}", packet); return; } // end of if (type == null) if (log.isLoggable(Level.FINEST)) { log.log( Level.FINEST, "{0} | {1} presence found: {2}", new Object[] {session.getBareJID().toString(), pres_type, packet}); } // All 'in' subscription presences must have a valid from address switch (pres_type) { case in_unsubscribe: case in_subscribe: case in_unsubscribed: case in_subscribed: if (packet.getStanzaFrom() == null) { if (log.isLoggable(Level.FINE)) { log.fine( "'in' subscription presence without valid 'from' address, " + "dropping packet: " + packet); } return; } if (session.isUserId(packet.getStanzaFrom().getBareJID())) { if (log.isLoggable(Level.FINE)) { log.log( Level.FINE, "''in'' subscription to myself, not allowed, returning " + "error for packet: " + "{0}", packet); } results.offer( Authorization.NOT_ALLOWED.getResponseMessage( packet, "You can not subscribe to yourself.", false)); return; } // as per http://xmpp.org/rfcs/rfc6121.html#sub // Implementation Note: When a server processes or generates an outbound // presence stanza of type "subscribe", "subscribed", "unsubscribe", // or "unsubscribed", the server MUST stamp the outgoing presence // stanza with the bare JID <localpart@domainpart> of the sending entity, // not the full JID <localpart@domainpart/resourcepart>. // // we enforce this rule also for incomming presence subscirption packets packet.initVars( packet.getStanzaFrom().copyWithoutResource(), session.getJID().copyWithoutResource()); break; case out_subscribe: case out_unsubscribe: case out_subscribed: case out_unsubscribed: // Check wheher the destination address is correct to prevent // broken/corrupted roster entries: if ((packet.getStanzaTo() == null) || packet.getStanzaTo().toString().isEmpty()) { results.offer( Authorization.JID_MALFORMED.getResponseMessage( packet, "The destination address is incorrect.", false)); return; } // According to RFC 3921 draft bis-3, both source and destination // addresses must be BareJIDs, handled by initVars(...) packet.initVars( session.getJID().copyWithoutResource(), packet.getStanzaTo().copyWithoutResource()); break; default: break; } switch (pres_type) { case out_subscribe: case out_unsubscribe: processOutSubscribe(packet, session, results, settings, pres_type); break; case out_subscribed: case out_unsubscribed: processOutSubscribed(packet, session, results, settings, pres_type); break; case in_subscribe: processInSubscribe(packet, session, results, settings, pres_type); break; case in_unsubscribe: processInUnsubscribe(packet, session, results, settings, pres_type); break; case in_subscribed: processInSubscribed(packet, session, results, settings, pres_type); break; case in_unsubscribed: processInUnsubscribed(packet, session, results, settings, pres_type); break; default: results.offer( Authorization.BAD_REQUEST.getResponseMessage( packet, "Request type is incorrect", false)); break; } // end of switch (type) } catch (NotAuthorizedException e) { log.log( Level.INFO, "Can not access user Roster, user session is not authorized yet: {0}", packet); log.log(Level.FINEST, "presence problem...", e); } catch (TigaseDBException e) { log.log(Level.WARNING, "Error accessing database for presence data: {0}", e); } // end of try-catch } }