if (!(failedToDeliverStanza instanceof XMPPCoreStanza)) {
throw new DeliveryException("could not return to sender");
}
XMPPCoreStanza failedCoreStanza = (XMPPCoreStanza) failedToDeliverStanza;
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));
stanzaRelay.relay(error.getTo(), error, IgnoreFailureStrategy.IGNORE_FAILURE_STRATEGY);
} 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();
stanzaRelay.relay(to, finalStanza, IgnoreFailureStrategy.IGNORE_FAILURE_STRATEGY);
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));
stanzaRelay.relay(error.getTo(), error, IgnoreFailureStrategy.IGNORE_FAILURE_STRATEGY);
}
} else if (deliveryExceptions.size() > 1) {
throw new RuntimeException("cannot return to sender for multiple failed deliveries");
}
}