1 22 package org.xsocket.stream.io.impl; 23 24 25 import java.io.IOException ; 26 import java.nio.ByteBuffer ; 27 import java.util.LinkedList ; 28 import java.util.logging.Level ; 29 import java.util.logging.Logger ; 30 31 import javax.net.ssl.SSLContext; 32 33 import org.xsocket.ByteBufferQueue; 34 import org.xsocket.ClosedConnectionException; 35 import org.xsocket.stream.io.spi.IIoHandlerCallback; 36 37 38 39 40 45 final class IoActivateableSSLHandler extends ChainableIoHandler implements SSLProcessor.EventHandler { 46 47 48 private static final Logger LOG = Logger.getLogger(IoSSLHandler.class.getName()); 49 50 private enum Mode { OFF, NON_RECEIVING, NON_RECEIVING_AND_WRITING, SSL }; 51 52 private Mode mode = Mode.OFF; 53 54 55 private final ByteBufferQueue inNetDataQueue = new ByteBufferQueue(); 57 private final ByteBufferQueue outAppDataQueue = new ByteBufferQueue(); 58 private final ByteBufferQueue inAppDataQueue = new ByteBufferQueue(); 59 60 private final IOEventHandler ioEventHandler = new IOEventHandler(); 62 63 private SSLProcessor sslProcessor = null; 65 66 67 68 69 78 IoActivateableSSLHandler(ChainableIoHandler successor, SSLContext sslContext,boolean isClientMode, IMemoryManager memoryManager) throws IOException { 79 super(successor); 80 81 sslProcessor = new SSLProcessor(sslContext, isClientMode, memoryManager, this); 82 } 83 84 85 public void init(IIoHandlerCallback callbackHandler) throws IOException { 86 setPreviousCallback(callbackHandler); 87 getSuccessor().init(ioEventHandler); 88 } 89 90 91 94 public void setPreviousCallback(IIoHandlerCallback callbackHandler) { 95 super.setPreviousCallback(callbackHandler); 96 getSuccessor().setPreviousCallback(ioEventHandler); 97 } 98 99 100 103 public final void close(boolean immediate) throws IOException { 104 if (!immediate) { 105 flushOutgoing(); 106 } 107 108 getSuccessor().close(immediate); 109 } 110 111 112 public boolean isSSLActivated() { 113 return (mode == Mode.SSL); 114 } 115 116 117 120 @Override 121 public int getPendingWriteDataSize() { 122 return outAppDataQueue.getSize() + super.getPendingWriteDataSize(); 123 } 124 125 int getPendingReceiveDataSize() { 126 return inAppDataQueue.getSize() + super.getPendingReceiveDataSize(); 127 } 128 129 130 131 134 public final LinkedList <ByteBuffer > drainIncoming() { 135 if (mode == Mode.OFF) { 136 return getSuccessor().drainIncoming(); 137 } else { 138 return inAppDataQueue.drain(); 139 } 140 } 141 142 143 144 145 146 147 150 public final void writeOutgoing(ByteBuffer buffer) throws ClosedConnectionException, IOException { 151 LinkedList <ByteBuffer > buffers = new LinkedList <ByteBuffer >(); 152 buffers.add(buffer); 153 writeOutgoing(buffers); 154 } 155 156 157 158 161 public final void writeOutgoing(LinkedList <ByteBuffer > buffers) throws ClosedConnectionException, IOException { 162 outAppDataQueue.append(buffers); 163 flushOutgoing(); 164 } 165 166 169 public void flushOutgoing() throws IOException { 170 if (mode == Mode.SSL) { 171 synchronized (sslProcessor) { 172 if (sslProcessor.isHandshaking()) { 173 sslProcessor.processOutAppData(); 174 175 } else { 176 if (!outAppDataQueue.isEmpty()) { 177 sslProcessor.processOutAppData(outAppDataQueue.drain()); 178 } 179 } 180 } 181 182 183 } else if ((mode == Mode.OFF) || (mode == Mode.NON_RECEIVING)) { 184 LinkedList <ByteBuffer > data = outAppDataQueue.drain(); 185 getSuccessor().writeOutgoing(data); 186 } 187 } 188 189 190 public boolean preStartSecuredMode() { 191 if (mode == Mode.OFF) { 192 mode = Mode.NON_RECEIVING; 193 return true; 194 195 } else { 196 LOG.warning("connection is already in ssl mode (mode=" + mode + "). Ignore (pre)startSecured Mode"); 197 return false; 198 } 199 } 200 201 202 211 public void startSecuredMode(LinkedList <ByteBuffer > data) throws IOException { 212 if (mode != Mode.NON_RECEIVING) { 213 LOG.warning("connection is not in non_receiving mode (mode=" + mode + ")"); 214 return; 215 } 216 217 mode = Mode.NON_RECEIVING_AND_WRITING; 218 219 inNetDataQueue.addFirst(data); 220 221 sslProcessor.start(); 222 mode = Mode.SSL; 223 224 flushOutgoing(); 225 readIncomingEncryptedData(); 226 } 227 228 229 230 public void onHandshakeFinished() throws IOException { 231 flushOutgoing(); 232 readIncomingEncryptedData(); 233 } 234 235 236 protected final void readIncomingEncryptedData() throws ClosedConnectionException, IOException { 237 inNetDataQueue.append(getSuccessor().drainIncoming()); 238 readIncomingEncryptedData(inNetDataQueue.drain()); 239 } 240 241 242 243 private synchronized void readIncomingEncryptedData(LinkedList <ByteBuffer > inNetDataList) throws ClosedConnectionException, IOException { 244 if (inNetDataList != null) { 245 if (LOG.isLoggable(Level.FINE)) { 246 int size = 0; 247 for (ByteBuffer buffer : inNetDataList) { 248 size += buffer.remaining(); 249 } 250 251 LOG.fine("received " + size + " bytes encrypted data"); 252 } 253 254 sslProcessor.processInNetData(inNetDataList); 255 } 256 } 257 258 259 public void onSSLProcessorClosed() throws IOException { 260 close(true); 261 } 262 263 public void onInAppDataReceived(LinkedList <ByteBuffer > appDataList) { 264 inAppDataQueue.append(appDataList); 265 266 if (!inAppDataQueue.isEmpty()) { 267 getPreviousCallback().onDataRead(); 268 } 269 } 270 271 272 public void onOutNetDataToWrite(ByteBuffer netData) throws IOException { 273 if (netData.hasRemaining()) { 274 getSuccessor().writeOutgoing(netData); 275 } 276 } 277 278 279 280 private final class IOEventHandler implements IIoHandlerCallback { 281 282 public void onDataRead() { 283 try { 284 if (mode == Mode.OFF) { 285 getPreviousCallback().onDataRead(); 286 287 } else if (mode == Mode.SSL) { 288 readIncomingEncryptedData(); 289 290 } else { 291 assert (mode == Mode.NON_RECEIVING) || (mode == Mode.NON_RECEIVING_AND_WRITING); 292 return; 293 } 294 } catch (Exception e) { 295 if (LOG.isLoggable(Level.FINE)) { 296 LOG.fine("[" + getId() + "] error occured while receiving data. Reason: " + e.toString()); 297 } 298 } 299 } 300 301 public void onConnect() { 302 getPreviousCallback().onConnect(); 303 } 304 305 public void onWriteException(IOException ioException) { 306 getPreviousCallback().onWriteException(ioException); 307 } 308 309 public void onWritten() { 310 getPreviousCallback().onWritten(); 311 } 312 313 public void onDisconnect() { 314 getPreviousCallback().onDisconnect(); 316 } 317 318 public void onConnectionAbnormalTerminated() { 319 getPreviousCallback().onConnectionAbnormalTerminated(); 320 } 321 322 323 public void onConnectionTimeout() { 324 getPreviousCallback().onConnectionTimeout(); 325 } 326 327 public void onIdleTimeout() { 328 getPreviousCallback().onIdleTimeout(); 329 } 330 } 331 } 332 | Popular Tags |