1 /** 2 * Copyright (c) 2012, University of Konstanz, Distributed Systems Group All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 * following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of 6 * conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, 7 * this list of conditions and the following disclaimer in the documentation and/or other materials provided with the 8 * distribution. * Neither the name of the University of Konstanz nor the names of its contributors may be used to 9 * endorse or promote products derived from this software without specific prior written permission. 10 * 11 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 12 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 13 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 14 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 15 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 17 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 */ 19 package org.jscsi.initiator.connection; 20 21 22 import java.io.IOException; 23 import java.net.InetSocketAddress; 24 import java.security.DigestException; 25 import java.util.Queue; 26 27 import org.jscsi.exception.InternetSCSIException; 28 import org.jscsi.exception.NoSuchSessionException; 29 import org.jscsi.exception.OperationalTextKeyException; 30 import org.jscsi.initiator.Configuration; 31 import org.jscsi.initiator.connection.state.IState; 32 import org.jscsi.parser.ProtocolDataUnit; 33 import org.jscsi.parser.datasegment.OperationalTextKey; 34 import org.jscsi.parser.datasegment.SettingsMap; 35 import org.jscsi.utils.SerialArithmeticNumber; 36 import org.slf4j.Logger; 37 import org.slf4j.LoggerFactory; 38 39 40 /** 41 * <h1>AbsConnection</h1> 42 * <p/> 43 * This abstract class represents a connection, which is used in the iSCSI Standard (RFC3720). Such a connection is 44 * directed from the initiator to the target. It is used in Sessions. 45 * 46 * @author Volker Wildi, University of Konstanz 47 * @author Patrice Matthias Brend'amour, University of Konstanz 48 * @author Sebastian Graf, University of Konstanz 49 */ 50 public final class Connection { 51 52 // -------------------------------------------------------------------------- 53 // -------------------------------------------------------------------------- 54 55 /** The logger interface. */ 56 private static final Logger LOGGER = LoggerFactory.getLogger(Connection.class); 57 58 // -------------------------------------------------------------------------- 59 // -------------------------------------------------------------------------- 60 61 /** 62 * The <code>Session</code> instance, which contains this <code>Connection</code> instance. 63 */ 64 private final Session referenceSession; 65 66 /** The <code>Configuration</code> instance for this connection. */ 67 private final Configuration configuration; 68 69 /** The current state of this connection. */ 70 private IState state; 71 72 /** 73 * The ID of this connection. This must be unique within a <code>Session</code>. 74 */ 75 private final short connectionID; 76 77 /** 78 * The Expected Status Sequence Number, which is expected to received from the target within this connection. 79 */ 80 private final SerialArithmeticNumber expectedStatusSequenceNumber; 81 82 // -------------------------------------------------------------------------- 83 // -------------------------------------------------------------------------- 84 85 /** 86 * The worker caller, which handles the transmission of the packages over the network. 87 */ 88 private final SenderWorker senderReceiver; 89 90 /** 91 * Method to create and return a new, empty <code>Connection</code> object with the configured layer of threading. 92 * 93 * @param session Reference to the <code>AbsSession</code> object, which contains this connection. 94 * @param initConfiguration The configuration to use within this connection. 95 * @param inetAddress The <code>InetSocketAddress</code> to which this connection should established. 96 * @param initConnectionID The ID of this connection. 97 * @throws Exception If any error occurs. 98 */ 99 100 public Connection (final Session session, final Configuration initConfiguration, final InetSocketAddress inetAddress, final short initConnectionID) throws Exception { 101 102 senderReceiver = new SenderWorker(this, inetAddress); 103 104 configuration = initConfiguration; 105 connectionID = initConnectionID; 106 107 referenceSession = session; 108 expectedStatusSequenceNumber = new SerialArithmeticNumber(); 109 110 } 111 112 /** 113 * Updates all entries of the given response key-values with the stored settings of this instance. 114 * 115 * @param response The settings of the response. 116 * @throws NoSuchSessionException if a session with this target name is not open. 117 */ 118 public final void update (final SettingsMap response) throws NoSuchSessionException { 119 120 configuration.update(referenceSession.getTargetName(), connectionID, response); 121 } 122 123 /** 124 * Returns the value of the given parameter, which is parsed to an <code>boolean</code>. 125 * 126 * @param textKey The name of the parameter. 127 * @return The <code>boolean</code> value of this parameter. So if the value is equal to <code>Yes</code>, then 128 * <code>true</code> will be returned. Else <code>false</code> is returned. 129 * @throws OperationalTextKeyException If the given parameter cannot be found. 130 */ 131 public final boolean getSettingAsBoolean (final OperationalTextKey textKey) throws OperationalTextKeyException { 132 return getSetting(textKey).compareTo("Yes") == 0; 133 } 134 135 /** 136 * Returns the value of the given parameter, which is parsed to an <code>integer</code>. 137 * 138 * @param textKey The name of the parameter. 139 * @return The <code>integer</code> value of this parameter. 140 * @throws OperationalTextKeyException If the given parameter cannot be found. 141 */ 142 public final int getSettingAsInt (final OperationalTextKey textKey) throws OperationalTextKeyException { 143 144 return Integer.parseInt(getSetting(textKey)); 145 } 146 147 /** 148 * Returns the value of the given parameter as <code>String</code>. 149 * 150 * @param textKey The name of the parameter. 151 * @return The value of this parameter. 152 * @throws OperationalTextKeyException If the given parameter cannot be found. 153 */ 154 public final String getSetting (final OperationalTextKey textKey) throws OperationalTextKeyException { 155 156 return configuration.getSetting(referenceSession.getTargetName(), connectionID, textKey); 157 } 158 159 /** 160 * Returns the settings of the given session and connection. 161 * 162 * @return The settings of this specific connection. 163 */ 164 public final SettingsMap getSettings () { 165 166 return configuration.getSettings(referenceSession.getTargetName(), connectionID); 167 } 168 169 // -------------------------------------------------------------------------- 170 // -------------------------------------------------------------------------- 171 172 /** 173 * Increments the Expected Status Sequence Number as defined in RFC1982 where <code>SERIAL_BITS = 32</code>. 174 */ 175 public final void incrementExpectedStatusSequenceNumber () { 176 177 expectedStatusSequenceNumber.increment(); 178 } 179 180 /** 181 * Returns the Expected Status Sequence Number of this <code>Connection</code> object. 182 * 183 * @return The current Expected Status Sequence Number. 184 */ 185 public final SerialArithmeticNumber getExpectedStatusSequenceNumber () { 186 187 return expectedStatusSequenceNumber; 188 } 189 190 /** 191 * Sets the expected Status Sequence Number to the given one from the leading Login Response. 192 * 193 * @param newExpectedStatusSequenceNumber The new value. 194 */ 195 public final void setExpectedStatusSequenceNumber (final int newExpectedStatusSequenceNumber) { 196 197 expectedStatusSequenceNumber.setValue(newExpectedStatusSequenceNumber); 198 199 LOGGER.trace("Set ExpStatSN to " + expectedStatusSequenceNumber); 200 } 201 202 // -------------------------------------------------------------------------- 203 // -------------------------------------------------------------------------- 204 205 /** 206 * Switch to the new state. Start point of the state pattern. All states are computed one after another. 207 * 208 * @param newState The new state. 209 * @throws InternetSCSIException of any kind 210 */ 211 public final void nextState (final IState newState) throws InternetSCSIException { 212 213 this.state = newState; 214 if (this.state != null) { 215 do { 216 this.state.execute(); 217 LOGGER.info("State is following: " + this.state.nextStateFollowing()); 218 } while (this.state.nextStateFollowing()); 219 } 220 221 } 222 223 /** 224 * Returns the current state of this connection. 225 * 226 * @return The current <code>IState</code> instance of this <code>Connection</code> instance. 227 */ 228 public final IState getState () { 229 230 return state; 231 } 232 233 /** 234 * Returns the session, which contains this connection instance. 235 * 236 * @return The parent session instance. 237 */ 238 public final Session getSession () { 239 240 return referenceSession; 241 } 242 243 /** 244 * Returns the ID of this <code>Connection</code> object. 245 * 246 * @return The connection ID. 247 */ 248 public final short getConnectionID () { 249 250 return connectionID; 251 } 252 253 // -------------------------------------------------------------------------- 254 // -------------------------------------------------------------------------- 255 256 /** 257 * This method does all the necessary steps, which are needed when a connection should be closed. 258 * 259 * @throws IOException if an I/O error occurs. 260 */ 261 public final void close () throws IOException { 262 263 senderReceiver.close(); 264 LOGGER.debug("Connection with ID " + connectionID + " closed."); 265 } 266 267 /** 268 * Enqueue this protocol data unit to the end of the sending queue. 269 * 270 * @param protocolDataUnit The protocol data unit to add. 271 * @throws InternetSCSIException for nearly everything 272 */ 273 public final void send (final ProtocolDataUnit protocolDataUnit) throws InternetSCSIException { 274 275 try { 276 senderReceiver.sendOverWire(protocolDataUnit); 277 } catch (IOException e) { 278 throw new InternetSCSIException(e); 279 } catch (InterruptedException e) { 280 throw new InternetSCSIException(e); 281 } 282 } 283 284 /** 285 * Enqueue all protocol data units to the end of the sending queue. 286 * 287 * @param protocolDataUnits The list with all protocol data units to add. 288 * @throws InternetSCSIException for nearly everything 289 */ 290 public final void send (final Queue<ProtocolDataUnit> protocolDataUnits) throws InternetSCSIException { 291 292 for (final ProtocolDataUnit unit : protocolDataUnits) { 293 send(unit); 294 } 295 } 296 297 /** 298 * Reads one <code>ProtocolDataUnit</code> instance from the <code>receivingQueue</code>. 299 * 300 * @return An instance of a <code>ProtocolDataUnit</code>. 301 * @throws InternetSCSIException for nearly everything 302 */ 303 public final ProtocolDataUnit receive () throws InternetSCSIException { 304 305 try { 306 return senderReceiver.receiveFromWire(); 307 } catch (DigestException e) { 308 throw new InternetSCSIException(e); 309 } catch (IOException e) { 310 throw new InternetSCSIException(e); 311 } 312 } 313 314 // -------------------------------------------------------------------------- 315 // -------------------------------------------------------------------------- 316 // -------------------------------------------------------------------------- 317 // -------------------------------------------------------------------------- 318 }