feat: finalize channels fixes and runtime stability

This commit is contained in:
DrygMira
2026-04-13 23:00:36 +03:00
parent 0c7d8fac02
commit a9c69e5947
46 changed files with 4654 additions and 356 deletions
@@ -6,6 +6,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.regex.Pattern;
import java.util.Objects;
/**
@@ -39,6 +40,10 @@ public final class CreateChannelBody implements BodyRecord, BodyHasLine {
public static final short SUBTYPE = MsgSubType.TECH_CREATE_CHANNEL;
private static final byte[] ZERO32 = new byte[32];
private static final int MIN_NAME_LENGTH = 3;
private static final int MAX_NAME_LENGTH = 32;
private static final Pattern ALLOWED_NAME_PATTERN =
Pattern.compile("^[\\p{IsLatin}\\p{IsCyrillic}0-9 _-]+$");
public final short subType; // из header
public final short version; // из header
@@ -121,14 +126,15 @@ public final class CreateChannelBody implements BodyRecord, BodyHasLine {
if ((subType & 0xFFFF) != (SUBTYPE & 0xFFFF))
throw new IllegalArgumentException("CreateChannelBody subType must be TECH_CREATE_CHANNEL(1)");
if (channelName == null || channelName.isBlank())
String normalizedName = normalizeDisplayName(channelName);
if (normalizedName.isEmpty())
throw new IllegalArgumentException("channelName is blank");
if (!channelName.matches("^[A-Za-z0-9_]+$"))
throw new IllegalArgumentException("channelName must match ^[A-Za-z0-9_]+$");
if ("0".equals(channelName))
throw new IllegalArgumentException("channelName \"0\" is reserved");
int cpLen = normalizedName.codePointCount(0, normalizedName.length());
// Backward compatibility for historical blocks:
// strict create-channel rules are enforced in AddBlock handler (ChannelNameRules),
// but parser-level check must allow legacy channel names during bootstrap/replay.
if (cpLen > MAX_NAME_LENGTH)
throw new IllegalArgumentException("channelName length must be <=32");
// tech-line: prev обязателен (минимум HEADER=0)
if (prevLineNumber < 0)
@@ -141,6 +147,11 @@ public final class CreateChannelBody implements BodyRecord, BodyHasLine {
return this;
}
private static String normalizeDisplayName(String value) {
if (value == null) return "";
return value.trim().replaceAll("\\s+", " ");
}
@Override
public byte[] toBytes() {
byte[] nameUtf8 = channelName.getBytes(StandardCharsets.UTF_8);
@@ -167,4 +178,4 @@ public final class CreateChannelBody implements BodyRecord, BodyHasLine {
@Override public int prevLineBlockGlobalNumber() { return prevLineNumber; }
@Override public byte[] prevLineBlockHash32() { return prevLineHash32 == null ? null : Arrays.copyOf(prevLineHash32, 32); }
@Override public int lineSeq() { return thisLineNumber; }
}
}