コード例 #1
0
ファイル: Program.cs プロジェクト: mcoqzeug/Time-Sync-eMote
        static void MacBase_OnNeighborChange(IMAC macInstance, DateTime time)
        {
            var neighborList = MACBase.NeighborListArray();

            macInstance.NeighborList(neighborList);
            PrintNeighborList("\t\tNeighbor list CHANGE for Node [" + _macBase.MACRadioObj.RadioAddress + "]: ", neighborList);
        }
コード例 #2
0
        /// <summary>
        /// Custom constructor.
        /// </summary>
        /// <param name="digest">Hash functon.</param>
        /// <param name="mac">MAC function.</param>
        /// <param name="iteration">Loop count.</param>
        public PBKDF2(IHash digest, IMAC mac, int iteration = 1000)
        {
            if (digest == null)
            {
                this._HashFunction = new Blake2b(512);
            }
            else
            {
                this._HashFunction = digest;
            }

            if (mac == null)
            {
                this._MACFunction = new HMAC(this._HashFunction);
            }
            else
            {
                this._MACFunction = mac;
            }

            if (iteration <= 0)
            {
                this._Iteration = 1000;
            }
            else
            {
                this._Iteration = iteration;
            }
        }
コード例 #3
0
        public static string MacInfo(IMAC imacInstance)
        {
            var info = "MAC Type: " + imacInstance.GetType()
                       + ", Channel: " + imacInstance.MACRadioObj.Channel
                       + ", Power: " + imacInstance.MACRadioObj.TxPower
                       + ", Radio Address: " + imacInstance.MACRadioObj.RadioAddress
                       + ", Radio Type: " + imacInstance.MACRadioObj.RadioName
                       + ", Neighbor Liveness Delay: " + imacInstance.NeighborLivenessDelay;

            return(info);
        }
コード例 #4
0
ファイル: Program.cs プロジェクト: mcoqzeug/Time-Sync-eMote
        private static void RadioReceive(IMAC macBase, DateTime receiveDateTime, Packet packet)
        {
            /*
             * t1: when the local node sent a request
             * t2: when a partner node received the request
             * t3: when the partner node sent a response
             * t4: when then local node received the response
             *
             * requset: "Request t1"
             * respond: "Respond t1 t2 t3"
             */
            long recvTime = time2Long(receiveDateTime) + _offset;  // could be t2 or t4

            var msgByte = packet.Payload;
            var msgChar = Encoding.UTF8.GetChars(msgByte);
            var msgStr  = new string(msgChar);

            ushort recvFromAddress = packet.Src;

            Debug.Print("\tReceived: \"" + msgStr + "\"" + " from " + packet.Src);

            if (msgStr.Length < HeadLength)
            {
                return;
            }

            if (msgStr.Substring(0, HeadLength) == HeaderRespond)
            {
                string   payload = msgStr.Substring(HeaderRespond.Length);
                String[] timeStrings = payload.Split(' ');
                long     t1, t2, t3, t4 = recvTime;
                try
                {
                    t1 = long.Parse(timeStrings[0]);
                    t2 = long.Parse(timeStrings[1]);
                    t3 = long.Parse(timeStrings[2]);
                }
                catch
                {
                    return;
                }

                _offsetSum += (t2 - t1 + t3 - t4) / 2;
                _numResponded++;
            }
            else if (msgStr.Substring(0, HeadLength) == HeaderRequest)
            {
                string t1Str    = msgStr.Substring(HeaderRespond.Length);
                long   t3       = getLocalTime();
                string response = t1Str + " " + recvTime.ToString() + " " + t3.ToString();
                RadioSend(response, recvFromAddress);
            }
        }
コード例 #5
0
        public static void PrintMessageReceived(IMAC imac, string toPrint)
        {
            const string stars = "****************** ";
            var          pipe  = imac as MACPipe;

            if (pipe != null)
            {
                Debug.Print("\n" + stars + toPrint + " Receive on pipe " + pipe.PayloadType);
            }
            else
            {
                Debug.Print("\n" + stars + toPrint + " Receive");
            }
        }
コード例 #6
0
        public static void PrintMessageSent(IMAC imac, string toPrint)
        {
            const string hashes = "################## ";
            var          pipe   = imac as MACPipe;

            if (pipe != null)
            {
                Debug.Print("\n" + hashes + toPrint + " Sent on pipe " + pipe.PayloadType);
            }
            else
            {
                Debug.Print("\n" + hashes + toPrint + " Sent");
            }
        }
コード例 #7
0
        /// <summary>
        /// Send a message to all neighbors
        /// </summary>
        /// <param name="mac"></param>
        /// <param name="message"></param>
        /// <param name="messageLength"></param>
        public static void Broadcast(IMAC mac, byte[] message, int messageLength)
        {
            var neighbors = MACBase.NeighborListArray();

            mac.NeighborList(neighbors);
#if !DBG_LOGIC
            PrintNeighborList(mac);
#endif

            var pipe = mac as MACPipe;

#if DBG_VERBOSE
            if (pipe != null)
            {
                PrintNumericVals("Broadcast (on MACPipe " + pipe.PayloadType + "): ", message, messageLength);
            }
            else
            {
                PrintNumericVals("Broadcast: ", message, messageLength);
            }
#endif
            foreach (var theNeighbor in neighbors)
            {
                if (theNeighbor == 0)
                {
                    continue;
                }
                var status = pipe.EnqueueToSend(theNeighbor, message, 0, (ushort)messageLength);

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

                Debug.Print("\tSent to " + theNeighbor);
#elif DBG_SIMPLE
                Debug.Print("\tSent to " + theNeighbor + ", status: " + status);
#endif
            }
        }
コード例 #8
0
 private static bool TryGetNanoAlgorithm(IMAC referent, int macSize, out IMAC algorithm)
 {
     if (macSize == -1)
     {
         algorithm = referent;
         return(true);
     }
     else if (macSize == referent.BlockSize / 2)
     {
         algorithm = referent;
         return(true);
     }
     else if (macSize >= 8 && macSize <= referent.BlockSize && macSize % 8 == 0)
     {
         algorithm = new MAC(((MAC)referent).BlockAlgorithm, macSize);
         return(true);
     }
     else
     {
         algorithm = null;
         return(false);
     }
 }
コード例 #9
0
        /// <summary>
        /// Send a message to all neighbors - moved here from SystemGlobal
        /// </summary>
        /// <param name="mac"></param>
        /// <param name="message"></param>
        /// <param name="messageLength"></param>
        public static void BroadcastBeacon(IMAC mac, byte[] message, int messageLength)
        {
            var neighbors = MACBase.NeighborListArray();

            mac.NeighborList(neighbors);
#if !DBG_LOGIC
            SystemGlobal.PrintNeighborList(mac);
#endif

            var pipe = mac as MACPipe;

#if DBG_VERBOSE
            if (pipe != null)
            {
                PrintNumericVals("Broadcast (on MACPipe " + pipe.PayloadType + "): ", message, messageLength);
            }
            else
            {
                PrintNumericVals("Broadcast: ", message, messageLength);
            }
#endif
            foreach (var theNeighbor in neighbors)
            {
                if (theNeighbor == 0)
                {
                    continue;
                }
                var status = pipe.EnqueueToSend(theNeighbor, message, 0, (ushort)messageLength);

                if (pipe.IsMsgIDValid(status))
                {
                    // Update link metrics
                    if (theNeighbor == Parent)
                    {
                        UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for parent " + theNeighbor + "; new value = " + GetNumTriesInCurrentWindow_Parent());
#endif
                    }
                    else
                    {
                        byte cindex = CandidateTable.findIndex(theNeighbor);
                        if (cindex < byte.MaxValue)
                        {
                            CandidateTable._candidateList[cindex].UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                            Debug.Print("Updated numTriesInCurrentWindow for candidate " + theNeighbor + "; new value = " + CandidateTable._candidateList[cindex].GetNumTriesInCurrentWindow());
#endif
                        }
                    }


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

                    Debug.Print("\tSent to " + theNeighbor);
#elif DBG_SIMPLE
                    Debug.Print("\tSent to " + theNeighbor + ", status: " + status);
#endif
                }
            }
        }
コード例 #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="macBase"></param>
        /// <param name="dateTime"></param>
        private static void NetManagerStreamReceive(IMAC macBase, DateTime dateTime, Packet packet)
        {
#if DBG_VERBOSE
            DebuggingSupport.PrintMessageReceived(macBase, "Net Manager");
#elif DBG_SIMPLE
            Debug.Print("");
#endif

            //Debug.Print("\ton " + packet.PayloadType);
            var rcvPayloadBytes = packet.Payload;

            //var payload = new string(Encoding.UTF8.GetChars(rcvPayloadBytes));

#if DBG_VERBOSE
            SystemGlobal.PrintNumericVals("Net Manager Rcv: ", rcvPayloadBytes);
#elif DBG_SIMPLE
            Debug.Print("");
#endif

            switch ((NetManagerGlobal.MessageIds)rcvPayloadBytes[0])
            {
            case NetManagerGlobal.MessageIds.Heartbeat:
                ushort originator;
                ushort numBeat;
                SystemGlobal.NodeTypes nodeType;
                ushort parent;
                byte   TTL;

                NetManagerGlobal.MoteMessages.Parse.HeartBeat(rcvPayloadBytes, out originator, out numBeat, out nodeType, out parent, out TTL);
                // NetManagerGlobal.MoteMessages.Parse.HeartBeat(rcvPayloadBytes, out originator, out numBeat, out nodeType, out parent, out bestetx, out neighbors, out nbrStatus, out numSamplesRec, out numSyncSent, out avgRSSI, out ewrnp);
                // NetManagerGlobal.MoteMessages.Parse.HeartBeat(rcvPayloadBytes, out originator, out numBeat, out nodeType, out parent, out bestetx, out num_nbrs, out neighbors, out nbrStatus, out numSamplesRec, out numSyncSent, out avgRSSI, out ewrnp, out isAvailableForUpperLayers, out TTL);
                Debug.Print("\t>>> Heartbeat #" + numBeat + " from neighbor " + packet.Src + " by " + originator + " with TTL " + TTL);

#if DBG_DIAGNOSTIC
                Debug.Print("Parent: " + parent);
                Debug.Print("");
#endif

#if RELAY_NODE || CLIENT_NODE
                // If we're the originator of the message, or if (TTL-1) is 0, do not pass it on.
                if (originator == _netManagerPipe.MACRadioObj.RadioAddress || --TTL == 0)
                {
                    return;
                }
                RoutingGlobal.AddChild(originator, packet.Src);
                #region Uncomment when not using scheduler
                // TODO: Uncomment lines when not using scheduler
                // If in a reset, do not forward TODO: Change this to "spray"
                if (RoutingGlobal._color == Color.Red)
                {
#if DBG_VERBOSE
                    Debug.Print("\tIn a Reset wave... not forwarded");
#endif
                    return;
                }

                // If parent is available, pass it on
                if (RoutingGlobal.IsParent)
                {
                    byte[] routedMsg = new byte[rcvPayloadBytes.Length];
                    var    size      = NetManagerGlobal.MoteMessages.Compose.Heartbeat(routedMsg, originator, numBeat, nodeType, parent, TTL);
                    var    status    = RoutingGlobal.SendToParent(_netManagerPipe, routedMsg, size);
                    if (status != 999)
                    {
                        RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for Parent " + RoutingGlobal.Parent + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                    }
                    else     //Retry once
                    {
#if !DBG_LOGIC
                        Debug.Print("Retrying packet");
#endif
                        RoutingGlobal.CleanseCandidateTable(_netManagerPipe);
                        Candidate tmpBest = CandidateTable.GetBestCandidate(false);
                        NetManagerGlobal.TempParent = tmpBest.GetMacID();
                        status = NetManagerGlobal.SendToTempParent(_netManagerPipe, routedMsg, size);
                        if (status != 999)
                        {
                            tmpBest.UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                            Debug.Print("Updated numTriesInCurrentWindow for TempParent " + NetManagerGlobal.TempParent + "; new value = " + tmpBest.GetNumTriesInCurrentWindow());
#endif
                        }
                    }
                }
                #endregion
                #region unused
                // If parent is not available, broadcast it
                //{
                //    //var size = NetManagerGlobal.ComposeMessages.CreateHeartbeat(NetManagerGlobal.MsgBytes, _netManagerPipe.MACRadioObj.RadioAddress);
                //    SystemGlobal.BroadcastBeacon(_netManagerPipe, rcvPayloadBytes, packet.Size);
                //}

                //if (payload.Substring(0, 9).Equals("Heartbeat")) //Relay heartbeats, generated hourly
                //{
                //	Debug.Print("\tReceived Heartbeat: " + payload.Substring(0, 9) + "; source: " + payload.Substring(9) + "; from neighbor: " + packet.Src);
                //	if (RoutingGlobal.Parent == SystemGlobal.NoParent)
                //	{
                //		return;
                //	}
                //	var toSendByte = Encoding.UTF8.GetBytes(payload);
                //	var status = _netManagerPipe.Send(RoutingGlobal.Parent, toSendByte, 0, (ushort)toSendByte.Length);
                //	if (status != NetOpStatus.S_Success)
                //	{
                //		Debug.Print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Send status: " + status);
                //	}

                //	SystemGlobal.PrintNumericVals("Net Manager Snd: ", toSendByte);

                //	Debug.Print("Forwarded Heartbeat: " + payload.Substring(0, 9) + "; source: " + payload.Substring(9) + "; from Node: " + packet.Src + " to Node: " + RoutingGlobal.Parent);
                //}
                #endregion
#endif
#if BASE_STATION
                string msg = NetManagerGlobal.PCMessages.Compose.Heartbeat(originator, numBeat, nodeType, parent);
                try
                {
                    _serialComm.Write(msg);
#if DBG_VERBOSE
                    Debug.Print("\n************ Heartbeat forwarded to PC " + msg.Substring(1, msg.Length - 2));
#endif
                }
                catch (Exception ex)
                {
                    Debug.Print("SerialComm exception for Heartbeat message [" + msg + "]\n" + ex);
                }
#endif
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
コード例 #11
0
        private static void OnSendStatus(IMAC macInstance, DateTime time, SendPacketStatus ACKStatus, uint transmitDestination, ushort index)
        {
            var pipe = macInstance as MACPipe;

            switch (ACKStatus)
            {
            case SendPacketStatus.SendACKed:
#if DBG_DIAGNOSTIC
                Debug.Print("\t\tNet Manager: Retry queue length = " + _retriedPackets.Count);
#endif
#if !DBG_LOGIC
                Debug.Print("Heartbeat to " + transmitDestination.ToString() + " ACKed");
#endif
                // Update link metrics
                if ((ushort)transmitDestination == RoutingGlobal.Parent)
                {
                    RoutingGlobal.UpdateNumReceivedInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                    Debug.Print("Updated numReceivedInCurrentWindow for parent " + transmitDestination + "; new value = " + RoutingGlobal.GetNumReceivedInCurrentWindow_Parent());
#endif
                }
                else
                {
                    byte cindex = CandidateTable.findIndex((ushort)transmitDestination);
                    if (cindex < byte.MaxValue)
                    {
                        CandidateTable._candidateList[cindex].UpdateNumReceivedInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numReceivedInCurrentWindow for candidate " + transmitDestination + "; new value = " + CandidateTable._candidateList[cindex].GetNumReceivedInCurrentWindow());
#endif
                    }
                }

                if (_retriedPackets.Contains(index))     // If this was a re-try, remove packet from queue
                {
                    _retriedPackets.Remove(index);
                }
                break;

            case SendPacketStatus.SendNACKed:
                    #if !DBG_LOGIC
                Debug.Print("Heartbeat to " + transmitDestination.ToString() + " NACKed");
#endif
                // Update link metrics
                if ((ushort)transmitDestination == RoutingGlobal.Parent)
                {
                    RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                    Debug.Print("Updated numTriesInCurrentWindow for parent " + transmitDestination + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                }
                else
                {
                    byte cindex = CandidateTable.findIndex((ushort)transmitDestination);
                    if (cindex < byte.MaxValue)
                    {
                        CandidateTable._candidateList[cindex].UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for candidate " + transmitDestination + "; new value = " + CandidateTable._candidateList[cindex].GetNumTriesInCurrentWindow());
#endif
                    }
                }
                break;

            case SendPacketStatus.SendFailed:
#if DBG_DIAGNOSTIC
                Debug.Print("\t\tNet Manager: Retry queue length = " + _retriedPackets.Count);
#endif

#if !DBG_LOGIC
                Debug.Print("Heartbeat to " + transmitDestination.ToString() + " failed");
#endif
                // Update link metrics
                if ((ushort)transmitDestination == RoutingGlobal.Parent)
                {
                    RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                    Debug.Print("Updated numTriesInCurrentWindow for parent " + transmitDestination + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                }
                else
                {
                    byte cindex = CandidateTable.findIndex((ushort)transmitDestination);
                    if (cindex < byte.MaxValue)
                    {
                        CandidateTable._candidateList[cindex].UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for candidate " + transmitDestination + "; new value = " + CandidateTable._candidateList[cindex].GetNumTriesInCurrentWindow());
#endif
                    }
                }

                // Retry
                if (!_retriedPackets.Contains(index) && RoutingGlobal._color == Color.Green)     // If packet not there, enqueue it and retry it once
                {
                    RoutingGlobal.CleanseCandidateTable(pipe);
                    Candidate tmpBst = CandidateTable.GetBestCandidate(false);
                    NetManagerGlobal.TempParent = tmpBst.GetMacID();
                    byte[] msg = new byte[NetManagerGlobal.HeartbeatMessageSize];
                    if (pipe.GetMsgWithMsgID(ref msg, index) == DeviceStatus.Success)
                    {
                        NetManagerGlobal.SendToTempParent(pipe, msg, msg.Length);
                        tmpBst.UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for TempParent " + transmitDestination + "; new value = " + tmpBst.GetNumTriesInCurrentWindow());
#endif
                        _retriedPackets.Add(index);
                    }
                }
                else     // Retried once; drop packet
                {
                    _retriedPackets.Remove(index);
                }
                break;

            default:
                break;
            }
        }
コード例 #12
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); }
        }
コード例 #13
0
 /// <summary>
 /// Construtor with custom hash function.
 /// </summary>
 /// <param name="digest">Hash function.</param>
 public PBKDF2(IHash digest, int iteration = 1000)
 {
     this._HashFunction = digest;
     this._MACFunction  = new HMAC(this._HashFunction);
     this._Iteration    = iteration;
 }
コード例 #14
0
 /// <summary>
 /// Default constructor.
 /// with HMAC-SHA1.
 /// </summary>
 public PBKDF2()
 {
     this._HashFunction = new Blake2b(512);
     this._MACFunction  = new HMAC(this._HashFunction);
     this._Iteration    = 1000;
 }
コード例 #15
0
 /// <summary>
 /// Print the neighbor list from MACBase instance
 /// </summary>
 /// <param name="macBase"></param>
 public static void PrintNeighborList(IMAC macBase)
 {
     macBase.NeighborList(Neighbors);
     PrintNumericVals("Neighbor List [for " + macBase.MACRadioObj.RadioAddress + "] ", Neighbors);
 }
コード例 #16
0
 /// <summary>
 /// Try get algorithm from mechanism.
 /// <para/>Used (block size / 2) as mac size by default.
 /// </summary>
 /// <param name="mechanism">Algorithm mechanism.</param>
 /// <param name="algorithm">Algorithm.</param>
 /// <returns></returns>
 public static bool TryGetAlgorithm(string mechanism, out IMAC algorithm)
 {
     return(TryGetAlgorithm(mechanism, -1, out algorithm));
 }
コード例 #17
0
        /// <summary>
        /// Handle an App message
        /// </summary>
        /// <param name="macBase"></param>
        /// <param name="dateTime"></param>
        /// <param name="packet"></param>
        public static void AppPipeReceive(IMAC macBase, DateTime dateTime, Packet packet)
        {
#if DBG_VERBOSE
            DebuggingSupport.PrintMessageReceived(macBase, "App");
#elif DBG_SIMPLE
            Debug.Print("");
            Debug.Print("AppPipeReceive ");
#endif
            try
            {
#if !DBG_LOGIC
                Debug.Print("\tFrom " + packet.Src);
#endif

                DebuggingSupport.PrintMessageReceived(macBase, "App");

                //Debug.Print("\ton " + packet.PayloadType);
                //var rcvPayloadBytes = packet.Payload;
                //var rcvPayloadBytes = SystemGlobal.GetTrimmedPayload(packet);
                byte[] rcvPayloadBytes = packet.Payload;
#if DBG_VERBOSE
                SystemGlobal.PrintNumericVals("App Rcv: ", rcvPayloadBytes);
#elif DBG_SIMPLE
                Debug.Print("");
#endif

                switch ((AppGlobal.MessageIds)rcvPayloadBytes[0])
                {
                case AppGlobal.MessageIds.Detect:
                {
                    AppGlobal.ClassificationType classificationType;
                    ushort originator;
                    byte   TTL;
                    ushort detectionNumber;

                    AppGlobal.MoteMessages.Parse.Detection(rcvPayloadBytes, out classificationType, out detectionNumber, out originator, out TTL);
#if DBG_SIMPLE
                    Debug.Print("\tDetect. From neighbor " + packet.Src + " # " + detectionNumber + ". Classification " + (char)classificationType + " created by " + originator + " with TTL " + TTL);
#endif
#if RELAY_NODE || CLIENT_NODE
                    //	Check if originated by self or if TTL-1 = 0
                    if (originator == AppGlobal.AppPipe.MACRadioObj.RadioAddress || --TTL == 0)
                    {
                        return;
                    }

                    #region Uncomment when scheduler disabled
                    // If in a reset, do not forward TODO: Change this to "spray"
                    if (RoutingGlobal._color == Color.Red)
                    {
#if DBG_VERBOSE
                        Debug.Print("\tIn a Reset wave... not forwarded");
#endif
                        return;
                    }
                    #endregion
                    #region Uncomment when scheduler disabled
                    /* TODO: Uncomment lines 368-394 when not using scheduler*/
                    // Not originated by self.
                    // If parent is available, pass it on
                    if (RoutingGlobal.IsParent)
                    {
                        byte[] routedMsg = new byte[rcvPayloadBytes.Length];
                        var    size      = AppGlobal.MoteMessages.Compose.Detection(routedMsg, originator, classificationType, detectionNumber, TTL);
                        Debug.Print("routed message len: " + routedMsg.Length);

                        Debug.Print("routedMsg: " + routedMsg.ToString());
                        var status = RoutingGlobal.SendToParent(AppGlobal.AppPipe, routedMsg, size);
                        Debug.Print("status " + status);
                        if (status != 999)
                        {
                            RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                            Debug.Print("Updated numTriesInCurrentWindow for Parent " + RoutingGlobal.Parent + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                        }
                        else     //Retry once
                        {
#if !DBG_LOGIC
                            Debug.Print("Retrying packet");
#endif
                            if (status != 999)
                            {
                                RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
                            }
                        }
                    }
                    #endregion
#elif BASE_STATION
                    var msg = AppGlobal.PCMessages.Compose.Detection(originator, classificationType, detectionNumber);
                    try
                    {
                        _serialComm.Write(msg);
#if DBG_VERBOSE
                        Debug.Print("\n************ Detection sent to PC " + msg.Substring(1, msg.Length - 2));
#endif
                    }
                    catch (Exception ex)
                    {
                        Debug.Print("SerialComm exception for Detection message [" + msg + "]\n" + ex);
                    }
#endif
                    break;
                }

                case AppGlobal.MessageIds.Send:
                {
                    AppGlobal.ClassificationType classificationType;
                    ushort originator;
                    byte   TTL;
                    ushort sndNumber;
                    ushort payloadLength;

                    _lcd.Write("PSnd");
                    AppGlobal.MoteMessages.Parse.SendPacket(rcvPayloadBytes, out classificationType, out sndNumber, out originator, out TTL, out payloadLength);
                    int    rcvHeader   = AppGlobal.SendMessageSize;
                    byte[] sendPayload = new byte[payloadLength];
                    AppGlobal.MoteMessages.getPayload.SendPacket(rcvPayloadBytes, rcvHeader, sendPayload, (int)payloadLength);

#if DBG_VERBOSE
                    Debug.Print("Received Packet #" + sndNumber + " from neighbor " + packet.Src);
                    Debug.Print("   Classification: " + (char)classificationType);
                    Debug.Print("   Originator: " + originator);
                    Debug.Print("   payload Length: " + payloadLength + "\n");
                    //Debug.Print("Received Packet # " + sndNumber + "From neighbor " + packet.Src + " with Classification " + (char)classificationType + ", created by " + originator + " with payload " + payloadString);
#endif
#if CLIENT_NODE
                    Debug.Print("\tClient Recieved a send message...");
                    //_serialComm.Write(rcvPayloadBytes);
#elif RELAY_NODE
                    //	Check if originated by self or if TTL-1 = 0
                    if (originator == AppGlobal.AppPipe.MACRadioObj.RadioAddress || --TTL == 0)
                    {
                        return;
                    }

                    #region Uncomment when scheduler disabled
                    // If in a reset, do not forward TODO: Change this to "spray"
                    if (RoutingGlobal._color == Color.Red)
                    {
#if DBG_VERBOSE
                        Debug.Print("\tIn a Reset wave... not forwarded");
#endif
                        return;
                    }
                    #endregion
                    #region Uncomment when scheduler disabled
                    /* TODO: Uncomment lines 368-394 when not using scheduler*/
                    // Not originated by self.
                    // If parent is available, pass it on
                    int payloadSize = sizeof(byte) * payloadLength;
                    // remove ushort in length because popping first in path
                    int rcvSize = rcvHeader + payloadSize;

                    byte[] routedMsg = new byte[rcvSize];
                    if (RoutingGlobal.IsParent)
                    {
                        var headerSize = AppGlobal.MoteMessages.Compose.SendPacket(routedMsg, originator, classificationType, sndNumber, TTL, payloadLength);
                        AppGlobal.MoteMessages.AddPayload.RecievePacket(routedMsg, headerSize, sendPayload, payloadLength);
                        Debug.Print("Sending Packet # " + sndNumber + " to neighbor " + RoutingGlobal.Parent);
                        Debug.Print("   Classification: " + (char)classificationType);
                        Debug.Print("   Originator: " + originator);
                        Debug.Print("   payload Length: " + payloadLength + "\n");
                        var status = RoutingGlobal.SendToParent(AppGlobal.AppPipe, routedMsg, rcvSize);
                        //Neighbor(AppGlobal.AppPipe, next_neighbor, routedMsg, size);
                        if (status != 999)
                        {
                            Debug.Print("Send Successful");
                            RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                            Debug.Print("Updated numTriesInCurrentWindow for Parent " + RoutingGlobal.Parent + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                        }
                        else     //Retry once
                        {
#if !DBG_LOGIC
                            Debug.Print("Retrying packet");
#endif
                            status = RoutingGlobal.SendToParent(AppGlobal.AppPipe, routedMsg, rcvSize);
                            if (status != 999)
                            {
                                Debug.Print("Send Successful");
                                //tmpBest.UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                                //Debug.Print("Updated numTriesInCurrentWindow for TempParent " + AppGlobal.TempParent + "; new value = " + tmpBest.GetNumTriesInCurrentWindow());
#endif
                            }
                        }
                    }
                    #endregion
#elif BASE_STATION
                    _packetNumber  = sndNumber;
                    _TTL           = TTL;
                    _payloadLength = payloadLength;
                    _destination   = originator;
                    //Debug.Print("Base serial output: " + rcvString);
                    _serialComm.Write(sendPayload);

                    /*
                     * var rcvString = new string(System.Text.Encoding.UTF8.GetChars(rcvPayloadBytes));
                     * Debug.Print("Base serial output: " + rcvString);
                     * _serialComm.Write(rcvString);
                     *
                     * //wait for reply
                     * int rcvSize = AppGlobal.MoteMessages.Length.SendPacket(pathLength, payloadLength);
                     * classificationType = AppGlobal.ClassificationType.Recieve;
                     * byte[] rcvPayload;
                     * if (payloadLength == 1)
                     * {
                     *  rcvPayload = BitConverter.GetBytes(GetBaseReply(sendPayload));
                     * }
                     * else
                     * {
                     *  rcvPayload = BitConverter.GetBytes('c');
                     * }
                     * int rcvPayloadLength = rcvPayload.Length;
                     *
                     * ushort next_neighbor = path[pathLength - 1];
                     *
                     * int headerSize = AppGlobal.MoteMessages.Compose.RecievePacket(rcvPayloadBytes, originator, classificationType, sndNumber, TTL, pathLength, path, payloadLength);
                     * AppGlobal.MoteMessages.AddPayload.RecievePacket(rcvPayloadBytes, headerSize, rcvPayload, rcvPayloadLength);
                     *
                     #if DBG_VERBOSE
                     * Debug.Print("Sending Packet #" + sndNumber + " to neighbor " + next_neighbor);
                     * Debug.Print("   Classification: " + (char)classificationType);
                     * Debug.Print("   Originator: " + originator);
                     * Debug.Print("   path Length: " + pathLength);
                     * Debug.Print("   payload Length: " + rcvPayloadLength + "\n");
                     #endif
                     * try
                     * {
                     #if DBG_VERBOSE
                     *  Debug.Print("Send Successful");
                     #endif
                     *  var status = RoutingGlobal.SendToNeighbor(AppGlobal.AppPipe, next_neighbor, rcvPayloadBytes, rcvSize);
                     *
                     #if DBG_VERBOSE
                     *                              Debug.Print("\n************ Detection sent to PC " + msg.Substring(1,msg.Length-2));
                     #endif
                     * }
                     * catch (Exception ex)
                     * {
                     *  Debug.Print("SerialComm exception for Detection message [" + rcvSize + "]\n" + ex);
                     * }
                     */
#endif
                    break;
                }

                case AppGlobal.MessageIds.Recieve:
                {
                    AppGlobal.ClassificationType classificationType;
                    ushort originator;
                    ushort destination;
                    byte   TTL;
                    ushort rcvNumber;
                    ushort payloadLength;

                    _lcd.Write("PRcv");
                    AppGlobal.MoteMessages.Parse.RecievePacket(rcvPayloadBytes, out classificationType, out rcvNumber, out originator, out destination, out TTL, out payloadLength);
#if DBG_VERBOSE
                    Debug.Print("Received Packet #" + rcvNumber + " from neighbor " + packet.Src);
                    Debug.Print("   Classification: " + (char)classificationType);
                    Debug.Print("   Originator: " + originator);
                    Debug.Print("   payload Length: " + payloadLength + "\n");
#endif
                    //Debug.Print("\tRecieve. From neighbor " + packet.Src + " # " + rcvNumber + ". Classification " + (char)classificationType + " created by " + originator + " with TTL " + TTL);
#if CLIENT_NODE
                    int    rcvHeader  = AppGlobal.RecieveMessageSize;
                    byte[] rcvPayload = new byte[payloadLength];
                    AppGlobal.MoteMessages.getPayload.RecievePacket(rcvPayloadBytes, rcvHeader, rcvPayload, (int)payloadLength);

                    //var rcvString = new string(System.Text.Encoding.UTF8.GetChars(rcvPayload));
                    //Debug.Print("Client serial output: " + rcvString);
                    _serialComm.Write(rcvPayloadBytes);
#elif RELAY_NODE
                    //	Check if originated by self or if TTL-1 = 0
                    if (originator == AppGlobal.AppPipe.MACRadioObj.RadioAddress || --TTL == 0)
                    {
                        return;
                    }

                    #region Uncomment when scheduler disabled
                    // If in a reset, do not forward TODO: Change this to "spray"
                    if (RoutingGlobal._color == Color.Red)
                    {
#if DBG_VERBOSE
                        Debug.Print("\tIn a Reset wave... not forwarded");
#endif
                        return;
                    }
                    #endregion
                    #region Uncomment when scheduler disabled
                    /* TODO: Uncomment lines 368-394 when not using scheduler*/
                    // Not originated by self.
                    // If parent is available, pass it on
                    int    sndHeader  = AppGlobal.RecieveMessageSize;
                    byte[] sndPayload = new byte[payloadLength];
                    AppGlobal.MoteMessages.getPayload.SendPacket(rcvPayloadBytes, sndHeader, sndPayload, (int)payloadLength);

                    int sendSize   = sndHeader + payloadLength;
                    var routedMsg  = new byte[sendSize];
                    var headerSize = AppGlobal.MoteMessages.Compose.RecievePacket(routedMsg, originator, classificationType, rcvNumber, TTL, payloadLength);

                    AppGlobal.MoteMessages.AddPayload.RecievePacket(routedMsg, headerSize, sndPayload, payloadLength);
#if DBG_VERBOSE
                    Debug.Print("Sending Packet # " + rcvNumber + " to child");
                    Debug.Print("   Classification: " + (char)classificationType);
                    Debug.Print("   Originator: " + originator);
                    Debug.Print("   payload Length: " + payloadLength + "\n");
#endif
                    var status = RoutingGlobal.SendToChild(AppGlobal.AppPipe, destination, routedMsg, sendSize);
                    if (status != 999)
                    {
                        Debug.Print("Send Successful");

                        RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for Parent " + RoutingGlobal.Parent + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                    }
                    else     //Retry once
                    {
#if !DBG_LOGIC
                        Debug.Print("Retrying packet");
#endif
                        status = RoutingGlobal.SendToChild(AppGlobal.AppPipe, destination, routedMsg, sendSize);

                        if (status != 999)
                        {
                            Debug.Print("Send Successful");
                            //tmpBest.UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                            //Debug.Print("Updated numTriesInCurrentWindow for TempParent " + AppGlobal.TempParent + "; new value = " + tmpBest.GetNumTriesInCurrentWindow());
#endif
                        }
                    }
                    #endregion
#elif BASE_STATION
#endif
                    break;
                }

                default:
                    Debug.Print("AppPipeReceive unknown rcvPayloadBytes[0] ");
                    throw new ArgumentOutOfRangeException();
                }
                #region unused
                ////var rcvPayloadChar = Encoding.UTF8.GetChars(rcvPayloadBytes);
                ////var payload = new string(rcvPayloadChar);

                //if (payload.Substring(0, 5).Equals("Human")) //Data packets--human
                //{
                //	Debug.Print("\n\tReceived decision: " + payload.Substring(0, 5) + "; source: " + payload.Substring(5) + "; from Node: " + packet.Src);
                //	_lcd.Write("" + (++_numData));
                //}

                //if (RoutingGlobal.Parent == SystemGlobal.NoParent)
                //{
                //	Debug.Print("\tNo parent specified ");
                //	return;
                //}
                ////Debug.Print("\t\t*** Parent: "+ Parent+", SelfAddress: "+SelfAddress);
                //if (RoutingGlobal.Parent == _routing.SelfAddress)
                //{
                //	Debug.Print("\tAt base");
                //	return;
                //}
                //var toSendByte = Encoding.UTF8.GetBytes(payload);
                //var status = AppPipe.Send(RoutingGlobal.Parent, toSendByte, 0, (ushort)toSendByte.Length);
                //if (status != NetOpStatus.S_Success)
                //{
                //	Debug.Print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Send status: " + status);
                //}

                //SystemGlobal.PrintNumericVals("App Snd: ", toSendByte);

                //Debug.Print("Forwarded to parent node: " + RoutingGlobal.Parent);
                #endregion
            }
            catch (Exception e)
            {
                Debug.Print(e.ToString());
            }
        }
コード例 #18
0
        /// <summary>
        /// Try get algorithm from mechanism.
        /// <para/>Legal mac size is between 8 and block size (8 bits increments).
        /// <para/>Legal mac size must be at least 24 bits (FIPS Publication 81) or 16 bits if being used as a data authenticator (FIPS Publication 113).
        /// <para/>Used (block size / 2) as mac size by default.
        /// </summary>
        /// <param name="mechanism">Algorithm mechanism.</param>
        /// <param name="macSize">MAC size bits.</param>
        /// <param name="algorithm">Algorithm.</param>
        /// <returns></returns>
        public static bool TryGetAlgorithm(string mechanism, int macSize, out IMAC algorithm)
        {
            mechanism = mechanism.Replace('_', '-').ToUpperInvariant();
            if (mechanism.EndsWith("MAC"))
            {
                if (mechanism.EndsWith("/MAC") || mechanism.EndsWith("-MAC"))
                {
                    mechanism = mechanism.Substring(0, mechanism.Length - 4);
                }
                else
                {
                    mechanism = mechanism.Substring(0, mechanism.Length - 3);
                }
            }
            mechanism = mechanism.Replace('/', '-');
            switch (mechanism)
            {
            case "AES": return(TryGetNanoAlgorithm(AES_MAC, macSize, out algorithm));

            case "BLOWFISH": return(TryGetNanoAlgorithm(Blowfish_MAC, macSize, out algorithm));

            case "CAMELLIA": return(TryGetNanoAlgorithm(Camellia_MAC, macSize, out algorithm));

            case "CAST5": return(TryGetNanoAlgorithm(CAST5_MAC, macSize, out algorithm));

            case "CAST6": return(TryGetNanoAlgorithm(CAST6_MAC, macSize, out algorithm));

            case "DES": return(TryGetNanoAlgorithm(DES_MAC, macSize, out algorithm));

            case "DESEDE":
            case "DESEDE3":
            case "TDEA":
            case "TRIPLEDES":
            case "3DES": return(TryGetNanoAlgorithm(DESede_MAC, macSize, out algorithm));

            case "DSTU7624-128": return(TryGetNanoAlgorithm(DSTU7624_128_MAC, macSize, out algorithm));

            case "DSTU7624-256": return(TryGetNanoAlgorithm(DSTU7624_256_MAC, macSize, out algorithm));

            case "DSTU7624-512": return(TryGetNanoAlgorithm(DSTU7624_512_MAC, macSize, out algorithm));

            case "GOST28147": return(TryGetNanoAlgorithm(GOST28147_MAC, macSize, out algorithm));

            case "IDEA": return(TryGetNanoAlgorithm(IDEA_MAC, macSize, out algorithm));

            case "NOEKEON": return(TryGetNanoAlgorithm(Noekeon_MAC, macSize, out algorithm));

            case "RC2": return(TryGetNanoAlgorithm(RC2_MAC, macSize, out algorithm));

            case "RC5":
            case "RC5-32": return(TryGetNanoAlgorithm(RC5_MAC, macSize, out algorithm));

            case "RC5-64": return(TryGetNanoAlgorithm(RC5_64_MAC, macSize, out algorithm));

            case "RC6": return(TryGetNanoAlgorithm(RC6_MAC, macSize, out algorithm));

            case "RIJNDAEL-128":
            case "RIJNDAEL128": return(TryGetNanoAlgorithm(Rijndael_128_MAC, macSize, out algorithm));

            case "RIJNDAEL-160":
            case "RIJNDAEL160": return(TryGetNanoAlgorithm(Rijndael_160_MAC, macSize, out algorithm));

            case "RIJNDAEL-192":
            case "RIJNDAEL192": return(TryGetNanoAlgorithm(Rijndael_192_MAC, macSize, out algorithm));

            case "RIJNDAEL-224":
            case "RIJNDAEL224": return(TryGetNanoAlgorithm(Rijndael_224_MAC, macSize, out algorithm));

            case "RIJNDAEL-256":
            case "RIJNDAEL256": return(TryGetNanoAlgorithm(Rijndael_256_MAC, macSize, out algorithm));

            case "SEED": return(TryGetNanoAlgorithm(SEED_MAC, macSize, out algorithm));

            case "SERPENT": return(TryGetNanoAlgorithm(Serpent_MAC, macSize, out algorithm));

            case "SKIPJACK": return(TryGetNanoAlgorithm(SKIPJACK_MAC, macSize, out algorithm));

            case "SM4": return(TryGetNanoAlgorithm(SM4_MAC, macSize, out algorithm));

            case "TEA": return(TryGetNanoAlgorithm(TEA_MAC, macSize, out algorithm));

            case "THREEFISH-256":
            case "THREEFISH256": return(TryGetNanoAlgorithm(Threefish_256_MAC, macSize, out algorithm));

            case "THREEFISH-512":
            case "THREEFISH512": return(TryGetNanoAlgorithm(Threefish_512_MAC, macSize, out algorithm));

            case "THREEFISH-1024":
            case "THREEFISH1024": return(TryGetNanoAlgorithm(Threefish_1024_MAC, macSize, out algorithm));

            case "TNEPRES": return(TryGetNanoAlgorithm(Tnepres_MAC, macSize, out algorithm));

            case "TWOFISH": return(TryGetNanoAlgorithm(Twofish_MAC, macSize, out algorithm));

            case "XTEA": return(TryGetNanoAlgorithm(XTEA_MAC, macSize, out algorithm));

            default: algorithm = null; return(false);
            }
        }