protected virtual bool ResponseAuthentication(SkylakeNATClient socket, IPAddress local, IPAddress dhcp, IPAddress dns) { byte[] message = new byte[sizeof(NATAuthenticationResponse)]; fixed(byte *pinned = message) { NATAuthenticationResponse *response = (NATAuthenticationResponse *)pinned; response->dhcp.local = (uint)Ethernet.GetAddress(local); response->dhcp.dhcp = (uint)Ethernet.GetAddress(dhcp); response->dhcp.dns = (uint)Ethernet.GetAddress(dns); } socket.Address = local; return(socket.Send(new SkylakeNATMessage(new BufferSegment(message)) { Commands = Commands.NATCommands_kAuthentication, })); }
public Router(IPAddress ethernet, int port, string key, int subtract) { if (ethernet == null) { throw new ArgumentNullException("It is not allowed to specify an ethernet card address with a null value"); } if (IPEndPoint.MinPort >= port || port > IPEndPoint.MaxPort) { throw new ArgumentOutOfRangeException($"The port used to connect to the server is less than or equal to {IPEndPoint.MinPort} or greater than {IPEndPoint.MaxPort}"); } this.Port = port; this.Key = key; this.Subtract = subtract; #if !__USE_UDP_PAYLOAD_TAP_PACKET this._server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this._server.NoDelay = true; this._server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); #else this._server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); this._server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); #endif this._server.Bind(new IPEndPoint(ethernet, port)); this._onSocketAbort = (sender, e) => { if (sender is SkylakeNATClient socket) { socket.Close(); if (socket.Address != null) { lock (this._sockets) { bool deleteCompletely = false; if (_sockets.TryGetValue(socket.Address, out LinkedList <SkylakeNATClient> s)) { if (s == null) { deleteCompletely = true; } else { var node = socket._rsv_current; if (node != null) { var l = node.List; if (l != null) { l.Remove(node); } socket._rsv_current = null; } if (s.Count <= 0) { deleteCompletely = true; } } } if (deleteCompletely) { _sockets.TryRemove(socket.Address, out s); lock (_addressAllocation) { _addressAllocation.TryRemove(socket.Id, out IPAddress address_x); if (socket.Address != null) { _assignedAddresses.Remove(socket.Address); } else if (address_x != null) { _assignedAddresses.Remove(address_x); } } } } this.ProcessAbort(socket); } } }; this._onSocketMessage = (sender, e) => { if (sender is SkylakeNATClient socket) { this.ProcessMessage(socket, e); } }; this._onAuthentication = (sender, e) => { if (sender is SkylakeNATClient socket) { this.ProcessAuthentication(socket); } }; // 建立以太网NAT链路工作引擎 #if NO_USAGE_PCAP_NET this.Ethernet = new Ethernet(ethernet, false); #else this.Ethernet = new Ethernet(ethernet, true); #endif this.NAT = new NAT(this.Ethernet.GetEthernetAddress()); // 建立以太网NAT传入传出链路 this.NAT.PublicOutput += (sender, e) => this.Ethernet.Output(e); this.NAT.PrivateOutput += (seder, e) => this.PrivateOutput(e); this.Ethernet.PublicInput += (sender, e) => this.NAT.PublicInput(e); #if __USE_UDP_PAYLOAD_TAP_PACKET this._doAgingswNatClientContextTimer = new Timer(); this._doAgingswNatClientContextTimer.Elapsed += (sender, e) => { foreach (var kv in _natClientTable) { bool freely = false; var context = kv.Value; if (context == null) { freely = true; } else { SkylakeNATClient clients = null; lock (context) { if (context.agingsw.ElapsedMilliseconds >= 10000) { freely = true; clients = context.client; } } clients?.OnAbort(EventArgs.Empty); } if (freely) { lock (this._sockets) { SkylakeNATClient clients = context.client; if (clients != null) { IPAddress address = IPAddress.Any; lock (_addressAllocation) { _addressAllocation.TryRemove(clients.Id, out address); if (address == null) { address = clients.Address; } if (address != null && !Ethernet.Equals(address, IPAddress.Any)) { _assignedAddresses.Remove(address); _sockets.TryRemove(address, out LinkedList <SkylakeNATClient> linkedlist_xx); } } } _natClientTable.TryRemove(kv.Key, out NATClientContext context_xx); } } } }; this._doAgingswNatClientContextTimer.Interval = 500; this._doAgingswNatClientContextTimer.Start(); #endif }