Represents a shortform globally unique identifier (GUID) which is easier to handle than Guid.NewGuid(). This class is used to uniquely identify a peer/application using NetworkComms.Net. See here for original source.
        public ItemRemovalUpdate(ShortGuid sourceNetworkIdentifier, string itemCheckSum, bool removeSwarmWide)
        {
            if (sourceNetworkIdentifier == null)
                throw new NullReferenceException("Unable to create ItemRemovalUpdate unless a valid sourceNetworkIdentifier is provided.");

            this.SourceNetworkIdentifier = sourceNetworkIdentifier;
            this.ItemCheckSum = itemCheckSum;
            this.RemoveSwarmWide = removeSwarmWide;
        }
        /// <summary>
        /// Get the provided peer IPEndPoint online status
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
        /// <returns></returns>
        public bool IPEndPointOnline(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
        {
            if (networkIdentifier == ShortGuid.Empty) throw new Exception("networkIdentifier should not be empty.");

            lock (peerLocker)
            {
                if (peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier))
                    peerAvailabilityByNetworkIdentifierDict[networkIdentifier].IsPeerIPEndPointOnline(networkIdentifier, peerIPEndPoint);
            }

            return false;
        }
        /// <summary>
        /// Set the provided peer IPEndPoint as offline
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
        public void SetIPEndPointOffline(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
        {
            if (networkIdentifier == ShortGuid.Empty) throw new Exception("networkIdentifier should not be empty.");

            lock (peerLocker)
            {
                if (peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier))
                    peerAvailabilityByNetworkIdentifierDict[networkIdentifier].SetPeerIPEndPointOnlineStatus(networkIdentifier, peerIPEndPoint, true);
            }
        }
 /// <summary>
 /// Removes any peers which have the same endPoint as the provided currentActivePeerEndPoint except one with matching currentActivePeerIdentifier
 /// </summary>
 /// <param name="currentActivePeerIdentifier">The NetworkIdenfier of the known active peer</param>
 /// <param name="currentActivePeerEndPoint">The endPoint of the known active peer</param>
 public void RemoveOldPeerAtEndPoint(ShortGuid currentActivePeerIdentifier, IPEndPoint currentActivePeerEndPoint)
 {
     lock (peerLocker)
     {
         //If we already have an entry for the provided endPoint but it does not match the provided currentActivePeerIdentifier
         //We need to remove the provided endPoint from the old peer
         string ipEndPointString = currentActivePeerEndPoint.ToString();
         if (peerEndPointToNetworkIdentifier.ContainsKey(ipEndPointString) && peerEndPointToNetworkIdentifier[ipEndPointString] != currentActivePeerIdentifier)
         {
             //Remove the provided currentActivePeerEndPoint from the old peer
             RemovePeerIPEndPointFromSwarm(peerEndPointToNetworkIdentifier[ipEndPointString], currentActivePeerEndPoint);
         }
     }
 }
 /// <summary>
 /// Create an ChunkAvailabilityReply which will precede the requested data.
 /// </summary>
 /// <param name="sourceNetworkIdentifier">The network identifier of the source of this ChunkAvailabilityReply</param>
 /// <param name="itemCheckSum">The checksum of the DFS item</param>
 /// <param name="chunkIndex">The chunkIndex of the requested item</param>
 /// <param name="packetIdentifier">The packet identifier used to send the data</param>
 public ChunkAvailabilityReply(ShortGuid sourceNetworkIdentifier, string itemCheckSum, byte chunkIndex, string packetIdentifier)
 {
     this.SourceNetworkIdentifier = sourceNetworkIdentifier;
     this.ItemCheckSum = itemCheckSum;
     this.ChunkIndex = chunkIndex;
     this.PacketIdentifier = packetIdentifier;
     this.ReplyState = ChunkReplyState.DataIncluded;
 }
 /// <summary>
 /// Execute this method when a peer is discovered 
 /// </summary>
 /// <param name="peerIdentifier">The network identifier of the discovered peer</param>
 /// <param name="discoveredPeerEndPoints">The discoverable endpoints found for the provided peer</param>
 private static void PeerDiscovered(ShortGuid peerIdentifier, Dictionary<ConnectionType, List<EndPoint>> discoveredPeerEndPoints)
 {
     //Lock to ensure we do not write to the console in parallel.
     lock (locker)
     {
         Console.WriteLine("\nEndpoints discovered for peer with networkIdentifier {0} ...", peerIdentifier);
         foreach (ConnectionType connectionType in discoveredPeerEndPoints.Keys)
         {
             Console.WriteLine("  ... endPoints of type {0}:", connectionType);
             foreach (EndPoint endPoint in discoveredPeerEndPoints[connectionType])
                 Console.WriteLine("    -> {0}", endPoint.ToString());
         }
     }
 }
        /// <summary>
        /// Returns the new timeout count value after incrementing the timeout count for the provided peer IPEndPoint.
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
        /// <returns></returns>
        public int GetNewTimeoutCount(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
        {
            if (networkIdentifier == ShortGuid.Empty) throw new Exception("networkIdentifier should not be empty.");

            lock (peerLocker)
            {
                if (!peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier))
                    return 0;

                return peerAvailabilityByNetworkIdentifierDict[networkIdentifier].GetNewTimeoutCount(networkIdentifier, peerIPEndPoint);
            }
        }
        /// <summary>
        /// Returns true if a peer has a complete copy of the DFS item
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="totalNumChunks">The total number of chunks in this item</param>
        /// <returns></returns>
        public bool PeerIsComplete(ShortGuid networkIdentifier, byte totalNumChunks)
        {
            if (networkIdentifier == ShortGuid.Empty) throw new Exception("networkIdentifier should not be empty.");

            lock (peerLocker)
            {
                if (!peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier))
                    throw new Exception("networkIdentifier provided does not exist in peerChunksByNetworkIdentifierDict. Check with PeerExistsInSwarm before calling this method.");

                return peerAvailabilityByNetworkIdentifierDict[networkIdentifier].PeerChunkFlags.AllFlagsSet(totalNumChunks);
            }
        }
        /// <summary>
        /// Update the provided peer IPEndPoint busy status
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
        /// <param name="busyStatus">The new peer busy status</param>
        public void SetPeerIPEndPointBusyStatus(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint, bool busyStatus)
        {
            ConnectionInfo connectionInfo = new ConnectionInfo(ConnectionType.TCP, networkIdentifier, peerIPEndPoint, true);
            lock (syncRoot)
            {
                ValidateNetworkIdentifier(connectionInfo);

                IPEndPointBusyDict[connectionInfo] = busyStatus;
                IPEndPointBusyAnnounceTimeDict[connectionInfo] = DateTime.Now;
            }
        }
        /// <summary>
        /// Returns the current busy status of the requested peer IPEndPoint
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
        /// <returns></returns>
        public bool IsPeerIPEndPointBusy(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
        {
            ConnectionInfo connectionInfo = new ConnectionInfo(ConnectionType.TCP, networkIdentifier, peerIPEndPoint, true);
            lock (syncRoot)
            {
                ValidateNetworkIdentifier(connectionInfo);

                if (IPEndPointBusyDict.ContainsKey(connectionInfo))
                    return IPEndPointBusyDict[connectionInfo];
                else
                    return false;
            }
        }
 /// <summary>
 /// Update the provided peer IPEndPoint online status
 /// </summary>
 /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
 /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
 /// <param name="onlineStatus">The new online status</param>
 public void SetPeerIPEndPointOnlineStatus(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint, bool onlineStatus)
 {
     ConnectionInfo connectionInfo = new ConnectionInfo(ConnectionType.TCP, networkIdentifier, peerIPEndPoint, true);
     lock (syncRoot)
     {
         ValidateNetworkIdentifier(connectionInfo);
         IPEndPointOnlineDict[connectionInfo] = onlineStatus;
     }
 }
        /// <summary>
        /// Returns true if the specified peer has the specified IPEndPoint online.
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the peer to check</param>
        /// <param name="peerIPEndPoint">The IPEndPoint of the peer to check</param>
        /// <returns></returns>
        public bool IsPeerIPEndPointOnline(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
        {
            ConnectionInfo connectionInfo = new ConnectionInfo(ConnectionType.TCP, networkIdentifier, peerIPEndPoint, true);
            lock (syncRoot)
            {
                ValidateNetworkIdentifier(connectionInfo);

                if (SuperPeer)
                {
                    //We may have many possible IPEndPoints for a super peer.
                    //If we have at least one IPEndPoint that is indeed marked as online we only return true for that match
                    if (IPEndPointOnlineDict.ContainsKey(connectionInfo))
                        return IPEndPointOnlineDict[connectionInfo];
                    else
                    {
                        if ((from current in IPEndPointOnlineDict where current.Value == true select current).Count() > 0)
                            return false;
                        else
                            //If no IPEndPoints are yet marked as online we return true by default
                            return true;
                    }
                }

                if (IPEndPointOnlineDict.ContainsKey(connectionInfo))
                    return IPEndPointOnlineDict[connectionInfo];
                else
                    return false;
            }
        }
        /// <summary>
        /// Returns the chunk flag availability of the requested peer.
        /// </summary>
        /// <param name="peerIdentifier">The relevant network identifier</param>
        /// <returns></returns>
        public ChunkFlags PeerChunkAvailability(ShortGuid peerIdentifier)
        {
            if (peerIdentifier == ShortGuid.Empty) throw new Exception("networkIdentifier should not be empty.");

            lock (peerLocker)
            {
                if (PeerExistsInSwarm(peerIdentifier))
                    return peerAvailabilityByNetworkIdentifierDict[peerIdentifier].PeerChunkFlags;
                else
                    throw new Exception("A peer with the provided peerIdentifier does not exist in this swarm.");
            }
        }
        /// <summary>
        /// Single method for determining if contact can be made with the request peer.
        /// Prevents loop back contact via matching identifier and currentLocalListenEndPoints.
        /// Finally uses the DFS.AllowedPeerIPS and DFS.DisallowedPeerIPS if set.
        /// </summary>
        /// <param name="peerIdentifier">The relevant network identifier</param>
        /// <param name="peerEndPoint">The relevant IPEndPoint</param>
        /// <param name="superPeer">True if this peer is a super peer</param>
        /// <returns></returns>
        public bool PeerContactAllowed(ShortGuid peerIdentifier, IPEndPoint peerEndPoint, bool superPeer)
        {
            if (peerIdentifier == NetworkComms.NetworkIdentifier)
                return false;

            List<EndPoint> currentLocalListenEndPoints = Connection.ExistingLocalListenEndPoints(ConnectionType.TCP);
            if (currentLocalListenEndPoints.Contains(peerEndPoint))
                return false;

            //We always allow super peers
            //If this is not a super peer and we have set the allowedPeerIPs then we check in there
            bool peerAllowed = false;
            if (!superPeer && (DFS.allowedPeerIPs.Count > 0 || DFS.disallowedPeerIPs.Count > 0))
            {
                if (DFS.allowedPeerIPs.Count > 0)
                    peerAllowed = DFS.allowedPeerIPs.Contains(peerEndPoint.Address.ToString());
                else
                    peerAllowed = !DFS.disallowedPeerIPs.Contains(peerEndPoint.Address.ToString());
            }
            else
                peerAllowed = true;

            return peerAllowed;
        }
        /// <summary>
        /// Returns true if a peer with the provided networkIdentifier exists in this SwarmChunkAvailability
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <returns></returns>
        public bool PeerExistsInSwarm(ShortGuid networkIdentifier)
        {
            if (networkIdentifier == ShortGuid.Empty) throw new Exception("networkIdentifier should not be empty.");

            lock (peerLocker)
                return peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier);
        }
        /// <summary>
        /// Returns true if the specified peer has the specified chunkIndex.
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="chunkIndex">The desired chunkIndex</param>
        /// <returns></returns>
        public bool PeerHasChunk(ShortGuid networkIdentifier, byte chunkIndex)
        {
            if (networkIdentifier == ShortGuid.Empty) throw new Exception("networkIdentifier should not be empty.");

            lock (peerLocker)
            {
                if (peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier))
                    return peerAvailabilityByNetworkIdentifierDict[networkIdentifier].PeerChunkFlags.FlagSet(chunkIndex);
                else
                    throw new Exception("No peer was found in peerChunksByNetworkIdentifierDict with the provided networkIdentifier.");
            }
        }
        /// <summary>
        /// Returns the new timeout count value after incrementing the timeout count.
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
        /// <returns></returns>
        public int GetNewTimeoutCount(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
        {
            ConnectionInfo connectionInfo = new ConnectionInfo(ConnectionType.TCP, networkIdentifier, peerIPEndPoint, true);
            lock (syncRoot)
            {
                ValidateNetworkIdentifier(connectionInfo);

                if (IPEndPointTimeoutCountDict.ContainsKey(connectionInfo))
                    return ++IPEndPointTimeoutCountDict[connectionInfo];
                else
                {
                    IPEndPointTimeoutCountDict[connectionInfo] = 1;
                    return 1;
                }
            }
        }
        /// <summary>
        /// Returns true if the specified peer is a super peer
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <returns></returns>
        public bool PeerIsSuperPeer(ShortGuid networkIdentifier)
        {
            if (networkIdentifier == ShortGuid.Empty) throw new Exception("networkIdentifier should not be empty.");

            lock (peerLocker)
            {
                if (!peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier))
                    return false;

                return peerAvailabilityByNetworkIdentifierDict[networkIdentifier].SuperPeer;
            }
        }
 /// <summary>
 /// Removes the provided connectionInfo from all internal dictionaries. Returns true if connectionInfo exists, otherwise false
 /// </summary>
 /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
 /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
 /// <returns></returns>
 public bool RemovePeerIPEndPoint(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
 {
     ConnectionInfo connectionInfo = new ConnectionInfo(ConnectionType.TCP, networkIdentifier, peerIPEndPoint, true);
     return RemovePeerIPEndPoint(connectionInfo);
 }
        /// <summary>
        /// Deletes knowledge of a peer IPEndPoint from our local swarm chunk availability. 
        /// If peerEndPoint.Address is IPAddress.Any then the entire peer will be deleted. 
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerEndPoint">The relevant IPEndPoint</param>
        /// <param name="forceRemoveWholePeer">If true every IPEndPoint is removed for the provided network identifier</param>
        public void RemovePeerIPEndPointFromSwarm(ShortGuid networkIdentifier, IPEndPoint peerEndPoint, bool forceRemoveWholePeer = false)
        {
            try
            {
                if (networkIdentifier == null || networkIdentifier == ShortGuid.Empty) 
                    throw new Exception("networkIdentifier should not be empty.");

                if (peerEndPoint.Address == IPAddress.Any && !forceRemoveWholePeer)
                    throw new Exception("IPEndPoint may only reference IPAddress.Any if forceRemoveWholePeer is true.");

                lock (peerLocker)
                {
                    //If we have an entry for this peer in peerAvailabilityByNetworkIdentifierDict
                    //We only remove the peer if we have more than one and it is not a super peer
                    if (peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier))
                    {
                        //We can remove this peer if
                        //1. We have set force remove
                        //or
                        //2. We have more than at least 1 other peer AND if this is a super peer we need at least 1 other super peer in order to remove
                        if (forceRemoveWholePeer ||
                            (peerAvailabilityByNetworkIdentifierDict.Count > 1 &&
                                (!peerAvailabilityByNetworkIdentifierDict[networkIdentifier].SuperPeer ||
                                (from current in peerAvailabilityByNetworkIdentifierDict where current.Value.SuperPeer select current.Key).Count() > 1)))
                        {
                            //If we have set force remove for the whole peer
                            //or this is the last IPEndPoint for the peer
                            if (forceRemoveWholePeer || peerAvailabilityByNetworkIdentifierDict[networkIdentifier].NumberOfConnectionInfos == 1)
                            {
                                //We need to remove all traces of this peer
                                if (peerAvailabilityByNetworkIdentifierDict[networkIdentifier].NumberOfConnectionInfos == 1 &&
                                    !peerAvailabilityByNetworkIdentifierDict[networkIdentifier].GetConnectionInfo()[0].LocalEndPoint.Equals(peerEndPoint) &&
                                    !forceRemoveWholePeer)
                                {
                                    //This circumstance could happen if multiple threads attempt to remove the same peer endPoint. The first one would succeed, the second
                                    //one was previously hitting this exception incorrectly.
                                    if (DFS.loggingEnabled) DFS._DFSLogger.Trace(" ... attempted to remove peer from swarm which has one remaining localEndPoint, but which doesn't match the provided peerEndPoint to remove - " + peerEndPoint + ".");
                                    return;
                                    //throw new Exception("Possible corruption detected in SwarmChunkAvailability - 1 - " + peerAvailabilityByNetworkIdentifierDict[networkIdentifier].GetConnectionInfo()[0].LocalEndPoint + " - " + peerEndPoint);
                                }

                                if (peerEndPointToNetworkIdentifier.ContainsKey(peerEndPoint.ToString()) && peerEndPointToNetworkIdentifier[peerEndPoint.ToString()] != networkIdentifier)
                                    throw new Exception("Possible corruption detected in SwarmChunkAvailability - 2");

                                List<ConnectionInfo> peerConnectionInfos = peerAvailabilityByNetworkIdentifierDict[networkIdentifier].GetConnectionInfo();
                                foreach (ConnectionInfo connInfo in peerConnectionInfos)
                                {
                                    peerAvailabilityByNetworkIdentifierDict[networkIdentifier].RemovePeerIPEndPoint(connInfo);
                                    peerEndPointToNetworkIdentifier.Remove(connInfo.LocalEndPoint.ToString());
                                }

                                peerAvailabilityByNetworkIdentifierDict.Remove(networkIdentifier);

                                if (DFS.loggingEnabled) DFS._DFSLogger.Trace(" ... removed entire peer from swarm - " + networkIdentifier + ".");
                            }
                            else
                            {
                                bool removeResult = peerAvailabilityByNetworkIdentifierDict[networkIdentifier].RemovePeerIPEndPoint(networkIdentifier, peerEndPoint);
                                peerEndPointToNetworkIdentifier.Remove(peerEndPoint.ToString());

                                if (removeResult)
                                {
                                    if (DFS.loggingEnabled) DFS._DFSLogger.Trace(" ... removed peer IPEndPoint from swarm - " + networkIdentifier + " - " + peerEndPoint.ToString() + ".");
                                }
                                else
                                {
                                    if (DFS.loggingEnabled) DFS._DFSLogger.Trace(" ... attempted to removed peer IPEndPoint from swarm but it didn't exist - " + networkIdentifier + " - " + peerEndPoint.ToString() + ".");
                                }
                            }
                        }
                        else
                        {
                            if (DFS.loggingEnabled) DFS._DFSLogger.Trace(" ... remove failed as forceRemove= " + forceRemoveWholePeer + ", peerAvailabilityByNetworkIdentifierDict.Count=" + peerAvailabilityByNetworkIdentifierDict.Count + ", isSuperPeer=" + peerAvailabilityByNetworkIdentifierDict[networkIdentifier].SuperPeer + ", superPeerCount=" + (from current in peerAvailabilityByNetworkIdentifierDict where current.Value.SuperPeer select current.Key).Count());
                        }
                    }
                    else
                    {
                        if (DFS.loggingEnabled) DFS._DFSLogger.Trace(" ... peer did not exist in peerAvailabilityByNetworkIdentifierDict. Checking for old ipEndPoint references");

                        //Remove any accidental entries left in the endpoint dict
                        peerEndPointToNetworkIdentifier.Remove(peerEndPoint.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                LogTools.LogException(ex, "Error_RemovePeerFromSwarm");
            }
        }
        /// <summary>
        /// Add new IPEndPoint for a peer. Returns true if successfully added, otherwise false.
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
        /// <returns></returns>
        public bool AddPeerIPEndPoint(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
        {
            ConnectionInfo connectionInfo = new ConnectionInfo(ConnectionType.TCP, networkIdentifier, peerIPEndPoint, true);
            lock (syncRoot)
            {
                ValidateNetworkIdentifier(connectionInfo);

                if (PeerConnectionInfo.Contains(connectionInfo))
                    return false;
                else
                {
                    PeerConnectionInfo.Add(connectionInfo);
                    IPEndPointBusyAnnounceTimeDict.Add(connectionInfo, DateTime.Now);
                    IPEndPointOnlineDict.Add(connectionInfo, false);
                    IPEndPointBusyDict.Add(connectionInfo, false);
                    IPEndPointTimeoutCountDict.Add(connectionInfo, 0);

                    return true;
                }
            }
        }
        /// <summary>
        /// Returns true if the provided IPEndPoint exists for this peer
        /// </summary>
        /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
        /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
        /// <returns></returns>
        public bool PeerContainsIPEndPoint(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
        {
            ConnectionInfo connectionInfo = new ConnectionInfo(ConnectionType.TCP, networkIdentifier, peerIPEndPoint, true);
            lock (syncRoot)
            {
                ValidateNetworkIdentifier(connectionInfo);

                return PeerConnectionInfo.Contains(connectionInfo);
            }
        }
 /// <summary>
 /// Set the provided peer IPEndPoint busy status to busy
 /// </summary>
 /// <param name="networkIdentifier">The network identifier of the relevant peer</param>
 /// <param name="peerIPEndPoint">The relevant IPEndPoint</param>
 public void SetIPEndPointBusy(ShortGuid networkIdentifier, IPEndPoint peerIPEndPoint)
 {
     lock (peerLocker)
     {
         if (peerAvailabilityByNetworkIdentifierDict.ContainsKey(networkIdentifier))
             peerAvailabilityByNetworkIdentifierDict[networkIdentifier].SetPeerIPEndPointBusyStatus(networkIdentifier, peerIPEndPoint, true);
     }
 }
 /// <summary>
 /// Create a new ChatMessage
 /// </summary>
 /// <param name="sourceIdentifier">The source identifier</param>
 /// <param name="sourceName">The source name</param>
 /// <param name="message">The message to be sent</param>
 /// <param name="messageIndex">The index of this message</param>
 public ChatMessage(ShortGuid sourceIdentifier, string sourceName, string message, long messageIndex)
 {
     this._sourceIdentifier = sourceIdentifier;
     this.SourceName = sourceName;
     this.Message = message;
     this.MessageIndex = messageIndex;
     this.RelayCount = 0;
 }
        /// <summary>
        /// Deserializes remote listeners that are discoverable
        /// </summary>
        /// <param name="data"></param>
        /// <param name="networkIdentifier"></param>
        /// <returns></returns>
        private static List<PeerListenerEndPoint> DeserializeRemoteListenerList(byte[] data, out ShortGuid networkIdentifier)
        {
            List<PeerListenerEndPoint> result = new List<PeerListenerEndPoint>();
            
            int offset = 0;

            byte[] idData = new byte[16];
            Buffer.BlockCopy(data, 0, idData, 0, 16); offset += 16;
            networkIdentifier = new ShortGuid(new Guid(idData));
            int numElements = BitConverter.ToInt32(data, offset); offset += sizeof(int);

            for (int i = 0; i < numElements; i++)
            {
                int size = BitConverter.ToInt32(data, offset); offset += sizeof(int);

                if (size > data.Length)
                    throw new Exception();

                byte[] peerData = new byte[size];
                Buffer.BlockCopy(data, offset, peerData, 0, peerData.Length); offset += peerData.Length;
                result.Add(PeerListenerEndPoint.Deserialize(peerData));
            }

            return result;
        }