using System.Text; namespace NATS.Server.Gateways; /// /// Gateway wire protocol command types matching Go's gateway.go format. /// Go reference: gateway.go:90-120 — gateway protocol constants. /// public enum GatewayCommandType { /// Gateway connection info exchange. Info, /// Subscribe interest notification. Sub, /// Unsubscribe interest notification. Unsub, /// Account interest mode change. Mode, /// Routed message through gateway. Msg, /// Ping keepalive. Ping, /// Pong keepalive response. Pong, } /// /// Gateway wire protocol byte sequences and formatting helpers matching Go's gateway protocol. /// Go reference: gateway.go:90-120 — gateway protocol constants and command formatting. /// public static class GatewayCommands { // Wire format byte sequences matching Go's gateway protocol public static readonly byte[] InfoPrefix = "GINFO "u8.ToArray(); public static readonly byte[] SubPrefix = "GS+ "u8.ToArray(); public static readonly byte[] UnsubPrefix = "GS- "u8.ToArray(); public static readonly byte[] ModePrefix = "GMODE "u8.ToArray(); public static readonly byte[] MsgPrefix = "GMSG "u8.ToArray(); public static readonly byte[] Ping = "GPING\r\n"u8.ToArray(); public static readonly byte[] Pong = "GPONG\r\n"u8.ToArray(); public static readonly byte[] Crlf = "\r\n"u8.ToArray(); /// /// Formats a gateway subscribe command. /// Wire format: GS+ {account} {subject}\r\n /// Go reference: gateway.go — sendGatewaySubsToGateway, RS+ propagation. /// public static byte[] FormatSub(string account, string subject) => Encoding.UTF8.GetBytes($"GS+ {account} {subject}\r\n"); /// /// Formats a gateway unsubscribe command. /// Wire format: GS- {account} {subject}\r\n /// Go reference: gateway.go — sendGatewayUnsubToGateway, RS- propagation. /// public static byte[] FormatUnsub(string account, string subject) => Encoding.UTF8.GetBytes($"GS- {account} {subject}\r\n"); /// /// Formats a gateway mode change command. /// Wire format: GMODE {account} {mode}\r\n /// Mode: "O" for Optimistic (send everything), "I" for Interest-only. /// Go reference: gateway.go — switchAccountToInterestMode, GMODE command. /// public static byte[] FormatMode(string account, GatewayInterestMode mode) { var modeStr = mode == GatewayInterestMode.InterestOnly ? "I" : "O"; return Encoding.UTF8.GetBytes($"GMODE {account} {modeStr}\r\n"); } /// /// Parses a gateway command type from the first bytes of a line. /// Returns null if the command prefix is unrecognized. /// Go reference: gateway.go — processGatewayMsg command dispatch. /// public static GatewayCommandType? ParseCommandType(ReadOnlySpan line) { if (line.StartsWith(InfoPrefix)) return GatewayCommandType.Info; if (line.StartsWith(SubPrefix)) return GatewayCommandType.Sub; if (line.StartsWith(UnsubPrefix)) return GatewayCommandType.Unsub; if (line.StartsWith(ModePrefix)) return GatewayCommandType.Mode; if (line.StartsWith(MsgPrefix)) return GatewayCommandType.Msg; if (line.StartsWith(Ping)) return GatewayCommandType.Ping; if (line.StartsWith(Pong)) return GatewayCommandType.Pong; return null; } }