001/** 002 * 003 * Copyright 2018-2021 Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smack.fsm; 018 019import java.io.IOException; 020 021import org.jivesoftware.smack.SmackException; 022import org.jivesoftware.smack.XMPPException; 023import org.jivesoftware.smack.c2s.XmppClientToServerTransport; 024import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal; 025import org.jivesoftware.smack.c2s.internal.WalkStateGraphContext; 026 027/** 028 * Note that this is an non-static inner class of XmppClientToServerConnection so that states can inspect and modify 029 * the connection. 030 */ 031public abstract class State { 032 033 protected final StateDescriptor stateDescriptor; 034 035 protected final ModularXmppClientToServerConnectionInternal connectionInternal; 036 037 protected State(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { 038 this.stateDescriptor = stateDescriptor; 039 this.connectionInternal = connectionInternal; 040 } 041 042 /** 043 * Check if the state should be activated. 044 * 045 * @param walkStateGraphContext the context of the current state graph walk. 046 * @return <code>null</code> if the state should be activated. 047 * @throws SmackException in case a Smack exception occurs. 048 */ 049 public StateTransitionResult.TransitionImpossible isTransitionToPossible(WalkStateGraphContext walkStateGraphContext) 050 throws SmackException { 051 return null; 052 } 053 054 public abstract StateTransitionResult.AttemptResult transitionInto(WalkStateGraphContext walkStateGraphContext) 055 throws IOException, SmackException, InterruptedException, XMPPException; 056 057 public StateDescriptor getStateDescriptor() { 058 return stateDescriptor; 059 } 060 061 public void resetState() { 062 } 063 064 @Override 065 public String toString() { 066 return "State " + stateDescriptor + ' ' + connectionInternal.connection; 067 } 068 069 protected final void ensureNotOnOurWayToAuthenticatedAndResourceBound( 070 WalkStateGraphContext walkStateGraphContext) { 071 if (walkStateGraphContext.isFinalStateAuthenticatedAndResourceBound()) { 072 throw new IllegalStateException( 073 "Smack should never attempt to reach the authenticated and resource bound state over " 074 + this 075 + ". This is probably a programming error within Smack, please report it to the develoeprs."); 076 } 077 } 078 079 public abstract static class AbstractTransport extends State { 080 081 private final XmppClientToServerTransport transport; 082 083 protected AbstractTransport(XmppClientToServerTransport transport, StateDescriptor stateDescriptor, 084 ModularXmppClientToServerConnectionInternal connectionInternal) { 085 super(stateDescriptor, connectionInternal); 086 this.transport = transport; 087 } 088 089 @Override 090 public StateTransitionResult.TransitionImpossible isTransitionToPossible(WalkStateGraphContext walkStateGraphContext) 091 throws SmackException { 092 if (!transport.hasUseableConnectionEndpoints()) { 093 return new StateTransitionResult.TransitionImpossibleBecauseNoEndpointsDiscovered(transport); 094 } 095 096 return super.isTransitionToPossible(walkStateGraphContext); 097 } 098 } 099}