diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/HttpChunksProcessor.java b/src/main/java/ru/serega6531/packmate/service/optimization/HttpChunksProcessor.java index 0a43cf9..cd22ca0 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/HttpChunksProcessor.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/HttpChunksProcessor.java @@ -1,6 +1,6 @@ package ru.serega6531.packmate.service.optimization; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import ru.serega6531.packmate.model.Packet; @@ -14,18 +14,20 @@ import java.util.Arrays; import java.util.List; @Slf4j -@AllArgsConstructor +@RequiredArgsConstructor public class HttpChunksProcessor { private final List packets; - public void processChunkedEncoding() { - boolean chunkStarted = false; - int start = -1; - List chunk = new ArrayList<>(); + private int position; + private boolean chunkStarted = false; + private final List chunkPackets = new ArrayList<>(); - for (int i = 0; i < packets.size(); i++) { - Packet packet = packets.get(i); + public void processChunkedEncoding() { + int start = -1; + + for (position = 0; position < packets.size(); position++) { + Packet packet = packets.get(position); if (!packet.isIncoming()) { String content = packet.getContentString(); @@ -37,97 +39,100 @@ public class HttpChunksProcessor { boolean chunked = headers.contains("Transfer-Encoding: chunked\r\n"); if (chunked) { chunkStarted = true; - start = i; - chunk.add(packet); + start = position; + chunkPackets.add(packet); - if (checkCompleteChunk(chunk, start)) { - chunkStarted = false; - chunk.clear(); - i = start + 1; - } + checkCompleteChunk(chunkPackets, start); } else { chunkStarted = false; - chunk.clear(); + chunkPackets.clear(); } } else if (chunkStarted) { - chunk.add(packet); - if (checkCompleteChunk(chunk, start)) { - chunkStarted = false; - chunk.clear(); - i = start + 1; - } + chunkPackets.add(packet); + checkCompleteChunk(chunkPackets, start); } } } } - /** - * @return true если чанк завершен - */ - @SneakyThrows - private boolean checkCompleteChunk(List packets, int start) { + private void checkCompleteChunk(List packets, int start) { boolean end = packets.get(packets.size() - 1).getContentString().endsWith("\r\n0\r\n\r\n"); if (end) { - //noinspection OptionalGetWithoutIsPresent - final byte[] content = PacketUtils.mergePackets(packets).get(); + processChunk(packets, start); + } + } - ByteArrayOutputStream output = new ByteArrayOutputStream(content.length); + @SneakyThrows + private void processChunk(List packets, int start) { + //noinspection OptionalGetWithoutIsPresent + final byte[] content = PacketUtils.mergePackets(packets).get(); - final int contentStart = Bytes.indexOf(content, "\r\n\r\n".getBytes()) + 4; - output.write(content, 0, contentStart); + ByteArrayOutputStream output = new ByteArrayOutputStream(content.length); - ByteBuffer buf = ByteBuffer.wrap(Arrays.copyOfRange(content, contentStart, content.length)); + final int contentStart = Bytes.indexOf(content, "\r\n\r\n".getBytes()) + 4; + output.write(content, 0, contentStart); - while (true) { - final String found = readChunkSize(buf); - if (found != null) { - final int chunkSize = Integer.parseInt(found, 16); + ByteBuffer buf = ByteBuffer.wrap(Arrays.copyOfRange(content, contentStart, content.length)); - if (chunkSize == 0) { // конец потока чанков - Packet result = Packet.builder() - .incoming(false) - .timestamp(packets.get(0).getTimestamp()) - .ungzipped(false) - .webSocketParsed(false) - .content(output.toByteArray()) - .build(); + while (true) { + final String found = readChunkSize(buf); + if (found != null) { + final int chunkSize = Integer.parseInt(found, 16); - this.packets.removeAll(packets); - this.packets.add(start, result); + if (chunkSize == 0) { // конец потока чанков + Packet result = Packet.builder() + .incoming(false) + .timestamp(packets.get(0).getTimestamp()) + .ungzipped(false) + .webSocketParsed(false) + .content(output.toByteArray()) + .build(); - return true; - } + this.packets.removeAll(packets); + this.packets.add(start, result); - if (chunkSize > buf.remaining()) { - log.warn("Failed to merge chunks, chunk size too big: {} + {} > {}", - buf.position(), chunkSize, buf.capacity()); - return true; // обнулить список, но не заменять пакеты - } + resetChunk(); + position = start + 1; - byte[] chunk = new byte[chunkSize]; - buf.get(chunk); - output.write(chunk); - - if (buf.remaining() < 2) { - log.warn("Failed to merge chunks, chunk doesn't end with \\r\\n"); - return true; // обнулить список, но не заменять пакеты - } - - int c1 = buf.get(); - int c2 = buf.get(); - if(c1 != '\r' || c2 != '\n') { - log.warn("Failed to merge chunks, chunk trailer is not equal to \\r\\n"); - return true; // обнулить список, но не заменять пакеты - } - } else { - log.warn("Failed to merge chunks, next chunk size not found"); - return true; // обнулить список, но не заменять пакеты + return; } + + if (chunkSize > buf.remaining()) { + log.warn("Failed to merge chunks, chunk size too big: {} + {} > {}", + buf.position(), chunkSize, buf.capacity()); + resetChunk(); + return; + } + + byte[] chunk = new byte[chunkSize]; + buf.get(chunk); + output.write(chunk); + + if (buf.remaining() < 2) { + log.warn("Failed to merge chunks, chunk doesn't end with \\r\\n"); + resetChunk(); + return; + } + + int c1 = buf.get(); + int c2 = buf.get(); + if(c1 != '\r' || c2 != '\n') { + log.warn("Failed to merge chunks, chunk trailer is not equal to \\r\\n"); + resetChunk(); + return; + } + } else { + log.warn("Failed to merge chunks, next chunk size not found"); + resetChunk(); + return; } } + } - return false; + private void resetChunk() { + chunkStarted = false; + chunkPackets.clear(); } private String readChunkSize(ByteBuffer buf) {