1 /* 2 * Copyright (C) 2007-2009 Jive Software and Ignite Realtime Community 2021. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.jivesoftware.openfire.session; 18 19 import org.jivesoftware.util.TaskEngine; 20 import org.jivesoftware.util.cache.ClusterTask; 21 import org.jivesoftware.util.cache.ExternalizableUtil; 22 import org.slf4j.Logger; 23 import org.slf4j.LoggerFactory; 24 25 import java.io.IOException; 26 import java.io.ObjectInput; 27 import java.io.ObjectOutput; 28 import java.net.UnknownHostException; 29 import java.util.concurrent.Future; 30 import java.util.concurrent.TimeUnit; 31 32 /** 33 * Operations to be executed in a remote session hosted in a remote cluster node. 34 * 35 * @author Gaston Dombiak 36 */ 37 public abstract class RemoteSessionTask implements ClusterTask<Object> { 38 private static final Logger Log = LoggerFactory.getLogger(RemoteSessionTask.class); 39 40 protected Object result; 41 protected Operation operation; 42 RemoteSessionTask()43 public RemoteSessionTask() { 44 } 45 RemoteSessionTask(Operation operation)46 protected RemoteSessionTask(Operation operation) { 47 this.operation = operation; 48 } 49 getSession()50 abstract Session getSession(); 51 getResult()52 public Object getResult() { 53 return result; 54 } 55 run()56 public void run() { 57 if (operation == Operation.getStreamID) { 58 result = getSession().getStreamID(); 59 } 60 else if (operation == Operation.getServerName) { 61 result = getSession().getServerName(); 62 } 63 else if (operation == Operation.getCreationDate) { 64 result = getSession().getCreationDate(); 65 } 66 else if (operation == Operation.getLastActiveDate) { 67 result = getSession().getLastActiveDate(); 68 } 69 else if (operation == Operation.getNumClientPackets) { 70 result = getSession().getNumClientPackets(); 71 } 72 else if (operation == Operation.getNumServerPackets) { 73 result = getSession().getNumServerPackets(); 74 } 75 else if (operation == Operation.getCipherSuiteName) { 76 result = getSession().getCipherSuiteName(); 77 } 78 else if (operation == Operation.getPeerCertificates) { 79 result = getSession().getPeerCertificates(); 80 } 81 else if (operation == Operation.getSoftwareVersion) { 82 result = getSession().getSoftwareVersion(); 83 } 84 else if (operation == Operation.close) { 85 // Run in another thread so we avoid blocking calls (in hazelcast) 86 final Session session = getSession(); 87 if (session != null) { 88 final Future<?> future = TaskEngine.getInstance().submit( () -> { 89 try { 90 if (session instanceof LocalSession) { 91 // OF-2311: If closed by another cluster node, chances are that the session needs to be closed forcibly. 92 // Chances of the session being resumed are neglectable, while retaining the session in a detached state 93 // causes problems (eg: IQBindHandler could have re-issued the resource to a replacement session). 94 ((LocalSession) session).getStreamManager().formalClose(); 95 } 96 session.close(); 97 } catch (Exception e) { 98 Log.info("An exception was logged while closing session: {}", session, e); 99 } 100 }); 101 // Wait until the close operation is done or timeout is met 102 try { 103 future.get(15, TimeUnit.SECONDS); 104 } 105 catch (Exception e) { 106 Log.info("An exception was logged while executing RemoteSessionTask to close session: {}", session, e); 107 } 108 } 109 } 110 else if (operation == Operation.isClosed) { 111 result = getSession().isClosed(); 112 } 113 else if (operation == Operation.isSecure) { 114 result = getSession().isSecure(); 115 } 116 else if (operation == Operation.getHostAddress) { 117 try { 118 result = getSession().getHostAddress(); 119 } catch (UnknownHostException e) { 120 Log.error("Error getting address of session: " + getSession(), e); 121 } 122 } 123 else if (operation == Operation.getHostName) { 124 try { 125 result = getSession().getHostName(); 126 } catch (UnknownHostException e) { 127 Log.error("Error getting address of session: " + getSession(), e); 128 } 129 } 130 else if (operation == Operation.validate) { 131 result = getSession().validate(); 132 } 133 } 134 writeExternal(ObjectOutput out)135 public void writeExternal(ObjectOutput out) throws IOException { 136 ExternalizableUtil.getInstance().writeBoolean(out, operation != null); 137 if (operation != null) { 138 ExternalizableUtil.getInstance().writeInt(out, operation.ordinal()); 139 } 140 } 141 readExternal(ObjectInput in)142 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 143 if (ExternalizableUtil.getInstance().readBoolean(in)) { 144 operation = Operation.values()[ExternalizableUtil.getInstance().readInt(in)]; 145 } 146 } 147 148 public enum Operation { 149 /** 150 * Basic session operations 151 */ 152 getStreamID, 153 getServerName, 154 getCreationDate, 155 getLastActiveDate, 156 getNumClientPackets, 157 getNumServerPackets, 158 getCipherSuiteName, 159 getPeerCertificates, 160 getSoftwareVersion, 161 close, 162 isClosed, 163 isSecure, 164 getHostAddress, 165 getHostName, 166 validate, 167 168 /** 169 * Operations of c2s sessions 170 */ 171 isInitialized, 172 incrementConflictCount, 173 hasRequestedBlocklist, 174 175 /** 176 * Operations of outgoing server sessions 177 */ 178 getOutgoingDomainPairs, 179 isUsingServerDialback, 180 181 /** 182 * Operations of external component sessions 183 */ 184 getType, 185 getCategory, 186 getInitialSubdomain, 187 getSubdomains, 188 getName, 189 getDescription, 190 start, 191 shutdown, 192 193 /** 194 * Operations of incoming server sessions 195 */ 196 getLocalDomain, 197 getAddress, 198 getValidatedDomains 199 } 200 } 201