From c59910a0eabbf03bbe7aefe17c66313575d4a4a4 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Tue, 4 Feb 2020 00:07:15 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../packmate/service/StreamOptimizer.java | 56 ++++++++++++------- .../packmate/service/StreamService.java | 1 + 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/main/java/ru/serega6531/packmate/service/StreamOptimizer.java b/src/main/java/ru/serega6531/packmate/service/StreamOptimizer.java index ef79376..482d702 100644 --- a/src/main/java/ru/serega6531/packmate/service/StreamOptimizer.java +++ b/src/main/java/ru/serega6531/packmate/service/StreamOptimizer.java @@ -21,28 +21,35 @@ import java.util.zip.ZipException; @AllArgsConstructor @Slf4j -public class StreamOptimizer { +class StreamOptimizer { private final CtfService service; private final List packets; private static final byte[] GZIP_HEADER = {0x1f, (byte) 0x8b, 0x08}; - public void optimizeStream() { + /** + * Вызвать для выполнения оптимизаций на переданном списке пакетов. + */ + void optimizeStream() { if (service.isUngzipHttp()) { - unpackGzip(packets); + unpackGzip(); } if (service.isUrldecodeHttpRequests()) { - urldecodeRequests(packets); + urldecodeRequests(); } if (service.isMergeAdjacentPackets()) { - mergeAdjacentPackets(packets); + mergeAdjacentPackets(); } } - private void mergeAdjacentPackets(List packets) { + /** + * Сжать соседние пакеты в одном направлении в один. + * Выполняется после других оптимизаций чтобы правильно определять границы пакетов. + */ + private void mergeAdjacentPackets() { int start = 0; int packetsInRow = 0; boolean incoming = true; @@ -52,7 +59,7 @@ public class StreamOptimizer { if (packet.isIncoming() != incoming) { if (packetsInRow > 1) { final List cut = packets.subList(start, i); - compress(packets, cut, incoming); + compress(cut, incoming); i++; // продвигаем указатель на следующий после склеенного блок } @@ -67,11 +74,14 @@ public class StreamOptimizer { if (packetsInRow > 1) { final List cut = packets.subList(start, packets.size()); - compress(packets, cut, incoming); + compress(cut, incoming); } } - private void compress(List packets, List cut, boolean incoming) { + /** + * Сжать кусок cut в один пакет + */ + private void compress(List cut, boolean incoming) { final long timestamp = cut.get(0).getTimestamp(); final boolean ungzipped = cut.stream().anyMatch(Packet::isUngzipped); //noinspection OptionalGetWithoutIsPresent @@ -89,8 +99,11 @@ public class StreamOptimizer { .build()); } + /** + * Декодирование urlencode с http пакета до смены стороны или окончания стрима + */ @SneakyThrows - private void urldecodeRequests(List packets) { + private void urldecodeRequests() { boolean httpStarted = false; for (Packet packet : packets) { @@ -111,9 +124,13 @@ public class StreamOptimizer { } /** - * Попытаться распаковать gzip из исходящих http пакетов + * Попытаться распаковать GZIP из исходящих http пакетов.
+ * GZIP поток начинается на найденном HTTP пакете с заголовком Content-Encoding: gzip + * (при этом заголовок HTTP может быть в другом пакете)
+ * Поток заканчивается при обнаружении нового HTTP заголовка, + * при смене стороны передачи или при окончании всего стрима */ - private void unpackGzip(List packets) { + private void unpackGzip() { boolean gzipStarted = false; int gzipStartPacket = 0; int gzipEndPacket; @@ -123,7 +140,7 @@ public class StreamOptimizer { if (packet.isIncoming() && gzipStarted) { // поток gzip закончился gzipEndPacket = i - 1; - if(extractGzip(packets, gzipStartPacket, gzipEndPacket)) { + if(extractGzip(gzipStartPacket, gzipEndPacket)) { gzipStarted = false; i = gzipStartPacket + 1; // продвигаем указатель на следующий после склеенного блок } @@ -135,7 +152,7 @@ public class StreamOptimizer { if (http && gzipStarted) { // начался новый http пакет, заканчиваем старый gzip поток gzipEndPacket = i - 1; - if(extractGzip(packets, gzipStartPacket, gzipEndPacket)) { + if(extractGzip(gzipStartPacket, gzipEndPacket)) { gzipStarted = false; i = gzipStartPacket + 1; // продвигаем указатель на следующий после склеенного блок } @@ -153,14 +170,15 @@ public class StreamOptimizer { } if (gzipStarted) { // стрим закончился gzip пакетом - extractGzip(packets, gzipStartPacket, packets.size() - 1); + extractGzip(gzipStartPacket, packets.size() - 1); } } /** + * Попытаться распаковать кусок пакетов с gzip body и вставить результат на их место * @return получилось ли распаковать */ - private boolean extractGzip(List packets, int gzipStartPacket, int gzipEndPacket) { + private boolean extractGzip(int gzipStartPacket, int gzipEndPacket) { List cut = packets.subList(gzipStartPacket, gzipEndPacket + 1); Packet decompressed = decompressGzipPackets(cut); @@ -173,9 +191,9 @@ public class StreamOptimizer { return false; } - private Packet decompressGzipPackets(List packets) { + private Packet decompressGzipPackets(List cut) { //noinspection OptionalGetWithoutIsPresent - final byte[] content = packets.stream() + final byte[] content = cut.stream() .map(Packet::getContent) .reduce(ArrayUtils::addAll) .get(); @@ -194,7 +212,7 @@ public class StreamOptimizer { return Packet.builder() .incoming(false) - .timestamp(packets.get(0).getTimestamp()) + .timestamp(cut.get(0).getTimestamp()) .ungzipped(true) .content(newContent) .build(); diff --git a/src/main/java/ru/serega6531/packmate/service/StreamService.java b/src/main/java/ru/serega6531/packmate/service/StreamService.java index 2eb5af3..b68e603 100644 --- a/src/main/java/ru/serega6531/packmate/service/StreamService.java +++ b/src/main/java/ru/serega6531/packmate/service/StreamService.java @@ -90,6 +90,7 @@ public class StreamService { } } + new StreamOptimizer(service, packets).optimizeStream(); processUserAgent(packets, stream); Stream savedStream = save(stream);