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 {
      }
   }
}