Search in sources :

Example 1 with ByteBufferInputStream

use of net.morimekta.util.io.ByteBufferInputStream in project providence by morimekta.

the class NonblockingSocketServer method handleRead.

@SuppressWarnings("unchecked")
private void handleRead(SelectionKey key, Context context) throws IOException {
    long startTime = System.nanoTime();
    // part a: read into the readBuffer.
    if (context.currentFrameSize == 0) {
        // read frame size.
        try {
            if (context.channel.read(context.sizeBuffer) < 0) {
                context.close();
                key.cancel();
                return;
            }
            if (context.sizeBuffer.position() < 4) {
                return;
            }
        } catch (IOException e) {
            // LOGGER.error(e.getMessage(), e);
            context.close();
            key.cancel();
            return;
        }
        context.sizeBuffer.flip();
        try (ByteBufferInputStream in = new ByteBufferInputStream(context.sizeBuffer);
            BigEndianBinaryReader reader = new BigEndianBinaryReader(in)) {
            context.currentFrameSize = reader.expectInt();
        }
        context.sizeBuffer.rewind();
        if (context.currentFrameSize > maxFrameSizeInBytes) {
            LOGGER.warn("Attempting message of " + context.currentFrameSize + " > " + maxFrameSizeInBytes);
            context.close();
            key.cancel();
            return;
        }
        if (context.currentFrameSize < 1) {
            LOGGER.warn("Attempting message of " + context.currentFrameSize);
            context.close();
            key.cancel();
            return;
        }
        context.readBuffer.rewind();
        context.readBuffer.limit(context.currentFrameSize);
    }
    try {
        if (context.channel.read(context.readBuffer) < 0) {
            LOGGER.warn("Closed connection while reading frame");
            context.close();
            key.cancel();
            return;
        }
    } catch (IOException e) {
        LOGGER.warn("Exception reading frame: {}", e.getMessage(), e);
        context.close();
        key.cancel();
        return;
    }
    if (context.readBuffer.position() < context.readBuffer.limit()) {
        // wait until next read, and see if remaining of frame has arrived.
        return;
    }
    // part b: if the read buffer is complete, handle the content.
    PServiceCall call;
    try {
        context.currentFrameSize = 0;
        context.readBuffer.flip();
        call = serializer.deserialize(new ByteBufferInputStream(context.readBuffer), processor.getDescriptor());
        context.readBuffer.clear();
        workerExecutor.submit(() -> {
            PServiceCall reply;
            try {
                reply = processor.handleCall(call);
            } catch (Exception e) {
                reply = new PServiceCall<>(call.getMethod(), PServiceCallType.EXCEPTION, call.getSequence(), PApplicationException.builder().setMessage(e.getMessage()).setId(PApplicationExceptionType.INTERNAL_ERROR).initCause(e).build());
            }
            synchronized (context.writeQueue) {
                context.writeQueue.offer(new WriteEntry(startTime, call, reply));
                key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
                selector.wakeup();
            }
        });
    } catch (IOException e) {
        double duration = ((double) System.nanoTime() - startTime) / NS_IN_MILLIS;
        instrumentation.onTransportException(e, duration, null, null);
    }
}
Also used : PServiceCall(net.morimekta.providence.PServiceCall) ByteBufferInputStream(net.morimekta.util.io.ByteBufferInputStream) BigEndianBinaryReader(net.morimekta.util.io.BigEndianBinaryReader) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) PApplicationException(net.morimekta.providence.PApplicationException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException)

Example 2 with ByteBufferInputStream

use of net.morimekta.util.io.ByteBufferInputStream in project providence by morimekta.

the class FramedBufferInputStream method readFrame.

private int readFrame() throws IOException {
    frameSizeBuffer.rewind();
    in.read(frameSizeBuffer);
    if (frameSizeBuffer.position() == 0) {
        return -1;
    }
    if (frameSizeBuffer.position() < Integer.BYTES) {
        throw new IOException("Not enough bytes for frame size: " + frameSizeBuffer.position());
    }
    frameSizeBuffer.flip();
    int frameSize;
    try (ByteBufferInputStream in = new ByteBufferInputStream(frameSizeBuffer);
        BigEndianBinaryReader reader = new BigEndianBinaryReader(in)) {
        frameSize = reader.expectInt();
    }
    if (frameSize < 1) {
        throw new IOException("Invalid frame size " + frameSize);
    } else if (frameSize > buffer.capacity()) {
        IOException ex = new IOException("Frame size too large " + frameSize + " > " + buffer.capacity());
        try {
            // Try to consume the frame so we can continue with the next.
            while (frameSize > 0) {
                buffer.rewind();
                buffer.limit(Math.max(frameSize, buffer.capacity()));
                int r = in.read(buffer);
                if (r > 0) {
                    frameSize -= r;
                } else {
                    break;
                }
            }
        } catch (Exception e) {
            ex.addSuppressed(e);
        }
        throw ex;
    }
    buffer.rewind();
    buffer.limit(frameSize);
    while (in.read(buffer) > 0) {
        if (buffer.position() == frameSize) {
            break;
        }
        LOGGER.debug("still not enough:  " + buffer.position() + " of " + frameSize);
    }
    if (buffer.position() < frameSize) {
        throw new IOException();
    }
    buffer.flip();
    return frameSize;
}
Also used : ByteBufferInputStream(net.morimekta.util.io.ByteBufferInputStream) BigEndianBinaryReader(net.morimekta.util.io.BigEndianBinaryReader) IOException(java.io.IOException) IOException(java.io.IOException)

Aggregations

IOException (java.io.IOException)2 BigEndianBinaryReader (net.morimekta.util.io.BigEndianBinaryReader)2 ByteBufferInputStream (net.morimekta.util.io.ByteBufferInputStream)2 UncheckedIOException (java.io.UncheckedIOException)1 PApplicationException (net.morimekta.providence.PApplicationException)1 PServiceCall (net.morimekta.providence.PServiceCall)1