Пример #1
0
        // World-wide remap
        private void wwRemap()
        {
            // Map the network with tracking numbers
            DoMap();

            // Poke the next node to allow it to start mapping.

            // Gather a list of all nodes in the network (not including self)
            List <int> allNodes = pathDictionary.Keys.ToList();

            allNodes.Sort();


            if (allNodes.Count > 0)
            {
                // Create a packet to send to the next node to map
                packet pokePacket = packetBuilder.CreatePokePacket(nodeID, allNodes[0]);

                // We will poke the lowest ID in the world (unless that's me???) TODO: Check what happens when lowest ID is the last to come online
                pokePacket.currentDestination = pathDictionary[allNodes[0]];
                SendPacket(pokePacket);
            }
            else  // Edge case: we are the first node online.  Mapping found nobody!  I'm so alone!!!
            {
                if (RFNET.debugging)
                {
                    Console.WriteLine("I am the first node to come up or there are none within range.");
                }
            }
        }
Пример #2
0
        public static packet CreateNeighborsPacket()
        {
            packet response = new packet();

            response.packetType = 4;
            return(response);
        }
Пример #3
0
        // Send packet   PORTED
        public void SendPacket(packet outgoingPacket)
        {
            if (RFNET.debugging)
            {
                Console.WriteLine("Sending packet:\tFrom " + nodeID + " to: " + outgoingPacket.currentDestination +
                                  " final destination: " + outgoingPacket.finalDestination + " type: " + outgoingPacket.packetType + " payload: " + outgoingPacket.payload);
            }
            RFNET.packetCount++;  // SIM ONLY
            // Note that we don't send the packet directly to the destination node object, but rather we
            //  send it to the nodes that are in range, no matter who they are.  This way we can simulate
            //  ranged communication between non-adjacent nodes.
            List <int> onlinePhysNeighbors = new List <int>(physNeighbors);  //SIM

            foreach (int offline in RFNET.offlineNodeList)
            {
                onlinePhysNeighbors.Remove(offline);  // SIM
            }

            foreach (int physNeighbor in onlinePhysNeighbors)
            {
                // If we are the last hop on the way to the destination, request a local ACK.
                outgoingPacket.ACK = outgoingPacket.currentDestination != 255 &&
                                     outgoingPacket.packetType != 9 &&
                                     (outgoingPacket.currentDestination == outgoingPacket.finalDestination);

                // Fake sendig a packet by simply telling the nodes in range to receive the packet object
                networkOps.meshNet[physNeighbor - 1].ReceivePacket(outgoingPacket);  //SIM
            }
        }
Пример #4
0
        // Simulator: these packet types aren't part of a physical implementation. Just here for sim/user interaction
        public static packet CreateOneWayPing(int dest)
        {
            packet response = new packet();

            response.packetType       = 7;
            response.finalDestination = dest;
            return(response);
        }
Пример #5
0
        public static packet CreateGeneralDataPacket(int dest, string payload)
        {
            packet response = new packet();

            response.packetType       = 8;
            response.finalDestination = dest;
            response.payload          = payload;
            return(response);
        }
Пример #6
0
        public static packet CreateGetNeighborsPacket()
        {
            packet response = new packet();

            response.packetType = 3;
            response.payload    = "";

            return(response);
        }
Пример #7
0
        public static packet CreatePokePacket(int fromMe, int toHim)
        {
            packet response = new packet();

            response.packetType          = 6;
            response.origin              = fromMe;
            response.finalDestination    = toHim;
            response.previousDestination = fromMe;
            return(response);
        }
Пример #8
0
        public static packet CreateDiscoverRequestPacket()
        {
            packet response = new packet();

            response.currentDestination = 255;
            response.finalDestination   = 255;
            response.packetType         = 1;

            return(response);
        }
Пример #9
0
        internal static packet CreateACK(packet incomingPacket)
        {
            packet response = new packet();

            response.currentDestination = incomingPacket.previousDestination;
            response.finalDestination   = incomingPacket.previousDestination;
            response.origin             = incomingPacket.finalDestination;
            response.ACK        = false;
            response.packetType = 9;
            return(response);
        }
Пример #10
0
        // Returns a DiscoveryRequest with a DiscoveryResponse
        public static packet CreateResponsePacket(packet discoveryRequest)
        {
            packet response = new packet();

            // Build responsePacket
            response.currentDestination = discoveryRequest.origin;
            response.finalDestination   = discoveryRequest.origin;
            response.packetType         = 2;  // DiscoveryResponse packet type code
            response.payload            = ""; // no payload necessary.  Any reponse to a DiscoverRequest is assumed to be from a neighbor.

            return(response);
        }
Пример #11
0
        // Heartbeat
        public void heartbeat()
        {
            // Copy the current list of neighbors
            List <int> oldNeighbors = new List <int>(neighbors);

            // Clear the master list
            neighbors.Clear();

            // Rebuild the master list
            packet mapNeighbors = packetBuilder.CreateDiscoverRequestPacket();

            mapNeighbors.origin = nodeID;
            SendPacket(mapNeighbors);

            // Compare the lists
            if (!oldNeighbors.SequenceEqual(neighbors))
            {
                // Trigger world-wide remapping
                Console.WriteLine("\n==================== NEIGHBORS CHANGED: WORLDWIDE REMAP ====================");
                wwRemap();
            }
            Console.WriteLine("\nHeartbeat: Success");
        }
Пример #12
0
        // Poke the next node to start mapping

        /* pokeNext is only activated from the wwMap
         *
         */
        private void pokeNext(int mapSessionID)
        {
            List <int> allNodes = pathDictionary.Keys.ToList();

            allNodes.Sort();
            bool foundSomeoneToPoke = false;

            foreach (int i in allNodes)
            {
                if (foundSomeoneToPoke) // Not efficient.  TODO: Improve?
                {
                    continue;
                }

                if (i > nodeID && i != nodeID && i != mapSessionID)
                {
                    // Create a packet to send to the next node to map
                    packet pokePacket = packetBuilder.CreatePokePacket(mapSessionID, i);
                    pokePacket.currentDestination = pathDictionary[i];
                    foundSomeoneToPoke            = true;
                    SendPacket(pokePacket);
                }
            }
        }
Пример #13
0
        // Map network
        public void DoMap()
        {
            // Add a FIFO queue to hold next vertecies to visit next
            Queue <int> vertexQueue = new Queue <int>();

            // To start, set me (node n) as the root of this tree of vertecies
            int rootVertex = nodeID;

            // Add the root of this tree to the queue
            vertexQueue.Enqueue(rootVertex);

            // Process the queue while it has elements
            while (vertexQueue.Count != 0)
            {
                //Console.WriteLine("Beginning pass through while; vertexQueue has " + vertexQueue.Count + " element(s)");

                // Pop an element off the queue
                int v = vertexQueue.Dequeue();
                //Console.WriteLine("Popped vertex ID " + v + " off the queue.");

                // Set current node (for sending packets from it)
                //Console.WriteLine("Currently processing node " + v);

                // If this is me doing the mapping, do it locally.  Otherwise request a remote mapping
                if (v == nodeID)
                {
                    // Send map packet to start getting a list of adjacent vertices
                    packet mapPacket = packetBuilder.CreateDiscoverRequestPacket();
                    mapPacket.origin = nodeID;

                    // Get rid of previous neighbor list and pathDictionary
                    // If this were a hardware node, this would be stored in volatile memory
                    // And cease to exist at poweroff, therefore we can't use this data at poweron
                    neighbors.Clear();
                    pathDictionary.Clear();

                    // Get neighbors list
                    SendPacket(mapPacket);

                    // Sort the neighbors
                    neighbors.Sort();

                    // Add the neighbors to the queue
                    foreach (int i in neighbors)
                    {
                        if (!visited.Contains(i) && !vertexQueue.Contains(i))
                        {
                            vertexQueue.Enqueue(i);
                            if (RFNET.debugging)
                            {
                                Console.WriteLine("----> Enqueued " + i);
                            }
                        }
                    }
                    visited.Add(nodeID);
                    if (RFNET.debugging)
                    {
                        Console.Write("Node " + nodeID + " has visited itself and ");
                        foreach (int x in visited)
                        {
                            Console.Write(x + " ");
                        }
                        Console.WriteLine();
                    }
                }
                else // Remote mapping.  Type 3 request and type 4 response
                {
                    packet mapPacket = packetBuilder.CreateGetNeighborsPacket();
                    mapPacket.currentDestination  = pathDictionary[v]; // Local lookup of next hop
                    mapPacket.finalDestination    = v;                 // Final destination of this packet
                    mapPacket.origin              = nodeID;            // Me
                    mapPacket.previousDestination = nodeID;
                    SendPacket(mapPacket);

                    // Enqueue something in here or it breaks!!  Of course!
                    // Add the neighbors to the queue
                    foreach (int i in pathDictionary.Keys)
                    {
                        // If we have  not visited it and it is not already in the queue, add it
                        if (!visited.Contains(i) && !vertexQueue.Contains(i))
                        {
                            vertexQueue.Enqueue(i);
                            if (RFNET.debugging)
                            {
                                Console.WriteLine("----> Enqueued " + i);
                            }
                        }
                    }
                }
            }


            if (RFNET.debugging)
            {
                Console.WriteLine("----------------- Node " + nodeID + " has finished mapping.   ------------------------");
            }

            visited.Clear();
        }
Пример #14
0
        // Receive packet
        private void ReceivePacket(packet incomingPacket)
        {
            // Since every packet send from node x will be seen by all of x's neighbors.
            // Each receiving node needs to decide if the node is for "me" or not.
            // Broadcasts sent to destination 255 will be accepted by all nodes.
            if (incomingPacket.currentDestination == nodeID || incomingPacket.currentDestination == 255)
            {
                // Eavesdropping
                if (incomingPacket.packetType == 4 && incomingPacket.payload.Length > 0)
                {
                    foreach (string s in incomingPacket.payload.Split(','))
                    {
                        int rn = Convert.ToInt32(s);
                        if (rn != 0 && rn != nodeID /* && !pathDictionary.ContainsKey(rn)*/) // <---- Commented bug causes nodes to pass back and forth to each other (Stack overflow)
                        {
                            //networkOps.meshNet
                            pathDictionary[rn] = incomingPacket.previousDestination;
                        }
                    }
                    if (/*!visited.Contains(incomingPacket.origin)*/ incomingPacket.finalDestination == nodeID)
                    {
                        visited.Add(incomingPacket.origin);
                        if (RFNET.debugging)
                        {
                            Console.WriteLine("Node " + nodeID + " has visited " + incomingPacket.origin);
                        }
                    }
                }

                // Eavesdropping for tracking-enabled nodes  <--- Get rid of this
                /*----->*/ // if(incomingPacket.finalDestination != nodeID && incomingPacket.packetType == 3 && incomingPacket.payload.Length > 0)
                           // {
                // This packet is sent with tracking; Append our address as a return hop
                //     incomingPacket.payload += "," + nodeID;
                // }

                // If we are not the final destination, pass it on
                if (incomingPacket.currentDestination != incomingPacket.finalDestination)
                {
                    // Just before we shoot this packet off as a hop, let's scrape out some useful info!
                    // The origin of this packet is accessible via the previousDestination
                    // Add this to the local path.  Hops can map out far away places like this.
                    //pathDictionary[incomingPacket.origin] = incomingPacket.previousDestination;

                    // We are a hop; Change the currentDestination to the next hop on the way to the final.
                    //  Execute lookup on the local pathDictionary.
                    //MeshSim.networkOps.meshNet[4].pathDictionary
                    // If this is an request packet (types 1 and 3) and not a response, we should add the

                    if (!pathDictionary.Keys.Contains(incomingPacket.origin) && incomingPacket.origin != nodeID && incomingPacket.origin != 0)
                    {
                        pathDictionary[incomingPacket.origin] = incomingPacket.previousDestination;
                    }
                    incomingPacket.currentDestination  = pathDictionary[incomingPacket.finalDestination];
                    incomingPacket.previousDestination = nodeID;

                    SendPacket(incomingPacket);
                }
                else
                {
                    // This packet is for me!
                    if (RFNET.experimentalACK && incomingPacket.ACK)
                    {
                        packet ACKPacket = packetBuilder.CreateACK(incomingPacket);
                        SendPacket(ACKPacket);
                    }
                    // Determine aciton based on packet type
                    switch (incomingPacket.packetType)
                    {
                    // This is an incoming DiscoveryRequest packet
                    case 1:
                        // Add the sending node (which is definitely a neighbor) to the pathDictionary
                        if (incomingPacket.origin != 0 /*&& !pathDictionary.ContainsKey(incomingPacket.origin)*/)
                        {
                            pathDictionary[incomingPacket.origin] = incomingPacket.origin;
                        }
                        if (!neighbors.Contains(incomingPacket.origin))
                        {
                            neighbors.Add(incomingPacket.origin);
                        }
                        // Respond
                        packet discoverResponse = new packet();
                        discoverResponse        = packetBuilder.CreateResponsePacket(incomingPacket);
                        discoverResponse.origin = nodeID;
                        discoverResponse.previousDestination = nodeID;
                        SendPacket(discoverResponse);
                        break;

                    // This is an incoming DiscoveryResponse packet
                    case 2:
                        // Do not generate a response, instead, add response ID to our physNeighbors list.
                        // Add this one as a direct neighbor
                        if (!neighbors.Contains(incomingPacket.origin))
                        {
                            neighbors.Add(incomingPacket.origin);
                        }
                        // Also add these nodes to the directory.
                        //if (!pathDictionary.ContainsKey(incomingPacket.origin)) <-- back and forth bug live here too
                        //{
                        pathDictionary[incomingPacket.origin] = incomingPacket.origin;
                        //}
                        break;

                    // This is an incoming GetNeighbors packet
                    case 3:
                        // Remote get neighbors request
                        // Incoming 3 must refresh neighbor list before sending?
                        // Go ahead and add the previous node (sending hop) as the path to the origin of the packet
                        //if (!pathDictionary.ContainsKey(incomingPacket.origin)) <-- Cuases responses to go back on a different path than they came from.  That's bad.
                        //{
                        pathDictionary[incomingPacket.origin] = incomingPacket.previousDestination;
                        //}

                        // Send back a list of neighbors
                        // Clear neighbors list
                        neighbors.Clear();     // <--- This stupid line was missing for a while...caused a big bug. APPRECIATE THIS LINE FOR A MOMENT!

                        packet discoverPacket = packetBuilder.CreateDiscoverRequestPacket();
                        discoverPacket.origin = nodeID;
                        discoverPacket.previousDestination = nodeID;
                        SendPacket(discoverPacket);

                        // Compile my neighbors into a string, then send that string in the payload of a type 4 response
                        string neighborListString = "";
                        foreach (int n in neighbors)
                        {
                            neighborListString += n + ",";
                        }
                        neighborListString = neighborListString.TrimEnd(',');

                        // Generate response packet
                        packet response = packetBuilder.CreateNeighborsPacket();

                        // This line can cause problems during a worldwide remap when one of the nodes along the path chosen here is offline
                        // Solution?  Perhaps send the packet to another neighbor in hopes that he will know the way back to origin.
                        // Solution?  Perhaps track all of the packet's travels during a worldwide remap so it can go back the same way.

                        response.currentDestination  = pathDictionary[incomingPacket.origin];
                        response.finalDestination    = incomingPacket.origin;
                        response.origin              = nodeID;
                        response.payload             = neighborListString;
                        response.previousDestination = nodeID;
                        SendPacket(response);

                        break;

                    // This is an incoming Neighbors packet
                    case 4:
                        // Case 4 stuff is handled by each node that touches it.  Look above the switch statement.
                        break;

                    // This is an incoming pokePacket.  My turn to map!
                    case 6:
                        DoMap();

                        pokeNext(incomingPacket.origin);
                        break;

                    case 9:      // EXPERIMENTAL SIM ONLY
                        // This is an incoming ACK response. Log it.
                        Console.WriteLine("ACK received from node " + incomingPacket.origin);
                        RFNET.ackCount++;
                        break;
                    }
                }
            }
        }
Пример #15
0
        static void Main()
        {
            Console.WriteLine("\nPlease enter a command.  Enter h for help");
            // Get the command from the user
            List <string> fullCommand = GetCommand();

            switch (fullCommand[0])
            {
            case "g":
                networkOps.GenerateNetwork();
                Main();
                break;

            case "ga":
                networkOps.GenerateNetwork(true);
                Main();
                break;

            case "gm":
                Console.WriteLine("Generating advanced (modified) network.  Last node will not be online.");
                networkOps.GenerateNetwork(false, true);
                Main();
                break;

            case "s":
                // Save the currently generated network
                Console.WriteLine("Saving network topology...");
                networkOps.SaveNetwork();
                Console.WriteLine("Done!");
                Main();
                break;

            case "l":
                Console.WriteLine("Loading saved network");
                networkOps.LoadNetwork();
                Console.WriteLine("Done!");
                networkOps.PrintNetwork();
                Main();
                break;

            case "d":
                Console.WriteLine("Deleting existing topology");
                MeshSim.networkOps.meshNet.Clear();
                offlineNodeList.Clear();
                Console.WriteLine("Done! Enter g to generate a new network");
                Main();
                break;

            case "c":
                Console.WriteLine("Checking validity of maps");
                networkOps.CheckValidity();
                Main();
                break;

            case "p":
                Console.WriteLine("Packets transmitted: " + RFNET.packetCount);
                Main();
                break;

            case "pa":
                Console.WriteLine("ACK count: " + RFNET.ackCount);
                Main();
                break;

            case "h":
                Console.WriteLine(@"
You've entered help.
Enter 'g' to generate a new network. (no mappings, all online. depreciated)
Enter 'ga' generate advanced: to generate a network where all nodes are powered off to start with.
Enter 'gm' to generate a modified network: all nodes on (not mapped) except last one.
Enter 's' to save the generated network (without mappings)
Enter 'l' to load the previously-saved network
Enter 'c' to check validity of network maps
Enter 'd' to delete the current network (doesn't delete file)
Enter 'off <nodeID> <nodeID>' to turn nodes off
Enter 'on <nodeID> <nodeID> ...<nodeID>' to turn nodes on
Enter 'ls' to show all ONLINE nodes.
Enter 'll' to show ALL nodes.
Enter 'send <fromID> <toID>' to manually send a packet.
Enter 'sho <nodeID>' to see the routing table of a node.
Enter 'alloff' to turn all nodes off.
Enter 'randomon' to turn all nodes on in a random order.
Enter 'sequentialon' to turn all nodes on in sequential order.
Enter 'alloff' to turn all nodes off immediately.
Enter 'hb <nodeID> <nodeID> ...<nodeID>' to trigger heartbeat on a node
Enter 'hball' to trigger a heartbeat on each node in random order
");
                Main();
                break;

            case "off":
                if (fullCommand.Count < 2)
                {
                    Console.WriteLine("Usage: 'off <nodeID> <nodeID> ... <nodeID>'");
                }

                if (fullCommand.Count > 1)
                {
                    // Iterate through the nodes that were listed
                    for (int i = 1; i < fullCommand.Count; i++)
                    {
                        offlineNodeList.Add(Convert.ToInt32(fullCommand[i]));
                        Console.WriteLine("Powered off node " + fullCommand[i]);
                    }
                }
                Main();
                break;

            case "on":
                if (fullCommand.Count < 2)
                {
                    Console.WriteLine("Usage: 'on <nodeID> <nodeID> ... <nodeID>'");
                }

                if (fullCommand.Count > 1)
                {
                    // Iterate through the nodes that were listed
                    for (int i = 1; i < fullCommand.Count; i++)
                    {
                        networkOps.meshNet[Convert.ToInt32(fullCommand[i]) - 1].start();
                        Console.WriteLine("Powered up node " + fullCommand[i]);
                    }
                }
                Main();
                break;

            case "ls":
                Console.WriteLine("Printing network");
                // Pass in false for optional bool showBothOnAndOff parameter
                networkOps.PrintNetwork(false);
                Main();
                break;

            case "ll":
                Console.WriteLine("Printing network");
                networkOps.PrintNetwork();
                Main();
                break;

            case "send":
                if (fullCommand.Count < 2)
                {
                    Console.WriteLine("Usage: 'ping <fromID> <toID>'");
                }

                int inputFrom = Convert.ToInt32(fullCommand[1]);
                int inputTo   = Convert.ToInt32(fullCommand[2]);

                // Create and send the packet
                packet oneWayPingPacket = new packet();
                oneWayPingPacket = packetBuilder.CreateOneWayPing(inputTo);
                oneWayPingPacket.currentDestination  = networkOps.meshNet[inputFrom - 1].pathDictionary[inputTo];
                oneWayPingPacket.previousDestination = inputFrom;
                networkOps.meshNet[inputFrom - 1].SendPacket(oneWayPingPacket);

                Main();
                break;

            //case "send": // <--- Depreciated
            //    Console.WriteLine("Sending general packet");
            //    Console.WriteLine("From:");
            //    int genFrom = stringToInt(Console.ReadLine());
            //    Console.WriteLine("To:");
            //    int genTo = stringToInt(Console.ReadLine());
            //    Console.WriteLine("Message");
            //    string payload = Console.ReadLine();
            //    packet genPacket = packetBuilder.CreateGeneralDataPacket(genTo,payload);
            //    genPacket.origin = genFrom;
            //    genPacket.currentDestination = networkOps.meshNet[genFrom - 1].pathDictionary[genTo];
            //    genPacket.previousDestination = genFrom;
            //    networkOps.meshNet[genFrom - 1].SendPacket(genPacket);
            //    Main();
            //    break;
            case "sho":
                int shoNode = Convert.ToInt32(fullCommand[1]);
                networkOps.meshNet[shoNode - 1].showPaths();
                Main();
                break;

            case "alloff":
                Console.WriteLine("\nTurning all nodes off");
                networkOps.AllOff();
                Main();
                break;

            case "randomon":
                Console.WriteLine("Turning on all nodes in random order");
                networkOps.randomOn();
                Console.WriteLine("Transmitted " + packetCount + " packets.");
                Main();
                break;

            case "sequentialon":
                Console.WriteLine("Turning on all nodes in sequential order");
                networkOps.sequentialOn();
                Console.WriteLine("Transmitted " + packetCount + " packets.");
                Main();
                break;

            case "map":
                int youMap = Convert.ToInt32(fullCommand[1]);    // stringToInt(Console.ReadLine());
                networkOps.meshNet[youMap - 1].DoMap();
                Main();
                break;

            case "hb":
                if (fullCommand.Count < 2)
                {
                    Console.WriteLine("Usage: 'hb <nodeID> <nodeID> ... <nodeID>'");
                }

                if (fullCommand.Count > 1)
                {
                    // Iterate through the nodes that were listed
                    for (int i = 1; i < fullCommand.Count; i++)
                    {
                        networkOps.meshNet[Convert.ToInt32(fullCommand[i]) - 1].heartbeat();
                    }
                }
                Main();
                break;

            case "hball":
                Console.WriteLine("Starting random but complete heartbeat triggering.");
                networkOps.heartbeatAll();
                Console.WriteLine("\nEach node in the network did a heartbeat in a random order.");
                Main();
                break;

            case "killrandom":
                networkOps.killRandom();
                Main();
                break;

            default:
                // Complain
                Console.WriteLine("WAT!?!?!");
                Main();
                break;
            }
        }