Рефакторинг
This commit is contained in:
@@ -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<Packet> packets;
|
||||
|
||||
public void processChunkedEncoding() {
|
||||
boolean chunkStarted = false;
|
||||
int start = -1;
|
||||
List<Packet> chunk = new ArrayList<>();
|
||||
private int position;
|
||||
private boolean chunkStarted = false;
|
||||
private final List<Packet> 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<Packet> packets, int start) {
|
||||
private void checkCompleteChunk(List<Packet> 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<Packet> 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) {
|
||||
|
||||
Reference in New Issue
Block a user