public void process()

in server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategy.java [66:129]


    public void process(Stanza failedToDeliverStanza, List<DeliveryException> deliveryExceptions)
            throws DeliveryException {
        StanzaErrorCondition stanzaErrorCondition = StanzaErrorCondition.SERVICE_UNAVAILABLE;
        StanzaErrorType errorType = StanzaErrorType.CANCEL;

        XMPPCoreStanza failedCoreStanza = XMPPCoreStanza.getWrapper(failedToDeliverStanza);

        // Not a core stanza
        if (failedCoreStanza == null) {
            throw new DeliveryException("could not return to sender");
        }

        if ("error".equals(failedCoreStanza.getType())) {
            return; // do not answer these
        }

        if (deliveryExceptions == null) {
            XMPPCoreStanza error = XMPPCoreStanza.getWrapper(ServerErrorResponses.getStanzaError(stanzaErrorCondition,
                    failedCoreStanza, errorType, "stanza could not be delivered", "en", null));
            stanzaBroker.write(error.getTo(), error, IgnoreFailureStrategy.INSTANCE);
        } else if (deliveryExceptions.size() == 1) {
            DeliveryException deliveryException = deliveryExceptions.get(0);
            if (deliveryException instanceof LocalRecipientOfflineException) {
                // TODO implement 8.2.3 here
                stanzaErrorCondition = StanzaErrorCondition.RECIPIENT_UNAVAILABLE;
                if (failedCoreStanza instanceof MessageStanza || failedCoreStanza instanceof IQStanza) {
                    // RFC3921bis#8.1: message and IQ must return service unavailable
                    stanzaErrorCondition = StanzaErrorCondition.SERVICE_UNAVAILABLE;
                }
            } else if (deliveryException instanceof NoSuchLocalUserException) {
                // RFC3921bis#8.1: message and IQ must return service unavailable
                stanzaErrorCondition = StanzaErrorCondition.SERVICE_UNAVAILABLE;
                if (failedCoreStanza instanceof PresenceStanza) {
                    final PresenceStanzaType presenceStanzaType = ((PresenceStanza) failedCoreStanza).getPresenceType();
                    if (presenceStanzaType == null || presenceStanzaType == SUBSCRIBED
                            || presenceStanzaType == UNSUBSCRIBE || presenceStanzaType == UNSUBSCRIBED
                            || presenceStanzaType == UNAVAILABLE || presenceStanzaType == ERROR) {
                        return; // silently ignore
                    }
                    // TODO what happens with PROBE? 8.1 is silent here, but see 4.3
                    if (presenceStanzaType == SUBSCRIBE) {
                        // return UNSUBSCRIBED
                        final Entity from = failedToDeliverStanza.getTo(); // reverse from/to
                        final Entity to = failedToDeliverStanza.getFrom(); // reverse from/to
                        StanzaBuilder builder = StanzaBuilder.createPresenceStanza(from, to, null, UNSUBSCRIBED, null,
                                null);
                        final Stanza finalStanza = builder.build();
                        stanzaBroker.write(to, finalStanza, IgnoreFailureStrategy.INSTANCE);
                        return;
                    }
                }
            } else if (deliveryException instanceof SmartDeliveryException) {
                // RFC3921bis#10.4.3: return remote server error to sender
                SmartDeliveryException smartDeliveryException = (SmartDeliveryException) deliveryException;
                XMPPCoreStanza error = XMPPCoreStanza.getWrapper(
                        ServerErrorResponses.getStanzaError(smartDeliveryException.getStanzaErrorCondition(),
                                failedCoreStanza, smartDeliveryException.getStanzaErrorType(),
                                smartDeliveryException.getErrorText(), "en", null));
                stanzaBroker.write(error.getTo(), error, IgnoreFailureStrategy.INSTANCE);
            }
        } else if (deliveryExceptions.size() > 1) {
            throw new RuntimeException("cannot return to sender for multiple failed deliveries");
        }
    }