Exemple #1
0
        /// <summary>
        /// Creates and adds a new connection mapping to the NAT.
        /// </summary>
        /// <param name="networkPort">The network interface number of the inside node.</param>
        /// <param name="insideNode">The inside node.</param>
        /// <param name="outsideNode">The outside node.</param>
        /// <param name="connection">The <see cref="NatConnection{TPacket, TNode}"/> that is created.</param>
        private void CreateMapping(int networkPort, TNode insideNode, TNode outsideNode, out NatConnection <TPacket, TNode> connection)
        {
            // Get the node which the outside node will see as the source. E.g. the NAT with a new TCP port
            var natNode = CreateMasqueradeNode(OutsideFacingAddress, Port_Drop, PaxConfig.deviceMap[Port_Outside].MacAddress);

            // Create connection object
            connection = new NatConnection <TPacket, TNode>(insideNode, outsideNode, natNode, GetInitialStateForNewConnection());

            // Add to NAT_MapToOutside
            var toOutsideKey = new ConnectionKey(insideNode, outsideNode);

            NAT_MapToOutside[toOutsideKey] = connection;

            // Add to NAT_MapToInside
            var toInsideKey = new ConnectionKey(outsideNode, natNode);

            NAT_MapToInside[toInsideKey] = connection;

#if DEBUG
            Console.WriteLine("Added mapping");
            Console.WriteLine("Inside: {0}", insideNode);
            Console.WriteLine("Outside: {0}", outsideNode);
            Console.WriteLine("Nat: {0}", natNode);
            PrintMappings();
#endif
        }
Exemple #2
0
        /// <summary>
        /// Remove connections that have timed out or are closed.
        /// </summary>
        public void GarbageCollectConnections()
        {
            bool     removedAny = false;
            DateTime now        = DateTime.Now;

            foreach (var pair in NAT_MapToInside)
            {
                NatConnection <TPacket, TNode> connection = pair.Value;
                bool removeEntry = false;
                if (now - connection.LastUsed > InactivityTimeout)
                {
                    removeEntry = true;
#if DEBUG
                    Console.WriteLine("Removing inactive connection (LastUsed {0}, Diff {1}, InactivityTimeout {2})",
                                      connection.LastUsed.ToShortTimeString(),
                                      (now - connection.LastUsed).ToString(),
                                      InactivityTimeout);
#endif
                }
                else if (connection.State.CanBeClosed)
                {
                    removeEntry = true;
#if DEBUG
                    Console.WriteLine("Removing closed connection (LastUsed {0}, Diff {1}, InactivityTimeout {2})",
                                      connection.LastUsed.ToShortTimeString(),
                                      (now - connection.LastUsed).ToString(),
                                      InactivityTimeout);
#endif
                }

                if (removeEntry)
                {
                    // Remove this connection from both lookups
                    NAT_MapToInside.Remove(pair);
                    NAT_MapToOutside.Remove(new ConnectionKey(connection.InsideNode, connection.OutsideNode));
#if DEBUG
                    removedAny = true;
#endif
                }
            }

#if DEBUG
            if (removedAny)
            {
                PrintMappings();
            }
#endif

            // FIXME - currently O(n); improve performance for sparse traffic.
            // Could use a regularly invoked GC, and keep the connections in one of two pools:
            //   - For connections with lower traffic, keep a double-LL of MRU, moving the connection to the head when used,
            //     and start at the LRU end when iterating. Needs to be concurrent.
            //     Cost is per packet, and maintains an ordering, meaning we only need to check those that have expired plus one extra.
            //   - For connections with higher traffic, it would be less expensive to leave unsorted and iterate in O(n).
            // However, this would add complexity in terms of tracking which pool each connection should be in.
        }