mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-09-27 18:19:33 +02:00
57961a8cc1
This continues the design started with e98d42790
("SmackReactor/NIO,
Java8/Android19, Pretty print XML, FSM connections"), where the
exceptions that caused an operation to fail, are not recorded within
SynchronizationPoint but within the connection instance itself.
130 lines
6.1 KiB
Java
130 lines
6.1 KiB
Java
/**
|
|
*
|
|
* Copyright 2018-2020 Florian Schmaus
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.jivesoftware.smack.compression;
|
|
|
|
import org.jivesoftware.smack.ConnectionConfiguration;
|
|
import org.jivesoftware.smack.SmackException;
|
|
import org.jivesoftware.smack.XMPPException;
|
|
import org.jivesoftware.smack.XmppInputOutputFilter;
|
|
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection.AuthenticatedButUnboundStateDescriptor;
|
|
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection.ResourceBindingStateDescriptor;
|
|
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionModule;
|
|
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
|
|
import org.jivesoftware.smack.c2s.internal.WalkStateGraphContext;
|
|
import org.jivesoftware.smack.compress.packet.Compress;
|
|
import org.jivesoftware.smack.compress.packet.Compressed;
|
|
import org.jivesoftware.smack.compress.packet.Failure;
|
|
import org.jivesoftware.smack.fsm.State;
|
|
import org.jivesoftware.smack.fsm.StateDescriptor;
|
|
import org.jivesoftware.smack.fsm.StateTransitionResult;
|
|
|
|
public class CompressionModule extends ModularXmppClientToServerConnectionModule<CompressionModuleDescriptor> {
|
|
|
|
protected CompressionModule(CompressionModuleDescriptor moduleDescriptor,
|
|
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
|
super(moduleDescriptor, connectionInternal);
|
|
}
|
|
|
|
public static final class CompressionStateDescriptor extends StateDescriptor {
|
|
private CompressionStateDescriptor() {
|
|
super(CompressionModule.CompressionState.class, 138);
|
|
addPredeccessor(AuthenticatedButUnboundStateDescriptor.class);
|
|
addSuccessor(AuthenticatedButUnboundStateDescriptor.class);
|
|
declarePrecedenceOver(ResourceBindingStateDescriptor.class);
|
|
}
|
|
|
|
@Override
|
|
protected CompressionModule.CompressionState constructState(ModularXmppClientToServerConnectionInternal connectionInternal) {
|
|
CompressionModule compressionModule = connectionInternal.connection.getConnectionModuleFor(CompressionModuleDescriptor.class);
|
|
return compressionModule.constructCompressionState(this, connectionInternal);
|
|
}
|
|
}
|
|
|
|
private static final class CompressionState extends State {
|
|
private XmppCompressionFactory selectedCompressionFactory;
|
|
private XmppInputOutputFilter usedXmppInputOutputCompressionFitler;
|
|
|
|
private CompressionState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) {
|
|
super(stateDescriptor, connectionInternal);
|
|
}
|
|
|
|
@Override
|
|
public StateTransitionResult.TransitionImpossible isTransitionToPossible(
|
|
WalkStateGraphContext walkStateGraphContext) {
|
|
final ConnectionConfiguration config = connectionInternal.connection.getConfiguration();
|
|
if (!config.isCompressionEnabled()) {
|
|
return new StateTransitionResult.TransitionImpossibleReason("Stream compression disabled by connection configuration");
|
|
}
|
|
|
|
Compress.Feature compressFeature = connectionInternal.connection.getFeature(Compress.Feature.ELEMENT, Compress.NAMESPACE);
|
|
if (compressFeature == null) {
|
|
return new StateTransitionResult.TransitionImpossibleReason("Stream compression not supported or enabled by service");
|
|
}
|
|
|
|
selectedCompressionFactory = XmppCompressionManager.getBestFactory(compressFeature);
|
|
if (selectedCompressionFactory == null) {
|
|
return new StateTransitionResult.TransitionImpossibleReason(
|
|
"No matching compression factory for " + compressFeature.getMethods());
|
|
}
|
|
|
|
usedXmppInputOutputCompressionFitler = selectedCompressionFactory.fabricate(config);
|
|
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public StateTransitionResult.AttemptResult transitionInto(WalkStateGraphContext walkStateGraphContext)
|
|
throws InterruptedException, SmackException, XMPPException {
|
|
final String compressionMethod = selectedCompressionFactory.getCompressionMethod();
|
|
connectionInternal.sendAndWaitForResponse(new Compress(compressionMethod), Compressed.class, Failure.class);
|
|
|
|
connectionInternal.addXmppInputOutputFilter(usedXmppInputOutputCompressionFitler);
|
|
|
|
connectionInternal.newStreamOpenWaitForFeaturesSequence("server stream features after compression enabled");
|
|
|
|
connectionInternal.setCompressionEnabled(true);
|
|
|
|
return new CompressionTransitionSuccessResult(compressionMethod);
|
|
}
|
|
|
|
@Override
|
|
public void resetState() {
|
|
selectedCompressionFactory = null;
|
|
usedXmppInputOutputCompressionFitler = null;
|
|
connectionInternal.setCompressionEnabled(false);
|
|
}
|
|
}
|
|
|
|
public static final class CompressionTransitionSuccessResult extends StateTransitionResult.Success {
|
|
private final String compressionMethod;
|
|
|
|
private CompressionTransitionSuccessResult(String compressionMethod) {
|
|
super(compressionMethod + " compression enabled");
|
|
this.compressionMethod = compressionMethod;
|
|
}
|
|
|
|
public String getCompressionMethod() {
|
|
return compressionMethod;
|
|
}
|
|
}
|
|
|
|
public CompressionState constructCompressionState(CompressionStateDescriptor compressionStateDescriptor,
|
|
ModularXmppClientToServerConnectionInternal connectionInternal) {
|
|
return new CompressionState(compressionStateDescriptor, connectionInternal);
|
|
}
|
|
}
|