Исправлена распаковка ws с контентом в пакете с хендшейком
This commit is contained in:
@@ -2,6 +2,7 @@ package ru.serega6531.packmate.service.optimization;
|
|||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.java_websocket.drafts.Draft_6455;
|
import org.java_websocket.drafts.Draft_6455;
|
||||||
import org.java_websocket.exceptions.InvalidDataException;
|
import org.java_websocket.exceptions.InvalidDataException;
|
||||||
import org.java_websocket.exceptions.InvalidHandshakeException;
|
import org.java_websocket.exceptions.InvalidHandshakeException;
|
||||||
@@ -11,25 +12,27 @@ import org.java_websocket.framing.Framedata;
|
|||||||
import org.java_websocket.handshake.HandshakeImpl1Client;
|
import org.java_websocket.handshake.HandshakeImpl1Client;
|
||||||
import org.java_websocket.handshake.HandshakeImpl1Server;
|
import org.java_websocket.handshake.HandshakeImpl1Server;
|
||||||
import ru.serega6531.packmate.model.Packet;
|
import ru.serega6531.packmate.model.Packet;
|
||||||
|
import ru.serega6531.packmate.utils.BytesUtils;
|
||||||
import ru.serega6531.packmate.utils.PacketUtils;
|
import ru.serega6531.packmate.utils.PacketUtils;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class WebSocketsParser {
|
public class WebSocketsParser {
|
||||||
|
|
||||||
private static final java.util.regex.Pattern WEBSOCKET_KEY_PATTERN =
|
private static final java.util.regex.Pattern WEBSOCKET_KEY_PATTERN =
|
||||||
java.util.regex.Pattern.compile("Sec-WebSocket-Key: (.+)\\r\\n");
|
Pattern.compile("Sec-WebSocket-Key: (.+)\\r\\n");
|
||||||
private static final java.util.regex.Pattern WEBSOCKET_EXTENSIONS_PATTERN =
|
private static final java.util.regex.Pattern WEBSOCKET_EXTENSIONS_PATTERN =
|
||||||
java.util.regex.Pattern.compile("Sec-WebSocket-Extensions?: (.+)\\r\\n");
|
Pattern.compile("Sec-WebSocket-Extensions?: (.+)\\r\\n");
|
||||||
private static final java.util.regex.Pattern WEBSOCKET_VERSION_PATTERN =
|
private static final java.util.regex.Pattern WEBSOCKET_VERSION_PATTERN =
|
||||||
java.util.regex.Pattern.compile("Sec-WebSocket-Version: (\\d+)\\r\\n");
|
Pattern.compile("Sec-WebSocket-Version: (\\d+)\\r\\n");
|
||||||
private static final java.util.regex.Pattern WEBSOCKET_ACCEPT_PATTERN =
|
private static final java.util.regex.Pattern WEBSOCKET_ACCEPT_PATTERN =
|
||||||
java.util.regex.Pattern.compile("Sec-WebSocket-Accept: (.+)\\r\\n");
|
Pattern.compile("Sec-WebSocket-Accept: (.+)\\r\\n");
|
||||||
|
|
||||||
private static final String WEBSOCKET_UPGRADE_HEADER = "upgrade: websocket\r\n";
|
private static final String WEBSOCKET_UPGRADE_HEADER = "upgrade: websocket\r\n";
|
||||||
private static final String WEBSOCKET_CONNECTION_HEADER = "connection: upgrade\r\n";
|
private static final String WEBSOCKET_CONNECTION_HEADER = "connection: upgrade\r\n";
|
||||||
@@ -57,7 +60,20 @@ public class WebSocketsParser {
|
|||||||
|
|
||||||
int httpEnd = -1;
|
int httpEnd = -1;
|
||||||
for (int i = clientHandshakePackets.size(); i < packets.size(); i++) {
|
for (int i = clientHandshakePackets.size(); i < packets.size(); i++) {
|
||||||
if (packets.get(i).getContentString().endsWith("\r\n\r\n")) {
|
Packet packet = packets.get(i);
|
||||||
|
byte[] content = packet.getContent();
|
||||||
|
if (BytesUtils.startsWith(content, "HTTP/1.1 101 Switching Protocols".getBytes())) {
|
||||||
|
int endPos = BytesUtils.indexOf(content, "\r\n\r\n".getBytes()) + "\r\n\r\n".length();
|
||||||
|
if (endPos != content.length) {
|
||||||
|
byte[] handshakePart = ArrayUtils.subarray(content, 0, endPos);
|
||||||
|
byte[] payloadPart = ArrayUtils.subarray(content, endPos, content.length);
|
||||||
|
|
||||||
|
Packet handshakePacket = mimicPacket(packet, handshakePart, false);
|
||||||
|
Packet payloadPacket = mimicPacket(packet, payloadPart, true);
|
||||||
|
|
||||||
|
packets.add(i, handshakePacket);
|
||||||
|
packets.set(i + 1, payloadPacket);
|
||||||
|
}
|
||||||
httpEnd = i + 1;
|
httpEnd = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -94,7 +110,7 @@ public class WebSocketsParser {
|
|||||||
httpEnd,
|
httpEnd,
|
||||||
packets.size());
|
packets.size());
|
||||||
|
|
||||||
if(wsPackets.isEmpty()) {
|
if (wsPackets.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +119,18 @@ public class WebSocketsParser {
|
|||||||
parse(wsPackets, handshakes, draft);
|
parse(wsPackets, handshakes, draft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Packet mimicPacket(Packet packet, byte[] content, boolean ws) {
|
||||||
|
return Packet.builder()
|
||||||
|
.content(content)
|
||||||
|
.incoming(packet.isIncoming())
|
||||||
|
.timestamp(packet.getTimestamp())
|
||||||
|
.ttl(packet.getTtl())
|
||||||
|
.ungzipped(packet.isUngzipped())
|
||||||
|
.webSocketParsed(ws)
|
||||||
|
.tlsDecrypted(packet.isTlsDecrypted())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private void parse(final List<Packet> wsPackets, final List<Packet> handshakes, Draft_6455 draft) {
|
private void parse(final List<Packet> wsPackets, final List<Packet> handshakes, Draft_6455 draft) {
|
||||||
List<List<Packet>> sides = PacketUtils.sliceToSides(wsPackets);
|
List<List<Packet>> sides = PacketUtils.sliceToSides(wsPackets);
|
||||||
parsedPackets = new ArrayList<>(handshakes);
|
parsedPackets = new ArrayList<>(handshakes);
|
||||||
@@ -124,7 +152,7 @@ public class WebSocketsParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Framedata frame : frames) {
|
for (Framedata frame : frames) {
|
||||||
if(frame instanceof DataFrame) {
|
if (frame instanceof DataFrame) {
|
||||||
parsedPackets.add(Packet.builder()
|
parsedPackets.add(Packet.builder()
|
||||||
.content(frame.getPayloadData().array())
|
.content(frame.getPayloadData().array())
|
||||||
.incoming(lastPacket.isIncoming())
|
.incoming(lastPacket.isIncoming())
|
||||||
@@ -190,7 +218,7 @@ public class WebSocketsParser {
|
|||||||
clientHandshakeImpl.put("Sec-WebSocket-Version", version);
|
clientHandshakeImpl.put("Sec-WebSocket-Version", version);
|
||||||
clientHandshakeImpl.put("Sec-WebSocket-Key", key);
|
clientHandshakeImpl.put("Sec-WebSocket-Key", key);
|
||||||
|
|
||||||
if(extensions != null) {
|
if (extensions != null) {
|
||||||
clientHandshakeImpl.put("Sec-WebSocket-Extensions", extensions);
|
clientHandshakeImpl.put("Sec-WebSocket-Extensions", extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BITS;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class BytesUtils {
|
public class BytesUtils {
|
||||||
|
|
||||||
/**
|
public int indexOf(byte[] array, byte[] target) {
|
||||||
* @param array где ищем
|
return indexOf(array, target, 0, array.length);
|
||||||
* @param target что ищем
|
}
|
||||||
*/
|
|
||||||
public int indexOf(byte[] array, byte[] target, int start, int end) {
|
public int indexOf(byte[] array, byte[] target, int start, int end) {
|
||||||
if (target.length == 0) {
|
if (target.length == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -32,6 +32,20 @@ public class BytesUtils {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean startsWith(byte[] array, byte[] prefix) {
|
||||||
|
if (prefix.length > array.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < prefix.length; i++) {
|
||||||
|
if (array[i] != prefix[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array где ищем
|
* @param array где ищем
|
||||||
* @param target что ищем
|
* @param target что ищем
|
||||||
|
|||||||
Reference in New Issue
Block a user