using System.Security.Cryptography; using System.Text; namespace XFEEliteDangerous.NativeFormat.Replication; public sealed class EdServerRouteSchemaException(string kind,uint nameBytes,int depth):NotSupportedException("Unsupported bounded route schema.") { public string Kind{get;}=kind; public uint NameBytes{get;}=nameBytes; public int Depth{get;}=depth; } public sealed class EdServerRouteMetadata { private readonly byte[] digest; internal EdServerRouteMetadata(ulong machine,bool request,int endpoints,IReadOnlyList schemes,byte[] digest) =>(MachineRunId,IsRequest,EndpointCount,Schemes,this.digest)=(machine,request,endpoints,schemes,digest); public ulong MachineRunId{get;} //4C373D0 explicitly labels flag1 as "request" and flag0 as "update". public bool IsRequest{get;} public int EndpointCount{get;} public IReadOnlyList Schemes{get;} public byte[] CopyIdentityDigest()=>digest.ToArray(); public override string ToString()=>$"Route metadata: request={IsRequest}, endpoints={EndpointCount}"; } // Pinned readers:4C372C0 U48+bool;4C18B10 ordinary narrow type name; // IP4 factory4C10A50;IP4NAT4C10D00;Comp4C113E0;Relay4C11C10. // This parses metadata // only. No advertised address is used to open, redirect or authorize a socket. public static class EdServerRouteMessageCodec { public static byte[] EncodeIp4Update(ulong machine,EdServerIp4Endpoint endpoint,int typeBits=16) { if(machine is 0 or >EdServerDatagramHeader.MaximumRunId||endpoint.Address!=0x7F000001||endpoint.Port==0||endpoint.Mtu is <576 or >1472) throw new ArgumentException("A private logical IPv4 route is required."); var bytes=new byte[(typeBits+169+7)/8];var p=0; EdServerControlMessageCodec.WriteLetterType(bytes,ref p,(byte)EdServerBuiltInLetter.Route,typeBits); void Write(ulong value,int count){for(var bit=0;bit>bit)&1)!=0)bytes[p/8]|=(byte)(1<<(p%8));} Write(machine,48);Write(0,1);Write(3,32);foreach(var value in Encoding.ASCII.GetBytes("IP4"))Write(value,8); Write(endpoint.Address,32);Write(endpoint.Port,16);Write(endpoint.Mtu,16); return bytes; } public static EdServerRouteMetadata ReadBody(ReadOnlySpan bytes,ref int bitOffset) { var start=bitOffset;var p=start;var machine=Read(bytes,ref p,48);var removed=Read(bytes,ref p,1)!=0; var schemes=new List();var endpoints=0; if(!removed)ReadEndpoint(bytes,ref p,0,schemes,ref endpoints); if(p-start>1472*8)throw new InvalidDataException("Route metadata exceeds the local datagram bound."); var canonical=new byte[(p-start+7)/8]; try { for(var index=0;index bytes,ref int p,int depth,List schemes,ref int endpoints) { if(depth>4||schemes.Count>=16)throw new InvalidDataException("Route nesting exceeds the local bound."); var length=Read(bytes,ref p,32);if(length>8)throw new EdServerRouteSchemaException("name-length",(uint)length,depth); Span name=stackalloc byte[8]; for(var index=0;index<(int)length;index++)name[index]=(byte)Read(bytes,ref p,8); var scheme=Encoding.ASCII.GetString(name[..(int)length]);schemes.Add(scheme); switch(scheme) { case "":return; case "IP4":Read(bytes,ref p,32);Read(bytes,ref p,16);Read(bytes,ref p,16);endpoints++;return; // Factory4C11C80: two U64 address halves, U16 port, U16 MTU. // Parsed metadata only, no IPv6 child socket or route authority. case "IP6":Read(bytes,ref p,64);Read(bytes,ref p,64);Read(bytes,ref p,16);Read(bytes,ref p,16);endpoints++;return; // Turn6 factory4C11ED0 reads one U32 and U16. case "Turn6":Read(bytes,ref p,32);Read(bytes,ref p,16);endpoints++;return; // Factory4C11C10 ignores the stream argument and constructs the // marker via4C31430. There is no body after the scheme name. case "Relay":endpoints++;return; case "IP4NAT": for(var index=0;index<4;index++){Read(bytes,ref p,32);Read(bytes,ref p,16);} Read(bytes,ref p,8);Read(bytes,ref p,1);Read(bytes,ref p,1);Read(bytes,ref p,32);endpoints++;return; case "Comp": var count=Read(bytes,ref p,16);if(count>4)throw new InvalidDataException("Route collection exceeds the local bound."); for(var index=0;index<(int)count;index++)ReadEndpoint(bytes,ref p,depth+1,schemes,ref endpoints);return; default:throw new EdServerRouteSchemaException("unknown-name",(uint)length,depth); } } private static ulong Read(ReadOnlySpan bytes,ref int p,int count) { if(p<0||(long)p+count>(long)bytes.Length*8)throw new InvalidDataException("Route metadata is truncated."); ulong value=0;for(var bit=0;bit>(p%8))&1)<