feat: port session 07 — Protocol Parser, Auth extras (TPM/certidp/certstore), Internal utilities & data structures
Session 07 scope (5 features, 17 tests, ~1165 Go LOC): - Protocol/ParserTypes.cs: ParserState enum (79 states), PublishArgument, ParseContext - Protocol/IProtocolHandler.cs: handler interface decoupling parser from client - Protocol/ProtocolParser.cs: Parse(), ProtoSnippet(), OverMaxControlLineLimit(), ProcessPub/HeaderPub/RoutedMsgArgs/RoutedHeaderMsgArgs, ClonePubArg(), GetHeader() - tests/Protocol/ProtocolParserTests.cs: 17 tests via TestProtocolHandler stub Auth extras from session 06 (committed separately): - Auth/TpmKeyProvider.cs, Auth/CertificateIdentityProvider/, Auth/CertificateStore/ Internal utilities & data structures (session 06 overflow): - Internal/AccessTimeService.cs, ElasticPointer.cs, SystemMemory.cs, ProcessStatsProvider.cs - Internal/DataStructures/GenericSublist.cs, HashWheel.cs - Internal/DataStructures/SubjectTree.cs, SubjectTreeNode.cs, SubjectTreeParts.cs All 461 tests pass (460 unit + 1 integration). DB updated for features 2588-2592 and tests 2598-2614.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
// Copyright 2012-2025 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Adapted from server/parser.go and server/client.go in the NATS server Go source.
|
||||
|
||||
namespace ZB.MOM.NatsNet.Server.Protocol;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for the protocol handler callbacks invoked by <see cref="ProtocolParser.Parse"/>.
|
||||
/// Decouples the state machine from the client implementation.
|
||||
/// The client connection will implement this interface in later sessions.
|
||||
/// </summary>
|
||||
public interface IProtocolHandler
|
||||
{
|
||||
// ---- Dynamic connection state ----
|
||||
|
||||
bool IsMqtt { get; }
|
||||
bool Trace { get; }
|
||||
bool HasMappings { get; }
|
||||
bool IsAwaitingAuth { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to register the no-auth user for this connection.
|
||||
/// Returns true if a no-auth user was found and registered (allowing parse to continue).
|
||||
/// </summary>
|
||||
bool TryRegisterNoAuthUser();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this is a gateway inbound connection that has not yet received CONNECT.
|
||||
/// </summary>
|
||||
bool IsGatewayInboundNotConnected { get; }
|
||||
|
||||
// ---- Protocol action handlers ----
|
||||
|
||||
Exception? ProcessConnect(byte[] arg);
|
||||
Exception? ProcessInfo(byte[] arg);
|
||||
void ProcessPing();
|
||||
void ProcessPong();
|
||||
void ProcessErr(string arg);
|
||||
|
||||
// ---- Sub/unsub handlers (kind-specific) ----
|
||||
|
||||
Exception? ProcessClientSub(byte[] arg);
|
||||
Exception? ProcessClientUnsub(byte[] arg);
|
||||
Exception? ProcessRemoteSub(byte[] arg, bool isLeaf);
|
||||
Exception? ProcessRemoteUnsub(byte[] arg, bool isLeafUnsub);
|
||||
Exception? ProcessGatewayRSub(byte[] arg);
|
||||
Exception? ProcessGatewayRUnsub(byte[] arg);
|
||||
Exception? ProcessLeafSub(byte[] arg);
|
||||
Exception? ProcessLeafUnsub(byte[] arg);
|
||||
Exception? ProcessAccountSub(byte[] arg);
|
||||
void ProcessAccountUnsub(byte[] arg);
|
||||
|
||||
// ---- Message processing ----
|
||||
|
||||
void ProcessInboundMsg(byte[] msg);
|
||||
bool SelectMappedSubject();
|
||||
|
||||
// ---- Tracing ----
|
||||
|
||||
void TraceInOp(string name, byte[]? arg);
|
||||
void TraceMsg(byte[] msg);
|
||||
|
||||
// ---- Error handling ----
|
||||
|
||||
void SendErr(string msg);
|
||||
void AuthViolation();
|
||||
void CloseConnection(int reason);
|
||||
string KindString();
|
||||
}
|
||||
171
dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ParserTypes.cs
Normal file
171
dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ParserTypes.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright 2012-2025 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Adapted from server/parser.go in the NATS server Go source.
|
||||
|
||||
using ZB.MOM.NatsNet.Server.Internal;
|
||||
|
||||
namespace ZB.MOM.NatsNet.Server.Protocol;
|
||||
|
||||
/// <summary>
|
||||
/// Parser state machine states.
|
||||
/// Mirrors the Go <c>parserState</c> const block in parser.go (79 states).
|
||||
/// </summary>
|
||||
public enum ParserState
|
||||
{
|
||||
OpStart = 0,
|
||||
OpPlus,
|
||||
OpPlusO,
|
||||
OpPlusOk,
|
||||
OpMinus,
|
||||
OpMinusE,
|
||||
OpMinusEr,
|
||||
OpMinusErr,
|
||||
OpMinusErrSpc,
|
||||
MinusErrArg,
|
||||
OpC,
|
||||
OpCo,
|
||||
OpCon,
|
||||
OpConn,
|
||||
OpConne,
|
||||
OpConnec,
|
||||
OpConnect,
|
||||
ConnectArg,
|
||||
OpH,
|
||||
OpHp,
|
||||
OpHpu,
|
||||
OpHpub,
|
||||
OpHpubSpc,
|
||||
HpubArg,
|
||||
OpHm,
|
||||
OpHms,
|
||||
OpHmsg,
|
||||
OpHmsgSpc,
|
||||
HmsgArg,
|
||||
OpP,
|
||||
OpPu,
|
||||
OpPub,
|
||||
OpPubSpc,
|
||||
PubArg,
|
||||
OpPi,
|
||||
OpPin,
|
||||
OpPing,
|
||||
OpPo,
|
||||
OpPon,
|
||||
OpPong,
|
||||
MsgPayload,
|
||||
MsgEndR,
|
||||
MsgEndN,
|
||||
OpS,
|
||||
OpSu,
|
||||
OpSub,
|
||||
OpSubSpc,
|
||||
SubArg,
|
||||
OpA,
|
||||
OpAsub,
|
||||
OpAsubSpc,
|
||||
AsubArg,
|
||||
OpAusub,
|
||||
OpAusubSpc,
|
||||
AusubArg,
|
||||
OpL,
|
||||
OpLs,
|
||||
OpR,
|
||||
OpRs,
|
||||
OpU,
|
||||
OpUn,
|
||||
OpUns,
|
||||
OpUnsu,
|
||||
OpUnsub,
|
||||
OpUnsubSpc,
|
||||
UnsubArg,
|
||||
OpM,
|
||||
OpMs,
|
||||
OpMsg,
|
||||
OpMsgSpc,
|
||||
MsgArg,
|
||||
OpI,
|
||||
OpIn,
|
||||
OpInf,
|
||||
OpInfo,
|
||||
InfoArg,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parsed publish/message arguments.
|
||||
/// Mirrors Go <c>pubArg</c> struct in parser.go.
|
||||
/// </summary>
|
||||
public sealed class PublishArgument
|
||||
{
|
||||
public byte[]? Arg { get; set; }
|
||||
public byte[]? PaCache { get; set; }
|
||||
public byte[]? Origin { get; set; }
|
||||
public byte[]? Account { get; set; }
|
||||
public byte[]? Subject { get; set; }
|
||||
public byte[]? Deliver { get; set; }
|
||||
public byte[]? Mapped { get; set; }
|
||||
public byte[]? Reply { get; set; }
|
||||
public byte[]? SizeBytes { get; set; }
|
||||
public byte[]? HeaderBytes { get; set; }
|
||||
public List<byte[]>? Queues { get; set; }
|
||||
public int Size { get; set; }
|
||||
public int HeaderSize { get; set; } = -1;
|
||||
public bool Delivered { get; set; }
|
||||
|
||||
/// <summary>Resets all fields to their defaults.</summary>
|
||||
public void Reset()
|
||||
{
|
||||
Arg = null;
|
||||
PaCache = null;
|
||||
Origin = null;
|
||||
Account = null;
|
||||
Subject = null;
|
||||
Deliver = null;
|
||||
Mapped = null;
|
||||
Reply = null;
|
||||
SizeBytes = null;
|
||||
HeaderBytes = null;
|
||||
Queues = null;
|
||||
Size = 0;
|
||||
HeaderSize = -1;
|
||||
Delivered = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds the parser state for a single connection.
|
||||
/// Mirrors Go <c>parseState</c> struct embedded in <c>client</c>.
|
||||
/// </summary>
|
||||
public sealed class ParseContext
|
||||
{
|
||||
// ---- Parser state ----
|
||||
|
||||
public ParserState State { get; set; }
|
||||
public byte Op { get; set; }
|
||||
public int ArgStart { get; set; }
|
||||
public int Drop { get; set; }
|
||||
public PublishArgument Pa { get; } = new();
|
||||
public byte[]? ArgBuf { get; set; }
|
||||
public byte[]? MsgBuf { get; set; }
|
||||
|
||||
// ---- Connection-level properties (set once at creation) ----
|
||||
|
||||
public ClientKind Kind { get; set; }
|
||||
public int MaxControlLine { get; set; } = ServerConstants.MaxControlLineSize;
|
||||
public int MaxPayload { get; set; } = -1;
|
||||
public bool HasHeaders { get; set; }
|
||||
|
||||
// ---- Internal scratch buffer ----
|
||||
|
||||
internal byte[] Scratch { get; } = new byte[ServerConstants.MaxControlLineSize];
|
||||
}
|
||||
1255
dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProtocolParser.cs
Normal file
1255
dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProtocolParser.cs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user