Example #1
0
        public static void Send_ResetWave()
        {
            // If in a reset wave already, return.
            if (RoutingGlobal._color == Color.Red)
            {
                return;
            }

            // Refresh children table
            _children.CleanseChildrenTable();

            if (!_children.IsEmpty())
            {
                RoutingGlobal._color = Color.Red;
                var msgBytes = new byte[3];
                var size     = ComposeMessages.CreateResetMessage(msgBytes, (ushort)_resetMsgNum);
                MulticastToChildren(msgBytes, size);
                _distResetTimer.Change(120000, Timeout.Infinite); // 2 min timer. TODO: Make timeout interval contingent on distance from the reset wave origin
            }
            else
            {
                // Create status query to existing candidates
                var msgBytes = new byte[3];
                var size     = ComposeMessages.CreateStatusQueryMessage(msgBytes, (ushort)_statusMsgNum);

                // Multicast query to candidates
                if (MulticastToCandidates(msgBytes, size)) // If there are candidates
                {
                    // Wait for response
                    _statusResponseTimer.Change(10000, Timeout.Infinite); // 10 second timer

                    // Reset candidate table
                    ushort[] neighbors = MACBase.NeighborListArray();
                    CandidateTable.Initialize((byte)neighbors.Length);
                }
                else //Empty candidate table; set parent immediately
                {
                    // Set best node in candidate table as parent
                    RoutingGlobal.SetParent(false);

                    // Reset params
                    RoutingGlobal._color = Color.Green;
                    // Send "Add Parent" message to new parent
                    DistributedReset.Send_AddParent();
                    _statusMsgNum++;
                    _resetMsgNum++;
                }
            }
        }
Example #2
0
        private static void Send_CompletionWave(int round)
        {
            var         msgBytes = new byte[3];
            var         size     = ComposeMessages.CreateCompletionMessage(msgBytes, (ushort)round);
            NetOpStatus status   = _distResetPipe.Send(RoutingGlobal.Parent, msgBytes, 0, (ushort)size);

#if DBG_VERBOSE
            if (status != NetOpStatus.S_Success)
            {
                Debug.Print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Send status: " + status);
            }

            Debug.Print("Sent Completion Wave " + round + " to " + RoutingGlobal.Parent);
#elif DBG_SIMPLE
            Debug.Print("Sent Completion Wave " + round + " to " + RoutingGlobal.Parent + ", status: " + status);
#endif
        }
Example #3
0
        public static void Send_DropParent()
        {
            _dropMsgNum++;
            var         msgBytes = new byte[3];
            var         size     = ComposeMessages.CreateDropParentMessage(msgBytes, (ushort)_dropMsgNum);
            NetOpStatus status   = _distResetPipe.Send(RoutingGlobal.ExParent, msgBytes, 0, (ushort)size);

#if DBG_VERBOSE
            if (status != NetOpStatus.S_Success)
            {
                Debug.Print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Send status: " + status);
            }

            Debug.Print("Sent \"Dropped Parent\" message to " + RoutingGlobal.Parent);
#elif DBG_SIMPLE
            Debug.Print("Sent \"Dropped Parent\" message to " + RoutingGlobal.Parent + ", status: " + status);
#endif
        }
Example #4
0
        private static void Reset_State(object state)
        {
#if DBG_VERBOSE
            Debug.Print("*** RESET WAVE TIMEOUT FIRED: Initiating completion wave# " + _resetMsgNum + " ***");
#elif DBG_SIMPLE
            Debug.Print("Initiating completion wave " + _resetMsgNum + "");
#endif
            Send_CompletionWave(_resetMsgNum);

            // Purge children table
            _children       = new ChildrenList();
            _completionMsgs = null;

            // Create status query to existing candidates
            var msgBytes = new byte[3];
            var size     = ComposeMessages.CreateStatusQueryMessage(msgBytes, (ushort)_statusMsgNum);

            // Multicast query to candidates
            if (MulticastToCandidates(msgBytes, size)) // If there are candidates
            {
                // Wait for response
                _statusResponseTimer.Change(10000, Timeout.Infinite); // 10 second timer

                // Reset candidate table
                ushort[] neighbors = MACBase.NeighborListArray();
                CandidateTable.Initialize((byte)neighbors.Length);
            }
            else //Empty candidate table; set parent immediately
            {
                // Set best node in candidate table as parent
                RoutingGlobal.SetParent(false);

                // Reset params
                RoutingGlobal._color = Color.Green;
                // Send "Add Parent" message to new parent
                DistributedReset.Send_AddParent();
                _statusMsgNum++;
            }

            _resetMsgNum++; // No more completion messages to be accepted beyond this point
        }
Example #5
0
        private static void DistResetStreamReceive(IMAC macBase, DateTime time, Packet packet)
        {
#if DBG_VERBOSE
            DebuggingSupport.PrintMessageReceived(macBase, "Distributed Reset");
#endif

            if (packet == null)
            {
                return;
            }
#if !DBG_LOGIC
            Debug.Print("\tRSSI: " + packet.RSSI + ", from " + packet.Src);
#endif

            var rcvPayloadBytes = packet.Payload;

            //var payload = new string(Encoding.UTF8.GetChars(rcvPayloadBytes));
#if DBG_VERBOSE
            SystemGlobal.PrintNumericVals("\tDistributed reset Rcv: ", rcvPayloadBytes);
#endif
            try
            {
                ushort[] neighbors = MACBase.NeighborListArray();


                var neighborStatus = _distResetPipe.NeighborStatus(packet.Src);
                if (neighborStatus == null)
                {
#if DBG_VERBOSE
                    Debug.Print("\t\t!!!!!!!!!!!!!!!!! Node " + packet.Src + " is not a Neighbor (MACBase.NeighborStatus returned null)");
#elif DBG_SIMPLE
                    Debug.Print("Sender not a neighbor.");
#endif
                    // If node in children table, drop it
                    if (Array.IndexOf(_children._childrenList, packet.Src) < -1)
                    {
                        _children.DropChild(packet.Src);
                    }

                    return;
                }
                //Debug.Print("\t\tFwd avg RSSI: " + neighborStatus.ReceiveLink.AverageRSSI + ", Rev avg RSSI: " + neighborStatus.SendLink.AverageRSSI);

                switch ((MessageIds)rcvPayloadBytes[0])
                {
                case MessageIds.AddParent:
#if !DBG_LOGIC
                    Debug.Print("\t>>> AddParent");
#endif
                    if (_children.AddChild(packet.Src))
                    {
#if DBG_VERBOSE
                        Debug.Print("+++ Added new child: " + packet.Src + " +++");
#elif DBG_SIMPLE
                        Debug.Print("Added new child: " + packet.Src);
#endif
                    }
                    else
                    {
#if DBG_VERBOSE
                        Debug.Print("@@@ Child already exists: " + packet.Src + " @@@");
#endif
                    }

                    return;

                case MessageIds.DropParent:
#if !DBG_LOGIC
                    Debug.Print("\t>>> DropParent");
#endif

                    if (_children.DropChild(packet.Src))
                    {
#if DBG_VERBOSE
                        Debug.Print("--- Dropped child: " + packet.Src + " ---");
#elif DBG_SIMPLE
                        Debug.Print("Dropped child: " + packet.Src);
#endif
                    }
                    else
                    {
#if DBG_VERBOSE
                        Debug.Print("@@@ Child does not exist: " + packet.Src + " @@@");
#endif
                    }

                    return;

                case MessageIds.Reset:
#if !DBG_LOGIC
                    Debug.Print("\t>>> ResetWave");
#endif
                    // Decode round number
                    ushort round_num;
                    ParseMessages.ParseResetMessage(rcvPayloadBytes, out round_num);

                    // Is this a legit reset wave?
                    if (RoutingGlobal._color == Color.Red || packet.Src != RoutingGlobal.Parent || round_num != _resetMsgNum)
                    {
#if DBG_VERBOSE
                        Debug.Print("!!! ILLEGAL RESET WAVE# " + round_num + ": Received from: " + packet.Src + " !!!");
#elif DBG_SIMPLE
                        Debug.Print("Illegal reset wave " + round_num + " from " + packet.Src);
#endif
                        return;
                    }

                    // Refresh children table
                    _children.CleanseChildrenTable();

                    if (_children.IsEmpty())     // Start completion wave if leaf node
                    {
#if DBG_VERBOSE
                        Debug.Print("*** LEAF NODE REACHED: Initiating completion wave# " + round_num + " ***");
#elif DBG_SIMPLE
                        Debug.Print("At leaf; initiating completion wave " + round_num);
#endif
                        Send_CompletionWave(round_num);

                        // Create status query to existing candidates
                        var msgBytes = new byte[3];
                        var size     = ComposeMessages.CreateStatusQueryMessage(msgBytes, (ushort)_statusMsgNum);

                        // Multicast query to candidates
                        if (MulticastToCandidates(msgBytes, size))     // If there are candidates
                        {
                            // Wait for response
                            _statusResponseTimer.Change(10000, Timeout.Infinite);     // 10 second timer

                            // Reset candidate table
                            CandidateTable.Initialize((byte)neighbors.Length);
                        }
                        else     //Empty candidate table; set parent immediately
                        {
                            // Set best node in candidate table as parent
                            RoutingGlobal.SetParent(false);

                            // Reset params
                            RoutingGlobal._color = Color.Green;
                            // Send "Add Parent" message to new parent
                            DistributedReset.Send_AddParent();
                            _statusMsgNum++;
                        }

                        _resetMsgNum++;
                    }
                    else
                    {
                        // Forward reset wave to own children
                        Send_ResetWave(rcvPayloadBytes);
                    }
                    return;

                case MessageIds.Completion:
#if !DBG_LOGIC
                    Debug.Print("\t>>> CompletionWave");
#endif
                    // Decode round number
                    ushort round;
                    ParseMessages.ParseCompletionMessage(rcvPayloadBytes, out round);

                    // Is this a legit completion wave?
                    int pos = Array.IndexOf(_children._childrenList, packet.Src);
                    if (RoutingGlobal._color != Color.Red || pos == -1 || round != _resetMsgNum)
                    {
#if DBG_VERBOSE
                        Debug.Print("!!! ILLEGAL COMPLETION WAVE# " + round + ": Received from: " + packet.Src + " !!!");
#elif DBG_SIMPLE
                        Debug.Print("Illegal completion wave " + round + " from " + packet.Src);
#endif
                        return;
                    }

                    _completionMsgs[pos] = true;

                    // Forward completion wave if received from all children
                    for (int i = 0; i < _completionMsgs.Length; i++)
                    {
                        if (!_completionMsgs[i])     // If not received from any child, return
                        {
                            return;
                        }
                    }

                    // Else, forward completion wave to parent
#if DBG_VERBOSE
                    Debug.Print("*** RECEIVED COMPLETION MESSAGES FROM ALL CHILDREN: initiating completion wave# " + round + " ***");
#elif DBG_SIMPLE
                    Debug.Print("All children responded; initiating completion wave " + round);
#endif
                    Send_CompletionWave(round);

                    // Purge children table
                    _children       = new ChildrenList();
                    _completionMsgs = null;
                    _distResetTimer.Change(Timeout.Infinite, Timeout.Infinite);

                    // Create status query to existing candidates
                    var msgBytes1 = new byte[3];
                    var size1     = ComposeMessages.CreateStatusQueryMessage(msgBytes1, (ushort)_statusMsgNum);

                    // Multicast query to candidates
                    if (MulticastToCandidates(msgBytes1, size1))     // If there are candidates
                    {
                        // Wait for response
                        _statusResponseTimer.Change(10000, Timeout.Infinite);     // 10 second timer

                        // Reset candidate table
                        CandidateTable.Initialize((byte)neighbors.Length);
                    }
                    else     //Empty candidate table; set parent immediately
                    {
                        // Set best node in candidate table as parent
                        RoutingGlobal.SetParent(false);

                        // Reset params
                        RoutingGlobal._color = Color.Green;
                        // Send "Add Parent" message to new parent
                        DistributedReset.Send_AddParent();
                        _statusMsgNum++;
                    }

                    _resetMsgNum++;
                    return;

                case MessageIds.StatusQuery:
#if !DBG_LOGIC
                    Debug.Print("\t>>> StatusQuery");
#endif
                    //If in a reset wave or no valid path, don't bother responding
                    if (RoutingGlobal._color == Color.Red || RoutingGlobal.BestEtx >= RoutingGlobal.Infinity)
                    {
#if DBG_VERBOSE
                        Debug.Print("!!! Not responding. Color: " + RoutingGlobal._color + ", BestEtx: " + RoutingGlobal.BestEtx + " !!!");
#elif DBG_SIMPLE
                        Debug.Print("Not responding. Color: " + RoutingGlobal._color + ", BestEtx: " + RoutingGlobal.BestEtx);
#endif
                        return;
                    }

                    // Decode round number
                    ushort status_msgnum;
                    ParseMessages.ParseStatusQueryMessage(rcvPayloadBytes, out status_msgnum);

                    // Send status response
                    var         msgBytes2 = new byte[5];
                    var         size2     = ComposeMessages.CreateStatusResponseMessage(msgBytes2, status_msgnum);
                    NetOpStatus status    = _distResetPipe.Send(RoutingGlobal.Parent, msgBytes2, 0, (ushort)size2);

                    return;

                case MessageIds.StatusResponse:
#if !DBG_LOGIC
                    Debug.Print("\t>>> StatusResponse");
#endif
                    ushort status_respnum;
                    Color  col;
                    byte   etx;
                    byte   pathEWRNP_B2N;

                    // Decode message
                    ParseMessages.ParseStatusResponseMessage(rcvPayloadBytes, out col, out etx, out status_respnum, out pathEWRNP_B2N);

                    // Is this a valid response?
                    if (status_respnum != _statusMsgNum)
                    {
#if DBG_VERBOSE
                        Debug.Print("!!! ILLEGAL STATUS RESPONSE# " + status_respnum + ": Received from: " + packet.Src + " !!!");
#elif DBG_SIMPLE
                        Debug.Print("Illegal status response " + status_respnum + " from " + packet.Src);
#endif
                        return;
                    }

                    byte tempEtx = (byte)(etx + 1);

                    // Add candidate if its offered etx exceeds _minEtx
                    if (tempEtx >= RoutingGlobal._minEtx)
                    {
                        CandidateTable.AddCandidate(packet.Src, 0, tempEtx, pathEWRNP_B2N, RoutingGlobal.MaxEtx);     // TODO: Add RSSI later
#if DBG_VERBOSE
                        Debug.Print("+++ Added new candidate: " + packet.Src + "; path length: " + tempEtx + " +++");
#elif DBG_SIMPLE
                        Debug.Print("New candidate " + packet.Src + ":[" + tempEtx + "]");
#endif
                    }
                    else
                    {
#if DBG_VERBOSE
                        Debug.Print("--- Not a candidate: " + packet.Src + "; path length: " + tempEtx + " ---");
#elif DBG_SIMPLE
                        Debug.Print("Not a candidate " + packet.Src + ":[" + tempEtx + "]");
#endif
                    }

                    return;

                default:
#if !DBG_LOGIC
                    Debug.Print("\tUnknown message received <" + rcvPayloadBytes[0] + ">");
#endif
                    break;
                }
            }
            catch (Exception e) { Debug.Print(e.StackTrace); }
        }