PageRenderTime 22ms CodeModel.GetById 9ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/hazelcast/src/main/java/com/hazelcast/nio/SocketPacketReader.java

https://bitbucket.org/gabral6_gmailcom/hazelcast
Java | 214 lines | 177 code | 22 blank | 15 comment | 39 complexity | d81ee77714b9cfefb3cdf0eb0a24e8ce MD5 | raw file
  1/*
  2 * Copyright (c) 2008-2013, Hazelcast, Inc. 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
 17package com.hazelcast.nio;
 18
 19import com.hazelcast.logging.ILogger;
 20
 21import javax.crypto.Cipher;
 22import javax.crypto.ShortBufferException;
 23import java.nio.ByteBuffer;
 24import java.util.logging.Level;
 25
 26import static com.hazelcast.nio.IOUtil.copyToHeapBuffer;
 27
 28class SocketPacketReader implements SocketReader {
 29
 30    Packet packet = null;
 31
 32    final PacketReader packetReader;
 33    final Connection connection;
 34    final IOService ioService;
 35    final SocketChannelWrapper socketChannel;
 36    final ILogger logger;
 37
 38    public SocketPacketReader(SocketChannelWrapper socketChannel, Connection connection) {
 39        this.connection = connection;
 40        this.ioService = connection.getConnectionManager().ioService;
 41        this.socketChannel = socketChannel;
 42        this.logger = ioService.getLogger(SocketPacketReader.class.getName());
 43        boolean symmetricEncryptionEnabled = CipherHelper.isSymmetricEncryptionEnabled(ioService);
 44        boolean asymmetricEncryptionEnabled = CipherHelper.isAsymmetricEncryptionEnabled(ioService);
 45        if (asymmetricEncryptionEnabled || symmetricEncryptionEnabled) {
 46            if (asymmetricEncryptionEnabled && symmetricEncryptionEnabled) {
 47                packetReader = new ComplexCipherPacketReader();
 48                logger.log(Level.INFO, "Reader started with ComplexEncryption");
 49            } else if (symmetricEncryptionEnabled) {
 50                packetReader = new SymmetricCipherPacketReader();
 51                logger.log(Level.INFO, "Reader started with SymmetricEncryption");
 52            } else {
 53                packetReader = new AsymmetricCipherPacketReader();
 54                logger.log(Level.INFO, "Reader started with AsymmetricEncryption");
 55            }
 56        } else {
 57            packetReader = new DefaultPacketReader();
 58        }
 59    }
 60
 61    public void read(ByteBuffer inBuffer) throws Exception {
 62        packetReader.readPacket(inBuffer);
 63    }
 64
 65    public void enqueueFullPacket(final Packet p) {
 66        p.flipBuffers();
 67        p.read();
 68        p.setFromConnection(connection);
 69        if (p.client) {
 70            connection.setType(Connection.Type.CLIENT);
 71            ioService.handleClientPacket(p);
 72        } else {
 73            connection.setType(Connection.Type.MEMBER);
 74            ioService.handleMemberPacket(p);
 75        }
 76    }
 77
 78    interface PacketReader {
 79        void readPacket(ByteBuffer inBuffer) throws Exception;
 80    }
 81
 82    class DefaultPacketReader implements PacketReader {
 83        public void readPacket(ByteBuffer inBuffer) {
 84            while (inBuffer.hasRemaining()) {
 85                if (packet == null) {
 86                    packet = obtainReadable();
 87                }
 88                boolean complete = packet.read(inBuffer);
 89                if (complete) {
 90                    enqueueFullPacket(packet);
 91                    packet = null;
 92                }
 93            }
 94        }
 95    }
 96
 97    class ComplexCipherPacketReader implements PacketReader {
 98
 99        ComplexCipherPacketReader() {
100        }
101
102        public void readPacket(ByteBuffer inBuffer) throws Exception {
103        }
104    }
105
106    class AsymmetricCipherPacketReader implements PacketReader {
107        Cipher cipher = null;
108        ByteBuffer cipherBuffer = ByteBuffer.allocate(128);
109        ByteBuffer bbAlias = null;
110        boolean aliasSizeSet = false;
111
112        public void readPacket(ByteBuffer inBuffer) throws Exception {
113            if (cipher == null) {
114                if (!aliasSizeSet) {
115                    if (inBuffer.remaining() < 4) {
116                        return;
117                    } else {
118                        int aliasSize = inBuffer.getInt();
119                        bbAlias = ByteBuffer.allocate(aliasSize);
120                    }
121                }
122                copyToHeapBuffer(inBuffer, bbAlias);
123                if (!bbAlias.hasRemaining()) {
124                    bbAlias.flip();
125                    String remoteAlias = new String(bbAlias.array(), 0, bbAlias.limit());
126                    cipher = CipherHelper.createAsymmetricReaderCipher(connection.getConnectionManager().ioService, remoteAlias);
127                }
128            }
129            while (inBuffer.remaining() >= 128) {
130                if (cipherBuffer.position() > 0) throw new RuntimeException();
131                int oldLimit = inBuffer.limit();
132                inBuffer.limit(inBuffer.position() + 128);
133                int cipherReadSize = cipher.doFinal(inBuffer, cipherBuffer);
134                inBuffer.limit(oldLimit);
135                cipherBuffer.flip();
136                while (cipherBuffer.hasRemaining()) {
137                    if (packet == null) {
138                        packet = obtainReadable();
139                    }
140                    boolean complete = packet.read(cipherBuffer);
141                    if (complete) {
142                        enqueueFullPacket(packet);
143                        packet = null;
144                    }
145                }
146                cipherBuffer.clear();
147            }
148        }
149    }
150
151    class SymmetricCipherPacketReader implements PacketReader {
152        int size = -1;
153        final Cipher cipher;
154        ByteBuffer cipherBuffer = ByteBuffer.allocate(2 * RECEIVE_SOCKET_BUFFER_SIZE);
155
156        SymmetricCipherPacketReader() {
157            cipher = init();
158        }
159
160        Cipher init() {
161            Cipher c = null;
162            try {
163                c = CipherHelper.createSymmetricReaderCipher(connection.getConnectionManager().ioService);
164            } catch (Exception e) {
165                logger.log(Level.SEVERE, "Symmetric Cipher for ReadHandler cannot be initialized.", e);
166            }
167            return c;
168        }
169
170        public void readPacket(ByteBuffer inBuffer) throws Exception {
171            while (inBuffer.hasRemaining()) {
172                try {
173                    if (size == -1) {
174                        if (inBuffer.remaining() < 4) return;
175                        size = inBuffer.getInt();
176                    }
177                    int remaining = inBuffer.remaining();
178                    if (remaining < size) {
179                        cipher.update(inBuffer, cipherBuffer);
180                        size -= remaining;
181                    } else if (remaining == size) {
182                        cipher.doFinal(inBuffer, cipherBuffer);
183                        size = -1;
184                    } else {
185                        int oldLimit = inBuffer.limit();
186                        int newLimit = inBuffer.position() + size;
187                        inBuffer.limit(newLimit);
188                        cipher.doFinal(inBuffer, cipherBuffer);
189                        inBuffer.limit(oldLimit);
190                        size = -1;
191                    }
192                } catch (ShortBufferException e) {
193                    logger.log(Level.WARNING, e.getMessage(), e);
194                }
195                cipherBuffer.flip();
196                while (cipherBuffer.hasRemaining()) {
197                    if (packet == null) {
198                        packet = obtainReadable();
199                    }
200                    boolean complete = packet.read(cipherBuffer);
201                    if (complete) {
202                        enqueueFullPacket(packet);
203                        packet = null;
204                    }
205                }
206                cipherBuffer.clear();
207            }
208        }
209    }
210
211    public Packet obtainReadable() {
212        return connection.obtainPacket();
213    }
214}