1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-22 03:52:06 +01:00

[core] Wrap current connection exception when re-throwing

Instead of directly throwing the current connection exception, wrap
it, so we do not lose the stack trace of the thread invoking
waitForConditionorThrowConnectionException().
This commit is contained in:
Florian Schmaus 2024-10-17 17:34:05 +02:00
parent 3c5fb5810e
commit 9e5ac5a39a
5 changed files with 24 additions and 39 deletions

View file

@ -281,8 +281,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
*/
protected Writer writer;
protected SmackException currentSmackException;
protected XMPPException currentXmppException;
private Exception currentConnectionException;
protected boolean tlsHandled;
@ -511,8 +510,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
public abstract boolean isUsingCompression();
protected void initState() {
currentSmackException = null;
currentXmppException = null;
currentConnectionException = null;
saslFeatureReceived = lastFeaturesReceived = tlsHandled = false;
// TODO: We do not init closingStreamReceived here, as the integration tests use it to check if we waited for
// it.
@ -686,28 +684,12 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
return streamId;
}
protected final void throwCurrentConnectionException() throws SmackException, XMPPException {
if (currentSmackException != null) {
throw currentSmackException;
} else if (currentXmppException != null) {
throw currentXmppException;
}
throw new AssertionError("No current connection exception set, although throwCurrentException() was called");
}
protected final boolean hasCurrentConnectionException() {
return currentSmackException != null || currentXmppException != null;
return currentConnectionException != null;
}
protected final void setCurrentConnectionExceptionAndNotify(Exception exception) {
if (exception instanceof SmackException) {
currentSmackException = (SmackException) exception;
} else if (exception instanceof XMPPException) {
currentXmppException = (XMPPException) exception;
} else {
currentSmackException = new SmackException.SmackWrappedException(exception);
}
currentConnectionException = exception;
notifyWaitingThreads();
}
@ -741,10 +723,12 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
return true;
}
protected final void waitForConditionOrThrowConnectionException(Supplier<Boolean> condition, String waitFor) throws InterruptedException, SmackException, XMPPException {
protected final void waitForConditionOrThrowConnectionException(Supplier<Boolean> condition, String waitFor)
throws InterruptedException, SmackException.SmackWrappedException, NoResponseException {
boolean success = waitFor(() -> condition.get().booleanValue() || hasCurrentConnectionException());
if (hasCurrentConnectionException()) {
throwCurrentConnectionException();
final Exception currentConnectionException = this.currentConnectionException;
if (currentConnectionException != null) {
throw new SmackException.SmackWrappedException(currentConnectionException);
}
// If there was no connection exception and we still did not successfully wait for the condition to hold, then
@ -1048,7 +1032,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
protected final boolean waitForClosingStreamTagFromServer() {
try {
waitForConditionOrThrowConnectionException(() -> closingStreamReceived, "closing stream tag from the server");
} catch (InterruptedException | SmackException | XMPPException e) {
} catch (InterruptedException | SmackException.SmackWrappedException | NoResponseException e) {
LOGGER.log(Level.INFO, "Exception while waiting for closing stream element from the server " + this, e);
return false;
}

View file

@ -39,6 +39,7 @@ import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.OutgoingQueueFullException;
import org.jivesoftware.smack.SmackException.SmackWrappedException;
import org.jivesoftware.smack.SmackFuture;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.FailedNonzaException;
@ -259,7 +260,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
@Override
public void waitForConditionOrThrowConnectionException(Supplier<Boolean> condition, String waitFor)
throws InterruptedException, SmackException, XMPPException {
throws InterruptedException, SmackWrappedException, NoResponseException {
ModularXmppClientToServerConnection.this.waitForConditionOrThrowConnectionException(condition, waitFor);
}
@ -596,8 +597,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
case "error":
StreamError streamError = PacketParserUtils.parseStreamError(parser, null);
StreamErrorException streamErrorException = new StreamErrorException(streamError);
currentXmppException = streamErrorException;
notifyWaitingThreads();
setCurrentConnectionExceptionAndNotify(streamErrorException);
throw streamErrorException;
case "features":
parseFeatures(parser);
@ -1048,8 +1048,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
XmppInputOutputFilter filter = it.next();
try {
filter.waitUntilInputOutputClosed();
} catch (IOException | CertificateException | InterruptedException | SmackException
| XMPPException e) {
} catch (IOException | CertificateException | InterruptedException | SmackException | XMPPException e) {
LOGGER.log(Level.WARNING, "waitUntilInputOutputClosed() threw", e);
}
}

View file

@ -26,6 +26,7 @@ import java.util.Queue;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.SmackWrappedException;
import org.jivesoftware.smack.SmackReactor;
import org.jivesoftware.smack.SmackReactor.ChannelSelectedCallback;
import org.jivesoftware.smack.XMPPException;
@ -127,7 +128,8 @@ public abstract class ModularXmppClientToServerConnectionInternal {
public abstract void asyncGo(Runnable runnable);
public abstract void waitForConditionOrThrowConnectionException(Supplier<Boolean> condition, String waitFor) throws InterruptedException, SmackException, XMPPException;
public abstract void waitForConditionOrThrowConnectionException(Supplier<Boolean> condition, String waitFor)
throws InterruptedException, SmackWrappedException, NoResponseException;
public abstract void notifyWaitingThreads();

View file

@ -889,8 +889,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
if (startTlsFeature != null) {
if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) {
SecurityRequiredByServerException smackException = new SecurityRequiredByServerException();
currentSmackException = smackException;
notifyWaitingThreads();
setCurrentConnectionExceptionAndNotify(smackException);
throw smackException;
}
@ -1020,8 +1019,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
// situation. It is still possible to authenticate and
// use the connection but using an uncompressed connection
// TODO Parse failure stanza
currentSmackException = new SmackException.SmackMessageException("Could not establish compression");
notifyWaitingThreads();
SmackException.SmackMessageException exception = new SmackException.SmackMessageException("Could not establish compression");
setCurrentConnectionExceptionAndNotify(exception);
break;
default:
parseAndProcessNonza(parser);

View file

@ -46,9 +46,11 @@ import javax.net.ssl.SSLSession;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.SecurityRequiredByClientException;
import org.jivesoftware.smack.SmackException.SecurityRequiredByServerException;
import org.jivesoftware.smack.SmackException.SmackCertificateException;
import org.jivesoftware.smack.SmackException.SmackWrappedException;
import org.jivesoftware.smack.SmackFuture;
import org.jivesoftware.smack.SmackFuture.InternalSmackFuture;
import org.jivesoftware.smack.SmackReactor.SelectionKeyAttachment;
@ -1201,7 +1203,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
return handshakeStatus == TlsHandshakeStatus.successful || handshakeStatus == TlsHandshakeStatus.failed;
}
private void waitForHandshakeFinished() throws InterruptedException, CertificateException, SSLException, SmackException, XMPPException {
private void waitForHandshakeFinished() throws InterruptedException, CertificateException, SSLException, SmackWrappedException, NoResponseException {
connectionInternal.waitForConditionOrThrowConnectionException(() -> isHandshakeFinished(), "TLS handshake to finish");
if (handshakeStatus == TlsHandshakeStatus.failed) {
@ -1234,8 +1236,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
}
@Override
public void waitUntilInputOutputClosed() throws IOException, CertificateException, InterruptedException,
SmackException, XMPPException {
public void waitUntilInputOutputClosed() throws IOException, CertificateException, InterruptedException, SmackWrappedException, NoResponseException {
waitForHandshakeFinished();
}