StunMessage class
Пакет: com.hypixel.hytale.server.core.io.ice
Файл: com/hypixel/hytale/server/core/io/ice/StunMessage.java
Поля (59)
| Модификаторы | Тип | Имя |
|---|---|---|
final |
int |
MAGIC_COOKIE |
|
|
break |
|
byte[] |
var0 |
|
byte[] |
var1 |
|
byte[] |
var1 |
|
byte[] |
var1 |
|
|
var1 |
|
CRC32 |
var1 |
|
int |
var1 |
|
ByteBuffer |
var1 |
|
ByteBuffer |
var1 |
|
Mac |
var1 |
|
ByteBuffer |
var10 |
|
int |
var10 |
|
int |
var11 |
|
byte[] |
var12 |
|
ByteBuffer |
var13 |
|
byte[] |
var2 |
|
byte[] |
var2 |
|
byte[] |
var2 |
|
ByteBuffer |
var2 |
|
int |
var2 |
|
int |
var2 |
|
byte[] |
var2 |
|
int |
var2 |
|
byte[] |
var2 |
|
byte[] |
var3 |
|
byte[] |
var3 |
|
byte[] |
var3 |
|
int |
var3 |
|
int |
var3 |
|
int |
var3 |
|
int |
var3 |
|
int |
var3 |
|
byte[] |
var4 |
|
byte[] |
var4 |
|
int |
var4 |
|
int |
var4 |
|
int |
var4 |
|
int |
var4 |
|
int |
var4 |
|
StunMessage |
var5 |
|
byte[] |
var5 |
|
int |
var5 |
|
int |
var5 |
|
byte[] |
var5 |
|
int |
var5 |
|
byte[] |
var5 |
|
Mac |
var6 |
|
ByteBuffer |
var6 |
|
int |
var6 |
|
byte[] |
var6 |
|
ByteBuffer |
var7 |
|
ByteBuffer |
var7 |
|
StunMessage |
var7 |
|
byte[] |
var8 |
|
int |
var8 |
|
byte[] |
var9 |
|
int |
var9 |
Методы (64)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
public |
record |
Attributerecord Attribute(int type, byte[] value) |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("Transaction ID must be 12 bytes") |
abstract |
throw new |
IllegalStateExceptionthrow new IllegalStateException("HmacSHA1 is required for STUN message integrity", var2) |
abstract |
throw new |
IllegalStateExceptionthrow new IllegalStateException("HmacSHA1 is required for STUN message integrity", var1) |
public |
void |
addAttributevoid addAttribute(int var1, @Nonnull byte[] var2) |
public |
void |
addIceRolevoid addIceRole(boolean var1, long var2) |
public |
void |
addPriorityvoid addPriority(long var1) |
public |
void |
addUseCandidatevoid addUseCandidate() |
public |
void |
addUsernamevoid addUsername(@Nonnull String var1) |
public |
void |
addXorMappedAddressvoid addXorMappedAddress(@Nonnull InetSocketAddress var1) |
public |
void |
appendFingerprintvoid appendFingerprint() |
public |
void |
appendMessageIntegrityvoid appendMessageIntegrity(@Nonnull byte[] var1) |
static |
Mac |
createHmacSha1Mac createHmacSha1() |
static |
byte[] |
createXorMaskbyte[] createXorMask(int var0, byte[] var1) |
abstract |
return |
decodeMappedAddressreturn decodeMappedAddress(var1, true, this.transactionId) |
static |
StunMessage |
errorResponseStunMessage errorResponse(@Nonnull byte[] var0, int var1, @Nonnull String var2) |
static |
int |
findAttributeint findAttribute(ByteBuffer var0, int var1) |
|
|
for for(StunMessage.Attribute var3 : this.attributes) |
|
|
for for(int var6 = 0; var6 < var2.length; var6++) |
|
|
for for(StunMessage.Attribute var3 : this.attributes) |
|
|
for for(StunMessage.Attribute var4 : this.attributes) |
|
|
for for(int var6 = 0; var6 < var5; var6++) |
|
|
for for(int var7 = 0; var7 < var3; var7++) |
public |
int |
getMessageTypeint getMessageType() |
public |
long |
getPrioritylong getPriority() |
public |
byte[] |
getTransactionIdbyte[] getTransactionId() |
public |
boolean |
hasAttributeboolean hasAttribute(int var1) |
static |
byte[] |
hmacSha1byte[] hmacSha1(byte[] var0, byte[] var1) |
|
|
if if(var2.length != 12) |
|
|
if if(var1 != null) |
|
|
if if(var3 < 0) |
|
|
if if(var4 != 20) |
|
|
if if(var2 < 20) |
|
|
if if(var4 % 4 != 0) |
|
|
if if(20 + var4 != var2) |
|
|
if if(var8 + 4 + var11 > var9) |
|
|
if if(var10 == 8) |
|
|
if if(var2 < 20) |
|
|
if if(var2 < 20) |
|
|
if if(var3 > var2) |
|
|
if if(var4 + 4 + var6 > var3) |
|
|
if if(var5 == var1) |
|
|
if if(var0.length < 4) |
|
|
if if(var0.length != 4 + var3) |
|
|
if if(var1) |
|
|
if if(var0 > 4) |
static |
Mac |
initializeHmacSha1Mac initializeHmacSha1(byte[] var0) |
public |
boolean |
isRequestboolean isRequest() |
public |
boolean |
isResponseboolean isResponse() |
static |
boolean |
looksLikeStunboolean looksLikeStun(@Nonnull byte[] var0, int var1) |
static |
boolean |
looksLikeStunboolean looksLikeStun(@Nonnull ByteBuffer var0) |
static |
int |
readUnsignedShortint readUnsignedShort(byte[] var0, int var1) |
static |
int |
readUnsignedShortint readUnsignedShort(ByteBuffer var0, int var1) |
static |
StunMessage |
requestStunMessage request() |
static |
StunMessage |
responseStunMessage response(@Nonnull byte[] var0) |
private |
byte[] |
serializeWithReservedbyte[] serializeWithReserved(int var1) |
static |
int |
serializedLengthint serializedLength(int var0) |
public |
byte[] |
toBytesbyte[] toBytes() |
static |
boolean |
verifyMessageIntegrityboolean verifyMessageIntegrity(@Nonnull byte[] var0, int var1, @Nonnull byte[] var2) |
static |
boolean |
verifyMessageIntegrityboolean verifyMessageIntegrity(@Nonnull ByteBuffer var0, @Nonnull byte[] var1) |
|
|
while while(var8 + 4 <= var9) |
|
|
while while(var4 + 4 <= var3) |
static |
void |
writeUnsignedShortvoid writeUnsignedShort(byte[] var0, int var1, int var2) |
abstract |
|
writeUnsignedShort writeUnsignedShort(var2, 2, var2.length - 20 + var1) |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.io.ice;
class="kw">import java.net.InetAddress;
class="kw">import java.net.InetSocketAddress;
class="kw">import java.net.UnknownHostException;
class="kw">import java.nio.ByteBuffer;
class="kw">import java.nio.charset.StandardCharsets;
class="kw">import java.security.GeneralSecurityException;
class="kw">import java.security.MessageDigest;
class="kw">import java.security.SecureRandom;
class="kw">import java.util.ArrayList;
class="kw">import java.util.List;
class="kw">import java.util.zip.CRC32;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import javax.crypto.Mac;
class="kw">import javax.crypto.spec.SecretKeySpec;
class="kw">public class="kw">final class StunMessage {
class="kw">public class="kw">static class="kw">final int MAGIC_COOKIE = 554869826;
class="kw">public class="kw">static class="kw">final int HEADER_LENGTH = 20;
class="kw">public class="kw">static class="kw">final int TRANSACTION_ID_LENGTH = 12;
class="kw">public class="kw">static class="kw">final int BINDING_REQUEST = 1;
class="kw">public class="kw">static class="kw">final int BINDING_INDICATION = 17;
class="kw">public class="kw">static class="kw">final int BINDING_RESPONSE = 257;
class="kw">public class="kw">static class="kw">final int BINDING_ERROR_RESPONSE = 273;
class="kw">public class="kw">static class="kw">final int ATTR_MAPPED_ADDRESS = 1;
class="kw">public class="kw">static class="kw">final int ATTR_USERNAME = 6;
class="kw">public class="kw">static class="kw">final int ATTR_MESSAGE_INTEGRITY = 8;
class="kw">public class="kw">static class="kw">final int ATTR_ERROR_CODE = 9;
class="kw">public class="kw">static class="kw">final int ATTR_XOR_MAPPED_ADDRESS = 32;
class="kw">public class="kw">static class="kw">final int ATTR_PRIORITY = 36;
class="kw">public class="kw">static class="kw">final int ATTR_USE_CANDIDATE = 37;
class="kw">public class="kw">static class="kw">final int ATTR_FINGERPRINT = 32808;
class="kw">public class="kw">static class="kw">final int ATTR_ICE_CONTROLLED = 32809;
class="kw">public class="kw">static class="kw">final int ATTR_ICE_CONTROLLING = 32810;
class="kw">public class="kw">static class="kw">final int MESSAGE_INTEGRITY_LENGTH = 24;
class="kw">public class="kw">static class="kw">final int FINGERPRINT_LENGTH = 8;
class="kw">public class="kw">static class="kw">final int FINGERPRINT_XOR = 1398035790;
class="kw">private class="kw">static class="kw">final int MAX_ATTRIBUTES = 64;
class="kw">private class="kw">static class="kw">final SecureRandom RANDOM = new SecureRandom();
class="kw">private class="kw">static class="kw">final ThreadLocal<Mac> HMAC_SHA1 = ThreadLocal.withInitial(StunMessage::createHmacSha1);
class="kw">private class="kw">final int messageType;
class="kw">private class="kw">final byte[] transactionId;
class="kw">private class="kw">final List<StunMessage.Attribute> attributes = new ArrayList<>();
class="kw">public StunMessage(int var1, @Nonnull byte[] var2) {
if (var2.length != 12) {
throw new IllegalArgumentException("Transaction ID must be 12 bytes");
}
this.messageType = var1;
this.transactionId = var2;
}
class="kw">public class="kw">static StunMessage request() {
byte[] var0 = new byte[12];
RANDOM.nextBytes(var0);
class="kw">return new StunMessage(1, var0);
}
class="kw">public class="kw">static StunMessage response(@Nonnull byte[] var0) {
class="kw">return new StunMessage(257, var0);
}
class="kw">public class="kw">static StunMessage errorResponse(@Nonnull byte[] var0, int var1, @Nonnull String var2) {
byte[] var3 = var2.getBytes(StandardCharsets.UTF_8);
byte[] var4 = new byte[4 + var3.length];
var4[2] = (byte)(var1 / 100);
var4[3] = (byte)(var1 % 100);
System.arraycopy(var3, 0, var4, 4, var3.length);
StunMessage var5 = new StunMessage(273, var0);
var5.attributes.add(new StunMessage.Attribute(9, var4));
class="kw">return var5;
}
class="kw">public int getMessageType() {
class="kw">return this.messageType;
}
class="kw">public byte[] getTransactionId() {
class="kw">return this.transactionId;
}
class="kw">public boolean isRequest() {
class="kw">return this.messageType == 1;
}
class="kw">public boolean isResponse() {
class="kw">return this.messageType == 257;
}
@Nullable
class="kw">public byte[] getAttribute(int var1) {
for (StunMessage.Attribute var3 : this.attributes) {
if (var3.type() == var1) {
class="kw">return var3.value();
}
}
class="kw">return null;
}
class="kw">public boolean hasAttribute(int var1) {
class="kw">return this.getAttribute(var1) != null;
}
@Nullable
class="kw">public String getUsername() {
byte[] var1 = this.getAttribute(6);
class="kw">return var1 == null ? null : new String(var1, StandardCharsets.UTF_8);
}
class="kw">public long getPriority() {
byte[] var1 = this.getAttribute(36);
class="kw">return var1 != null && var1.length >= 4 ? Integer.toUnsignedLong(ByteBuffer.wrap(var1).getInt()) : 0L;
}
@Nullable
class="kw">public InetSocketAddress getMappedAddress() {
byte[] var1 = this.getAttribute(32);
if (var1 != null) {
class="kw">return decodeMappedAddress(var1, true, this.transactionId);
}
var1 = this.getAttribute(1);
class="kw">return var1 == null ? null : decodeMappedAddress(var1, false, this.transactionId);
}
class="kw">public void addAttribute(int var1, @Nonnull byte[] var2) {
this.attributes.add(new StunMessage.Attribute(var1, var2));
}
class="kw">public void addUsername(@Nonnull String var1) {
this.addAttribute(6, var1.getBytes(StandardCharsets.UTF_8));
}
class="kw">public void addPriority(long var1) {
byte[] var3 = new byte[4];
ByteBuffer.wrap(var3).putInt((int)var1);
this.addAttribute(36, var3);
}
class="kw">public void addUseCandidate() {
this.addAttribute(37, new byte[0]);
}
class="kw">public void addIceRole(boolean var1, long var2) {
byte[] var4 = new byte[8];
ByteBuffer.wrap(var4).putLong(var2);
this.addAttribute(var1 ? 32810 : 32809, var4);
}
class="kw">public void addXorMappedAddress(@Nonnull InetSocketAddress var1) {
byte[] var2 = var1.getAddress().getAddress();
byte[] var3 = new byte[4 + var2.length];
var3[0] = 0;
var3[1] = (byte)(var2.length == 4 ? 1 : 2);
int var4 = var1.getPort() ^ 8466;
var3[2] = (byte)(var4 >>> 8);
var3[3] = (byte)var4;
byte[] var5 = createXorMask(var2.length, this.transactionId);
for (int var6 = 0; var6 < var2.length; var6++) {
var3[4 + var6] = (byte)(var2[var6] ^ var5[var6]);
}
this.addAttribute(32, var3);
}
class="kw">public void appendMessageIntegrity(@Nonnull byte[] var1) {
byte[] var2 = hmacSha1(var1, this.serializeWithReserved(24));
this.attributes.add(new StunMessage.Attribute(8, var2));
}
class="kw">public void appendFingerprint() {
CRC32 var1 = new CRC32();
var1.update(this.serializeWithReserved(8));
byte[] var2 = new byte[4];
ByteBuffer.wrap(var2).putInt((int)(var1.getValue() ^ Integer.toUnsignedLong(1398035790)));
this.attributes.add(new StunMessage.Attribute(32808, var2));
}
class="kw">public class="kw">static boolean verifyMessageIntegrity(@Nonnull byte[] var0, int var1, @Nonnull byte[] var2) {
class="kw">return var1 >= 0 && var1 <= var0.length ? verifyMessageIntegrity(ByteBuffer.wrap(var0, 0, var1), var2) : false;
}
class="kw">public class="kw">static boolean verifyMessageIntegrity(@Nonnull ByteBuffer var0, @Nonnull byte[] var1) {
ByteBuffer var2 = var0.slice();
int var3 = findAttribute(var2, 8);
if (var3 < 0) {
class="kw">return false;
}
int var4 = readUnsignedShort(var2, var3 + 2);
if (var4 != 20) {
class="kw">return false;
}
int var5 = var3 - 20 + 24;
Mac var6 = initializeHmacSha1(var1);
var6.update(var2.get(0));
var6.update(var2.get(1));
var6.update((byte)(var5 >>> 8));
var6.update((byte)var5);
ByteBuffer var7 = var2.duplicate();
var7.position(4);
var7.limit(var3);
var6.update(var7);
byte[] var8 = var6.doFinal();
byte[] var9 = new byte[20];
ByteBuffer var10 = var2.duplicate();
var10.position(var3 + 4);
var10.get(var9);
class="kw">return MessageDigest.isEqual(var8, var9);
}
class="kw">public byte[] toBytes() {
int var1 = 0;
for (StunMessage.Attribute var3 : this.attributes) {
var1 += serializedLength(var3.value().length);
}
ByteBuffer var7 = ByteBuffer.allocate(20 + var1);
var7.putShort((short)this.messageType);
var7.putShort((short)var1);
var7.putInt(554869826);
var7.put(this.transactionId);
for (StunMessage.Attribute var4 : this.attributes) {
var7.putShort((short)var4.type());
var7.putShort((short)var4.value().length);
var7.put(var4.value());
int var5 = (4 - var4.value().length % 4) % 4;
for (int var6 = 0; var6 < var5; var6++) {
var7.put((byte)0);
}
}
class="kw">return var7.array();
}
@Nullable
class="kw">public class="kw">static StunMessage parse(@Nonnull byte[] var0, int var1) {
class="kw">return var1 >= 0 && var1 <= var0.length ? parse(ByteBuffer.wrap(var0, 0, var1)) : null;
}
@Nullable
class="kw">public class="kw">static StunMessage parse(@Nonnull ByteBuffer var0) {
ByteBuffer var1 = var0.slice();
int var2 = var1.remaining();
if (var2 < 20) {
class="kw">return null;
}
int var3 = readUnsignedShort(var1, 0);
if ((var3 & 49152) != 0) {
class="kw">return null;
}
int var4 = readUnsignedShort(var1, 2);
if (var4 % 4 != 0) {
class="kw">return null;
}
if (20 + var4 != var2) {
class="kw">return null;
}
if (var1.getInt(4) != 554869826) {
class="kw">return null;
}
byte[] var5 = new byte[12];
ByteBuffer var6 = var1.duplicate();
var6.position(8);
var6.get(var5);
StunMessage var7 = new StunMessage(var3, var5);
int var8 = 20;
int var9 = 20 + var4;
while (var8 + 4 <= var9) {
if (var7.attributes.size() >= 64) {
class="kw">return null;
}
int var10 = readUnsignedShort(var1, var8);
int var11 = readUnsignedShort(var1, var8 + 2);
if (var8 + 4 + var11 > var9) {
class="kw">return null;
}
byte[] var12 = new byte[var11];
ByteBuffer var13 = var1.duplicate();
var13.position(var8 + 4);
var13.get(var12);
var7.attributes.add(new StunMessage.Attribute(var10, var12));
var8 += serializedLength(var11);
if (var10 == 8) {
break;
}
}
class="kw">return var7;
}
class="kw">public class="kw">static boolean looksLikeStun(@Nonnull byte[] var0, int var1) {
class="kw">return var1 >= 0 && var1 <= var0.length ? looksLikeStun(ByteBuffer.wrap(var0, 0, var1)) : false;
}
class="kw">public class="kw">static boolean looksLikeStun(@Nonnull ByteBuffer var0) {
ByteBuffer var1 = var0.slice();
int var2 = var1.remaining();
if (var2 < 20) {
class="kw">return false;
}
if ((var1.get(0) & 192) != 0) {
class="kw">return false;
}
if (var1.getInt(4) != 554869826) {
class="kw">return false;
}
int var3 = readUnsignedShort(var1, 2);
class="kw">return var3 % 4 == 0 && 20 + var3 == var2;
}
class="kw">private byte[] serializeWithReserved(int var1) {
byte[] var2 = this.toBytes();
writeUnsignedShort(var2, 2, var2.length - 20 + var1);
class="kw">return var2;
}
class="kw">private class="kw">static int serializedLength(int var0) {
class="kw">return 4 + var0 + (4 - var0 % 4) % 4;
}
class="kw">private class="kw">static int findAttribute(ByteBuffer var0, int var1) {
int var2 = var0.remaining();
if (var2 < 20) {
class="kw">return -1;
}
int var3 = 20 + readUnsignedShort(var0, 2);
if (var3 > var2) {
class="kw">return -1;
}
int var4 = 20;
while (var4 + 4 <= var3) {
int var5 = readUnsignedShort(var0, var4);
int var6 = readUnsignedShort(var0, var4 + 2);
if (var4 + 4 + var6 > var3) {
class="kw">return -1;
}
if (var5 == var1) {
class="kw">return var4;
}
var4 += serializedLength(var6);
}
class="kw">return -1;
}
class="kw">private class="kw">static byte[] hmacSha1(byte[] var0, byte[] var1) {
class="kw">return initializeHmacSha1(var0).doFinal(var1);
}
class="kw">private class="kw">static Mac initializeHmacSha1(byte[] var0) {
try {
Mac var1 = HMAC_SHA1.get();
var1.init(new SecretKeySpec(var0, "HmacSHA1"));
class="kw">return var1;
} catch (GeneralSecurityException var2) {
throw new IllegalStateException("HmacSHA1 is required for STUN message integrity", var2);
}
}
class="kw">private class="kw">static Mac createHmacSha1() {
try {
class="kw">return Mac.getInstance("HmacSHA1");
} catch (GeneralSecurityException var1) {
throw new IllegalStateException("HmacSHA1 is required for STUN message integrity", var1);
}
}
@Nullable
class="kw">private class="kw">static InetSocketAddress decodeMappedAddress(byte[] var0, boolean var1, byte[] var2) {
if (var0.length < 4) {
class="kw">return null;
}
int var3 = class="kw">switch (var0[1] & 0xFF) {
case 1 -> 4;
case 2 -> 16;
class="kw">default -> -1;
};
if (var0.length != 4 + var3) {
class="kw">return null;
}
int var4 = readUnsignedShort(var0, 2);
byte[] var5 = new byte[var3];
System.arraycopy(var0, 4, var5, 0, var3);
if (var1) {
var4 ^= 8466;
byte[] var6 = createXorMask(var3, var2);
for (int var7 = 0; var7 < var3; var7++) {
var5[var7] ^= var6[var7];
}
}
try {
class="kw">return new InetSocketAddress(InetAddress.getByAddress(var5), var4);
} catch (UnknownHostException var8) {
class="kw">return null;
}
}
class="kw">private class="kw">static byte[] createXorMask(int var0, byte[] var1) {
byte[] var2 = new byte[var0];
ByteBuffer.wrap(var2).putInt(554869826);
if (var0 > 4) {
System.arraycopy(var1, 0, var2, 4, 12);
}
class="kw">return var2;
}
class="kw">private class="kw">static int readUnsignedShort(byte[] var0, int var1) {
class="kw">return (var0[var1] & 0xFF) << 8 | var0[var1 + 1] & 0xFF;
}
class="kw">private class="kw">static int readUnsignedShort(ByteBuffer var0, int var1) {
class="kw">return (var0.get(var1) & 0xFF) << 8 | var0.get(var1 + 1) & 0xFF;
}
class="kw">private class="kw">static void writeUnsignedShort(byte[] var0, int var1, int var2) {
var0[var1] = (byte)(var2 >>> 8);
var0[var1 + 1] = (byte)var2;
}
class="kw">public record Attribute(int type, byte[] value) {
class="kw">public Attribute {
}
}
}