1 22 package org.xsocket.stream.io.impl; 23 24 import java.io.IOException ; 25 import java.nio.ByteBuffer ; 26 import java.util.LinkedList ; 27 import java.util.logging.Level ; 28 import java.util.logging.Logger ; 29 30 import javax.net.ssl.SSLContext; 31 32 import org.xsocket.ByteBufferQueue; 33 import org.xsocket.ClosedConnectionException; 34 import org.xsocket.stream.io.spi.IIoHandlerCallback; 35 36 37 42 final class IoSSLHandler extends ChainableIoHandler implements SSLProcessor.EventHandler { 43 44 private static final Logger LOG = Logger.getLogger(IoSSLHandler.class.getName()); 45 46 private final ByteBufferQueue outAppDataQueue = new ByteBufferQueue(); 48 private final ByteBufferQueue inAppDataQueue = new ByteBufferQueue(); 49 50 51 private final IOEventHandler ioEventHandler = new IOEventHandler(); 52 53 54 private SSLProcessor sslProcessor = null; 56 private boolean isClientMode = false; 57 private boolean isSSLConnected = false; 58 59 60 61 62 71 IoSSLHandler(ChainableIoHandler successor, SSLContext sslContext,boolean isClientMode, IMemoryManager memoryManager) throws IOException { 72 super(successor); 73 74 this.isClientMode = isClientMode; 75 sslProcessor = new SSLProcessor(sslContext, isClientMode, memoryManager, this); 76 } 77 78 79 public void init(IIoHandlerCallback callbackHandler) throws IOException { 80 setPreviousCallback(callbackHandler); 81 getSuccessor().init(ioEventHandler); 82 83 startSSL(); 84 } 85 86 87 90 public void setPreviousCallback(IIoHandlerCallback callbackHandler) { 91 super.setPreviousCallback(callbackHandler); 92 getSuccessor().setPreviousCallback(ioEventHandler); 93 } 94 95 96 97 100 @Override 101 public int getPendingWriteDataSize() { 102 return outAppDataQueue.getSize() + super.getPendingWriteDataSize(); 103 } 104 105 106 int getPendingReceiveDataSize() { 107 return inAppDataQueue.getSize() + super.getPendingReceiveDataSize(); 108 } 109 110 111 112 117 void startSSL() throws IOException { 118 if (!isSSLConnected) { 119 sslProcessor.start(); 120 } 121 122 readIncomingEncryptedData(); 123 } 124 125 126 127 128 131 public LinkedList <ByteBuffer > drainIncoming() { 132 return inAppDataQueue.drain(); 133 } 134 135 136 139 public final void close(boolean immediate) throws IOException { 140 141 if (!immediate) { 142 flushOutgoing(); 143 } 144 145 getSuccessor().close(immediate); 146 } 147 148 149 152 public final void writeOutgoing(ByteBuffer buffer) throws ClosedConnectionException, IOException { 153 LinkedList <ByteBuffer > buffers = new LinkedList <ByteBuffer >(); 154 buffers.add(buffer); 155 writeOutgoing(buffers); 156 } 157 158 159 162 public final void writeOutgoing(LinkedList <ByteBuffer > buffers) throws ClosedConnectionException, IOException { 163 outAppDataQueue.append(buffers); 164 flushOutgoing(); 165 } 166 167 168 171 public void flushOutgoing() throws IOException { 172 synchronized (sslProcessor) { 173 if (!sslProcessor.isHandshaking()) { 174 if (!outAppDataQueue.isEmpty()) { 175 sslProcessor.processOutAppData(outAppDataQueue.drain()); 176 } 177 } else { 178 sslProcessor.processOutAppData(); 179 } 180 } 181 } 182 183 184 185 186 protected final void readIncomingEncryptedData() throws ClosedConnectionException, IOException { 187 readIncomingEncryptedData(getSuccessor().drainIncoming()); 188 } 189 190 191 192 private synchronized void readIncomingEncryptedData(LinkedList <ByteBuffer > inNetDataList) throws ClosedConnectionException, IOException { 193 if (inNetDataList != null) { 194 if (LOG.isLoggable(Level.FINE)) { 195 int size = 0; 196 for (ByteBuffer buffer : inNetDataList) { 197 size += buffer.remaining(); 198 } 199 200 LOG.fine("received " + size + " bytes encrypted data"); 201 } 202 203 sslProcessor.processInNetData(inNetDataList); 204 } 205 } 206 207 208 public void onHandshakeFinished() throws IOException { 209 if (!isSSLConnected) { 210 if (LOG.isLoggable(Level.FINE)) { 211 if (isClientMode) { 212 LOG.fine("[" + getId() + "] handshake has been finished (clientMode)"); 213 } else { 214 LOG.fine("[" + getId() + "] handshake has been finished (serverMode)"); 215 } 216 } 217 218 isSSLConnected = true; 219 getPreviousCallback().onConnect(); 220 } 221 222 flushOutgoing(); 223 readIncomingEncryptedData(); 224 } 225 226 227 public void onSSLProcessorClosed() throws IOException { 228 close(true); 229 } 230 231 232 public void onInAppDataReceived(LinkedList <ByteBuffer > appDataList) { 233 inAppDataQueue.append(appDataList); 234 235 if (!inAppDataQueue.isEmpty()) { 236 getPreviousCallback().onDataRead(); 237 } 238 } 239 240 241 242 public void onOutNetDataToWrite(ByteBuffer netData) throws IOException { 243 if (netData.hasRemaining()) { 244 getSuccessor().writeOutgoing(netData); 245 } 246 } 247 248 249 250 private final class IOEventHandler implements IIoHandlerCallback { 251 252 public void onDataRead() { 253 try { 254 readIncomingEncryptedData(); 255 } catch (Exception e) { 256 if (LOG.isLoggable(Level.FINE)) { 257 LOG.fine("[" + getId() + "] error occured while receiving data. Reason: " + e.toString()); 258 } 259 } 260 } 261 262 263 public void onConnect() { 264 265 } 266 267 public void onWriteException(IOException ioException) { 268 getPreviousCallback().onWriteException(ioException); 269 } 270 271 public void onWritten() { 272 getPreviousCallback().onWritten(); 273 } 274 275 public void onDisconnect() { 276 sslProcessor.destroy(); 277 getPreviousCallback().onDisconnect(); 278 } 279 280 public void onConnectionAbnormalTerminated() { 281 getPreviousCallback().onConnectionAbnormalTerminated(); 282 } 283 284 285 public void onConnectionTimeout() { 286 getPreviousCallback().onConnectionTimeout(); 287 } 288 289 public void onIdleTimeout() { 290 getPreviousCallback().onIdleTimeout(); 291 } 292 } 293 } 294 | Popular Tags |