async Task SendData(byte[] Data, IncomingClient client)
        {
            try
            {
                byte[] nonce = new byte[8];
                Common.rngCsp.GetBytes(nonce);

                byte[] counter_sender_data = Utils.GetLengthAsBytes((int)client.PacketCounter).Concat(Data).ToArray();

                byte[] CryptedCounterSenderData = Salsa20.ProcessSalsa20(counter_sender_data, client.TransportKey, nonce, 0);

                byte[] HMAC = (new HMACSHA256(client.AuthenticationKey)).ComputeHash(CryptedCounterSenderData).Take(16).ToArray();

                byte[] NONCE_MAC_DATA = nonce.Concat(HMAC).Concat(CryptedCounterSenderData).ToArray();

                await PacketSender.SendTransportPacket(client.client.GetStream(), TransportPacketType.DataCrypted, NONCE_MAC_DATA);
            }
            catch { }
        }
        public void StartListeningInternal()
        {
            try
            {
                listener.Start();

                while (Constants.ApplicationRunning)
                {
                    IncomingClient _inClient = new IncomingClient();
                    _inClient.client = listener.AcceptTcpClient();

                    Constants.SERVER_GLOBAL_TOTAL_ACC_CONNS++;

                    Hash hsh = new Hash(Utils.GenerateUniqueGUID_Bytes(8));
                    _inClient.Identifier = hsh;

                    ThreadList.Add(hsh, _inClient);

                    Task.Run(() => { ClientHandler(_inClient); });

                    /*Thread clientThread = new Thread(new ParameterizedThreadStart(ClientHandler));
                    _inClient.thread = clientThread;
                    clientThread.Start(_inClient);*/
                }
            }
            catch (Exception ex)
            {
                DisplayUtils.Display("Listening", ex);
            }
        }
        //System.Diagnostics.Stopwatch sw_timer = new System.Diagnostics.Stopwatch();

        async Task ProcessIncomingUserInternal(IncomingClient iClient, TransportPacket p)
        {
            BinaryReader reader = new BinaryReader(iClient.client.GetStream());
            //BinaryWriter writer = new BinaryWriter(iClient.client.GetStream());

            NetworkStream writer = iClient.client.GetStream();

            //DisplayUtils.Display("Packet Received: " + p.Type);

            switch (p.Type)
            {
                case TransportPacketType.Initialize:

                    iClient.ConnTimeStart = DateTime.UtcNow.Ticks;

                    //DisplayUtils.Display("Init Received", DisplayType.Info);

                    if ((!iClient.WorkProven) && (!iClient.KeyExchanged))
                    {
                        await PacketSender.SendTransportPacket(writer, TransportPacketType.WorkProofRequest, iClient.WorkTask);
                    }

                    break;

                case TransportPacketType.WorkProofKeyResponse:
                    //DisplayUtils.Display("WorkProofResponse Received : " + p.Data.Length, DisplayType.Info);

                    if ((!iClient.WorkProven) && (!iClient.KeyExchanged))
                    {
                        if (p.Data.Length == 60)
                        {
                            Constants.SERVER_GLOBAL_AUTH_PACKETS++;

                            byte[] Proof = new byte[4];
                            byte[] DHClientPublic = new byte[32];
                            byte[] AuthRandom = new byte[24];

                            Array.Copy(p.Data, 0, Proof, 0, 4);
                            Array.Copy(p.Data, 4, DHClientPublic, 0, 32);
                            Array.Copy(p.Data, 36, AuthRandom, 0, 24);

                            iClient.WorkProven = WorkProof.VerifyProof(iClient.WorkTask, Proof, Constants.Difficulty);

                            if (iClient.WorkProven)
                            {
                                //DisplayUtils.Display("Work Proved", DisplayType.Info);
                                Common.rngCsp.GetBytes(iClient.DHRandomBytes);

                                iClient.DHPrivateKey = Curve25519.ClampPrivateKey(iClient.DHRandomBytes);
                                iClient.DHPublicKey = Curve25519.GetPublicKey(iClient.DHPrivateKey);

                                // Generate the shared-secret using the provided client Public Key
                                byte[] sharedSecret = (new SHA512Managed()).ComputeHash(Curve25519.GetSharedSecret(iClient.DHPrivateKey, DHClientPublic));

                                Array.Copy(sharedSecret, iClient.TransportKey, 32);
                                Array.Copy(sharedSecret, 32, iClient.AuthenticationKey, 0, 32);

                                // Sign the data using the Node-Private key, so that the client can know that the connection is secure.
                                // This thwarts MITM attacks.
                                byte[] Client_ServerAuthSignature = nodeConfig.SignDataWithPrivateKey(AuthRandom);

                                // 64 bytes Signature
                                byte[] signPlain = Client_ServerAuthSignature;

                                if (signPlain.Length != 64) throw new Exception("Improbable Assertion failed : 1");

                                // Encrypt the Signature and Identifier using Salsa20
                                byte[] signCrypted = Salsa20.ProcessSalsa20(signPlain, iClient.TransportKey, new byte[8], 0);

                                // EtM -> Encrypt then MAC
                                byte[] signMAC = (new HMACSHA256(iClient.AuthenticationKey)).ComputeHash(signCrypted);

                                // SERVER_PUBLIC[32] || signMAC[32] || signCrypted[64] => 128 bytes
                                byte[] KeysSignature = iClient.DHPublicKey.Concat(signMAC).Concat(signCrypted).ToArray();

                                await PacketSender.SendTransportPacket(writer, TransportPacketType.ServerPublicTransfer, KeysSignature);
                            }
                            else
                            {
                                DisplayUtils.Display("Work Proof invalid : " + p.Data.Length, DisplayType.Exception);
                                await PacketSender.SendTransportPacket(writer, TransportPacketType.InvalidAuthDisconnect, new byte[0]);
                            }
                        }
                        else
                        {
                            DisplayUtils.Display("Invalid Packet Length : " + p.Data.Length, DisplayType.Exception);
                            await PacketSender.SendTransportPacket(writer, TransportPacketType.InvalidAuthDisconnect, new byte[0]);
                        }
                    }

                    break;

                case TransportPacketType.KeyExComplete_1:

                    if ((iClient.WorkProven) && (!iClient.KeyExchanged))
                    {
                        if (p.Data.Length == 128)
                        {
                            // cryptedSigPK_MAC[32] || cryptedSigPK[96] = 128 bytes

                            byte[] cryptedSigPK_MAC = new byte[32];
                            byte[] cryptedSigPK = new byte[96];

                            Array.Copy(p.Data, 0, cryptedSigPK_MAC, 0, 32);
                            Array.Copy(p.Data, 32, cryptedSigPK, 0, 96);

                            byte[] cryptedSigPK_MAC_Expected = (new HMACSHA256(iClient.AuthenticationKey)).ComputeHash(cryptedSigPK);

                            if (CryptoBytes.ConstantTimeEquals(cryptedSigPK_MAC_Expected, cryptedSigPK_MAC))
                            {
                                byte[] workSignPK = Salsa20.ProcessSalsa20(cryptedSigPK, iClient.TransportKey, new byte[8], 0);

                                // workSignPK[96]  = workSign[64] || nodeConfig.PublicKey[32]

                                byte[] workSign = new byte[64];
                                byte[] remotePK = new byte[32];

                                Array.Copy(workSignPK, 0, workSign, 0, 64);
                                Array.Copy(workSignPK, 64, remotePK, 0, 32);

                                bool serverVerified = Ed25519.Verify(workSign, iClient.WorkTask, remotePK);

                                if (serverVerified)
                                {
                                    iClient.PublicKey = new Hash(remotePK);

                                    if (Constants.NetworkVerbosity >= Verbosity.Info)
                                    {
                                        /*DisplayUtils.Display(NodeSocketData.GetString(nodeSocketData) + " : Key Exchanged 1: Shared KEY [TransportKey] : {" +
                                            (HexUtil.ToString(TransportKey)) + "}", DisplayType.Info);*/

                                        DisplayUtils.Display(iClient.PublicKey.ToString() + " Client Authenticated", DisplayType.Info);
                                    }

                                    await PacketSender.SendTransportPacket(writer, TransportPacketType.KeyExComplete_2, new byte[0]);

                                    iClient.KeyExchanged = true;

                                    IncomingConnections.Add(iClient.PublicKey, iClient);

                                    DisplayUtils.Display("Exchange Complete 2, Shared KEY [TransportKey] : " + HexUtil.ToString(iClient.TransportKey), DisplayType.Info);

                                }
                            }
                        }
                    }

                    break;

                case TransportPacketType.DataCrypted:

                    if (iClient.KeyExchanged && p.Data.Length > 28)
                    {
                        Constants.SERVER_GLOBAL_DATA_PACKETS++;

                        byte[] nonce = new byte[8];
                        byte[] hmac = new byte[16];
                        byte[] crypted_data = new byte[p.Data.Length - 24];

                        Array.Copy(p.Data, 0, nonce, 0, 8);
                        Array.Copy(p.Data, 8, hmac, 0, 16);
                        Array.Copy(p.Data, 24, crypted_data, 0, crypted_data.Length);

                        byte[] MAC_EXPECTED = (new HMACSHA256(iClient.AuthenticationKey)).ComputeHash(crypted_data).Take(16).ToArray();

                        if (CryptoBytes.ConstantTimeEquals(MAC_EXPECTED, hmac))
                        {
                            byte[] DeCryptedData = Salsa20.ProcessSalsa20(crypted_data, iClient.TransportKey, nonce, 0);

                            byte[] counter = new byte[4];
                            byte[] rec_data = new byte[p.Data.Length - 28];

                            Array.Copy(DeCryptedData, 0, counter, 0, 4);
                            Array.Copy(DeCryptedData, 4, rec_data, 0, rec_data.Length);

                            Array.Copy(DeCryptedData, 0, counter, 0, 4);
                            Array.Copy(DeCryptedData, 4, rec_data, 0, rec_data.Length);

                            NetworkPacket np = new NetworkPacket();

                            np.Deserialize(rec_data);

                            if (iClient.PublicKey == np.PublicKeySource)
                            {
                                if (PacketReceived != null)
                                    PacketReceived(np);
                            }
                            else
                            {
                                DisplayUtils.Display("Packet Source Incoming Mismatch", DisplayType.Warning);
                            }

                        }
                        else
                        {
                            DisplayUtils.Display("HMAC FAILED : ");
                        }
                    }

                    break;
            }
        }