/** * Copyright (C) 2009-2013 Typesafe Inc. */ package docs.io.japi; //#frame import java.nio.ByteOrder; import java.util.ArrayList; import scala.util.Either; import akka.io.AbstractSymmetricPipePair; import akka.io.PipePairFactory; import akka.io.PipelineContext; import akka.io.SymmetricPipePair; import akka.io.SymmetricPipelineStage; import akka.util.ByteString; import akka.util.ByteStringBuilder; public class LengthFieldFrame extends SymmetricPipelineStage { final int maxSize; public LengthFieldFrame(int maxSize) { this.maxSize = maxSize; } @Override public SymmetricPipePair apply(final PipelineContext ctx) { return PipePairFactory .create(ctx, new AbstractSymmetricPipePair() { final ByteOrder byteOrder = ByteOrder.BIG_ENDIAN; ByteString buffer = null; @Override public Iterable> onCommand( ByteString cmd) { final int length = cmd.length() + 4; if (length > maxSize) { return new ArrayList>(0); } final ByteStringBuilder bb = new ByteStringBuilder(); bb.putInt(length, byteOrder); bb.append(cmd); return singleCommand(bb.result()); } @Override public Iterable> onEvent( ByteString event) { final ArrayList> res = new ArrayList>(); ByteString current = buffer == null ? event : buffer.concat(event); while (true) { if (current.length() == 0) { buffer = null; return res; } else if (current.length() < 4) { buffer = current; return res; } else { final int length = current.iterator().getInt(byteOrder); if (length > maxSize) throw new IllegalArgumentException( "received too large frame of size " + length + " (max = " + maxSize + ")"); if (current.length() < length) { buffer = current; return res; } else { res.add(makeEvent(current.slice(4, length))); current = current.drop(length); } } } } }); } } //#frame