0

I don't know why but half the sites that go through ssl get a buffer_underflow during my read.

When I have my program chained to call different ssl sites consecutively it doesn't work on half the links, but if I call one by one individually, they work. For example, I used Chrome's developer tools to call https://www.facebook.com on my nexus 7 tablet. When I see the requests, The links called are:

If I chain them together (to simulate a call to https://www.facebook.com from the browser), I get half the links getting buffer underflows until eventually I have to close their connections (Reading 0 bytes). However, if I cal them one by one individually, they are always fine. Here is my code for reading:

public int readSSLFrom(SelectionKey key, SecureIO session) throws IOException{
    int result = 0;
    String TAG = "readSSLFrom";
    Log.i(TAG,"Hanshake status: "+session.sslEngine.getHandshakeStatus().toString());
    synchronized (buffer){
        ByteBuffer sslIn = ByteBuffer.allocate(session.getApplicationSizeBuffer());
        ByteBuffer tmp = ByteBuffer.allocate(session.getApplicationSizeBuffer());
        ReadableByteChannel channel = (ReadableByteChannel) key.channel();
        if (buffer.remaining() < session.getPacketBufferSize()){
            increaseSize(session.getPacketBufferSize());
        }
        int read = 0;
        while (((read = channel.read(sslIn)) > 0) &&
                buffer.remaining() >= session.getApplicationSizeBuffer()){
            if (read < 0){
                session.sslEngine.closeInbound();
                return -1;
            }
            inner: while (sslIn.position() > 0){ 
                sslIn.flip();
                tmp.clear();
                SSLEngineResult res = session.sslEngine.unwrap(sslIn, tmp);
                result = result + res.bytesProduced();
                sslIn.compact();
                tmp.flip();
                if (tmp.hasRemaining()){
                    buffer.put(tmp);
                }
                switch (res.getStatus()){
                case BUFFER_OVERFLOW:
                    Log.i(TAG,"Buffer overflow");
                    throw new Error();
                case BUFFER_UNDERFLOW:
                    Log.i(TAG,"Buffer underflow");
                    if (session.getPacketBufferSize() > tmp.capacity()){
                        Log.i(TAG,"increasing capacity");
                        ByteBuffer b = ByteBuffer.allocate(session.getPacketBufferSize());
                        sslIn.flip();
                        b.put(sslIn);
                        sslIn = b;
                    }
                    break inner;
                case CLOSED:
                    Log.i(TAG,"Closed");
                    if (sslIn.position() == 0){
                        break inner;
                    } else{
                        return -1;
                    }
                case OK:
                    Log.i(TAG,"OK");
                    session.checkHandshake(key);
                    break;
                default:
                    break;
                }
            }
        }
        if (read < 0){
            //session.sslEngine.closeInbound();
            return -1;
        }
    }
    dataEnd = buffer.position();
    return result;
}

Thank you.

4

1 回答 1

0

缓冲区下溢在展开期间是可以接受的并且经常发生。当您有部分 TLS 记录 (<16KB) 时会发生这种情况。这可能在两种情况下发生,1)当你有少于 16KB 的时候,所以当你解包时你没有得到任何结果 - 只需缓存所有这些数据并等待剩余的数据到达解包它。2) 当你有超过 16KB 但最后一个 TLS 数据包不完整时,例如 20KB 或 36KB。在这种情况下,前 16KB/32KB 将在解包期间为您提供结果,您需要缓存剩余的 4KB 并等待完成此 TLS 数据包的剩余 12KB - 在您可以解包之前。

我希望这会有所帮助,试试我的代码,看看它是否适合你。

抱歉,这不适合评论,所以我回复了答案。

于 2014-01-03T06:49:29.570 回答