private void PresenceHelloSend()
        {
            byte[] buffer;
            TTNet.GeneratePresenceBuffer(MacAddress, out buffer, TTInstruction.Discovery_Hello, Settings.SettingsData.Name, DeviceType);

            socketUDP.SendTo(buffer, PresenceEndPoint);
        }
        private void PresenceByeSend()
        {
            byte[] buffer;
            TTNet.GeneratePresenceBuffer(MacAddress, out buffer, TTInstruction.Discovery_Bye);

            socketUDP.SendTo(buffer, PresenceEndPoint);
        }
Exemple #3
0
        private CommunicationResult TryRead(string ipPort, int count, bool doEncryption)
        {
            ReadResult result = server.ReadWithTimeout(maxPingMs, ipPort, count);

            TTInstruction ins = TTInstruction.Empty;

            byte[] buffer = null;
            if (result.Status != ReadResultStatus.Success)
            {
                throw new FailedReceivingException($"Did not receive response ({result.Status}).");
            }

            if (doEncryption && clientEncryptor != null)
            {
                buffer = clientEncryptor.AESDecryptBytes(result.Data);
            }
            else
            {
                buffer = result.Data;
            }

            byte[] dat = null;
            if (!TTNet.UnpackTCPBuffer(buffer, ref ins, ref dat))
            {
                throw new FailedReceivingException($"Received invalid response.");
            }

            return(new CommunicationResult(ins, dat));
        }
Exemple #4
0
        private CommunicationResult TryRead(int count, int?overrideTimeoutMs = null)
        {
            int        timeout = overrideTimeoutMs ?? maxPingMs;
            ReadResult result  = client.ReadWithTimeout(timeout, count);

            if (result.Status != ReadResultStatus.Success)
            {
                throw new FailedReceivingException($"Did not receive response ({result.Status}).");
            }

            TTInstruction ins = TTInstruction.Empty;

            byte[] dat = null;
            if (!TTNet.UnpackTCPBuffer(result.Data, ref ins, ref dat))
            {
                throw new FailedReceivingException($"Received invalid response.");
            }

            return(new CommunicationResult(ins, dat));
        }
        private void Grid_Loaded(object sender, RoutedEventArgs e)
        {
            SetSendButtonEnabled(true);

            InitializeNetworkInfo();

            // TCP
            transferServer = new TransferServer(IPAddress, Settings.SettingsData.NetworkTransferPort, Settings.SettingsData.MaxNetworkPingMs, Settings.SettingsData.MaxBufferSize, TransferProgress);
            transferServer.OnRecordableEvent += OnRecordableEvent;
            transferServer.Start();
            transferClient = new TransferClient(Settings.SettingsData.NetworkTransferPort, Settings.SettingsData.MaxNetworkPingMs, Settings.SettingsData.MaxBufferSize, TransferProgress);
            transferClient.OnRecordableEvent += OnRecordableEvent;

            TTNet.GeneratePresenceBuffer(MacAddress, out PresenceBuffer, TTInstruction.Discovery_Present, Settings.SettingsData.Name, DeviceType);
            PresenceTimer                      = new Timer(new TimerCallback(PresenceSend), null, 2000, Settings.SettingsData.PresenceSendPeriod);
            PresenceTimeoutCheckTimer          = new Timer(new TimerCallback(PresenceTimeoutTick), null, Settings.SettingsData.MaxNetworkPingMs, Settings.SettingsData.PresenceTimeoutCheckPeriod);
            presenceReceiveThread              = new Thread(new ThreadStart(PresenceReceiveLoop));
            presenceReceiveThread.IsBackground = true;
            presenceReceiveThread.Start();
            PresenceHelloSend();
        }
        private void PresenceReceiveLoop()
        {
            IPEndPoint remoteIpEndPoint;
            PhysicalAddressSerializable remoteMac;
            TTInstruction instruction;
            List <byte>   data;


            while (true)
            {
                remoteIpEndPoint = null;
                remoteMac        = null;
                instruction      = TTInstruction.Empty;
                data             = null;

                if (TTNet.UnpackBuffer(clientUDP.Receive(ref remoteIpEndPoint), ref remoteMac, ref instruction, ref data))
                {
                    //OnRecordableEvent($"Received presence from: {remoteIpEndPoint.Address.ToString()}", Console.ConsoleMessageType.Common);

                    // Skip if from self
                    if (remoteIpEndPoint.Address.ToString() == IPAddress.ToString())
                    {
                        continue;
                    }

                    // Add or update device in saved list
                    if (instruction == TTInstruction.Discovery_Hello || instruction == TTInstruction.Discovery_Present)
                    {
                        if (!Enum.IsDefined(typeof(DeviceType), (int)data[0]))
                        {
                            continue;
                        }

                        DeviceType deviceType = (DeviceType)data[0];
                        string     deviceName = Encoding.UTF8.GetString(data.GetRange(1, data.Count - 1).ToArray());

                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            Settings.SettingsData.AddUpdateDevice(remoteMac, deviceName, remoteIpEndPoint.Address, deviceType);
                        });
                    }

                    // Keep track of online status
                    switch (instruction)
                    {
                    case TTInstruction.Discovery_Hello:
                        OnlineDevices.SetOnline(remoteMac);
                        PresenceSend(null);
                        break;

                    case TTInstruction.Discovery_Present:
                        OnlineDevices.SetOnline(remoteMac);
                        break;

                    case TTInstruction.Discovery_Bye:
                        OnlineDevices.SetOffline(remoteMac);
                        break;
                    }
                }
            }
        }
        // General
        private void InitializeNetworkInfo()
        {
            IPAddress internetIp;

            using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
            {
                socket.Connect("8.8.8.8", 65530);
                IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
                internetIp = endPoint.Address;
            }


            // Mac - this will either select the interface based on the selected mac address or the interface which will connect to internet
            MacAddress = null;

            PhysicalAddress backupMac  = null;
            IPAddress       backupIp   = null;
            IPAddress       backupMask = null;

            var nics = TTNet.GetUsableNetworkInterfaces();

            foreach (NetworkInterface nic in nics)
            {
                var       interNetwork  = nic.GetIPProperties().UnicastAddresses.Where(u => u.Address.AddressFamily == AddressFamily.InterNetwork);
                IPAddress interfaceIp   = interNetwork.Select(u => u.Address).FirstOrDefault();
                IPAddress interfaceMask = interNetwork.Select(u => u.IPv4Mask).FirstOrDefault();
                if (interfaceIp == null)
                {
                    continue;
                }
                PhysicalAddress interfaceMac = nic.GetPhysicalAddress();

                if (Settings.SettingsData.InterfaceMac != null && Settings.SettingsData.InterfaceMac.Equals(interfaceMac))
                {
                    MacAddress = interfaceMac;
                    IPAddress  = interfaceIp;
                    IPMask     = interfaceMask;
                    break;
                }

                if (interfaceIp.ToString() == internetIp.ToString())
                {
                    backupMac  = interfaceMac;
                    backupIp   = interfaceIp;
                    backupMask = interfaceMask;
                }
            }

            // If interface with selected mac doesn't exist, select the one which connect to internet
            if (MacAddress == null)
            {
                if (backupMac != null)
                {
                    MacAddress = backupMac;
                    IPAddress  = internetIp;
                    IPMask     = backupMask;
                    Settings.SettingsData.InterfaceMac = MacAddress;
                }
                else
                {
                    throw new Exception("Could not find a usable network interface.");
                }
            }

            // Broadcast endpoint
            PresenceEndPoint = new IPEndPoint(TTNet.GetBroadcastAddress(IPAddress, IPMask), Settings.SettingsData.NetworkPresencePort);
        }
Exemple #8
0
        // Data
        private async Task SendData()
        {
            transferStopwatch = new Stopwatch();
            transferStopwatch.Start();
            int totalItemCount = 0;
            await Task.Run(() =>
            {
                // Send files info
                byte[] infoBuffer = new byte[13];
                infoBuffer[0]     = (byte)TTInstruction.Transfer_TransferInfo;

                totalItemCount = items.Count();
                foreach (var item in items)
                {
                    totalItemCount += item.GetTotalChildCount();
                }
                byte[] countBytes = BitConverter.GetBytes(totalItemCount);
                Array.Copy(countBytes, 0, infoBuffer, 1, 4);

                long totalSize = 0;
                foreach (var item in items)
                {
                    totalSize += item.GetTotalSize();
                }
                byte[] sizeBytes = BitConverter.GetBytes(totalSize);
                Array.Copy(sizeBytes, 0, infoBuffer, 1 + 4, 8);

                TrySend(infoBuffer, true);


                // Send data
                bytesSent  = 0;
                totalBytes = totalSize;
                foreach (var item in items)
                {
                    if (item.IsFolder)
                    {
                        SendFolder(item, "");
                    }
                    else
                    {
                        SendFile(item, "");
                    }
                }
            });


            transferStopwatch.Stop();
            OnRecordableEvent($"Sucessfully sent {totalItemCount} item/s ({ExplorerControl.FormatFileSize(bytesSent)}) in {TTNet.FormatTimeSpan(transferStopwatch.Elapsed)} at average { ExplorerControl.FormatFileSize(totalBytes * 1000 / transferStopwatch.ElapsedMilliseconds)}/s.", Console.ConsoleMessageType.Common);
        }
Exemple #9
0
        private async Task EstablishConnection()
        {
            await Task.Run(() =>
            {
                CommunicationResult res = null;
                byte[] buffer           = null;


                // Deny, accept, or askpass
                res = TryRead(1, maxPingMs + Settings.SettingsData.MaxPermissionAskWaitMs);


                // Denied
                switch (res.Instruction)
                {
                case TTInstruction.Connection_RefuseBusy:
                    throw new FailedConnectingException($"Connection to {serverDevice.Name} failed because it's busy right now.");


                case TTInstruction.Connection_RefuseDeny:
                    throw new FailedConnectingException($"Connection to {serverDevice.Name} failed because it hasn't allowed you to send them files.");
                }


                // Encryption
                DataEncryptor encryptor = null;
                if (serverDevice.EncryptionEnabled)
                {
                    // Check if server also has password set
                    if (res.Instruction != TTInstruction.Connection_AskPass)
                    {
                        TrySend(new byte[] { (byte)TTInstruction.Connection_RefusePass }, false);
                        throw new FailedConnectingException($"Connection to {serverDevice.Name} refused because you have set a password and it has none.");
                    }


                    // Send password
                    encryptor           = new DataEncryptor(serverDevice.EncryptionPassword);
                    byte[] timePassword = TTNet.GenerateTimePasswordBytes();
                    buffer = new byte[1] {
                        (byte)TTInstruction.Connection_SendPass
                    }.ToList().Concat(encryptor.AESEncryptBytes(timePassword)).ToArray();
                    TrySend(buffer, false);


                    // Receive password response
                    res = TryRead(1);
                    if (res.Instruction != TTInstruction.Connection_AcceptPass)
                    {
                        throw new FailedConnectingException($"Connection to {serverDevice.Name} failed because you do not have the right password.");
                    }


                    // Receive password
                    try
                    {
                        res = TryRead(TTNet.TimePasswordLength + 1);
                    }
                    catch (Exception e)
                    {
                        OnRecordableEvent("Caught " + e.Message, Console.ConsoleMessageType.Error);
                        throw new Exception();
                    }



                    // Check password
                    byte[] receivedTimePassword = encryptor.AESDecryptBytes(res.Data);
                    if (Enumerable.SequenceEqual(timePassword, receivedTimePassword) || !TTNet.CheckTimePasswordValid(receivedTimePassword, serverDevice, maxPingMs))
                    {
                        // TODO Send RefusePass to server
                        throw new FailedConnectingException($"Connection to {serverDevice.Name} refused because it did not have the correct password.");
                    }
                }
                else
                {
                    // Check if server also doesn't use password
                    if (res.Instruction != TTInstruction.Connection_Accept)
                    {
                        TrySend(new byte[] { (byte)TTInstruction.Connection_RefuseDeny }, false); // TODO Doesn't work, server doesn't recognize this scenario
                        throw new FailedConnectingException($"Connection to {serverDevice.Name} failed because it requires a password and none is set.");
                    }
                }


                // Send connection accept
                TrySend(new byte[] { (byte)TTInstruction.Connection_Accept }, false);


                serverEncryptor = encryptor;
                OnRecordableEvent($"Established { (serverDevice.EncryptionEnabled ? "secure " : "")}connection with {serverDevice.Name}.", Console.ConsoleMessageType.Common);
            });
        }
Exemple #10
0
        // Data
        private async Task ReceiveData()
        {
            transferStopwatch = new Stopwatch();
            transferStopwatch.Start();
            await Task.Run(() =>
            {
                // Receive info about transfer
                int length = 13;
                if (clientEncryptor != null)
                {
                    length = DataEncryptor.PredictAESLength(length);
                }
                CommunicationResult res = TryRead(clientIpPort, length, true);


                // Receive data
                int itemCount = 0;
                if (res.Instruction == TTInstruction.Transfer_TransferInfo)
                {
                    // Receive files individually
                    itemCount  = BitConverter.ToInt32(res.Data, 0);
                    totalBytes = BitConverter.ToInt64(res.Data, 4);

                    for (int i = 0; i < itemCount; i++)
                    {
                        ReceiveItem();
                    }
                }
                else
                {
                    throw new FailedReceivingException("Client sent wrong instruction about transfer.");
                }

                transferStopwatch.Stop();
                OnRecordableEvent($"Sucessfully received {itemCount} item/s ({Explorer.ExplorerControl.FormatFileSize(bytesReceived)}) in {TTNet.FormatTimeSpan(transferStopwatch.Elapsed)} at average { Explorer.ExplorerControl.FormatFileSize(bytesReceived * 1000 / transferStopwatch.ElapsedMilliseconds)}/s.", Console.ConsoleMessageType.Common);
            });
        }
Exemple #11
0
        private async Task EstablishConnection(string ipPort)
        {
            await Task.Run(() =>
            {
                if (ipPort == null || ipPort == "")
                {
                    throw new FailedConnectingException("Wrong IP.");
                }

                string[] ipParts = ipPort.Split(':');
                if (ipParts.Length != 2)
                {
                    throw new FailedConnectingException("Wrong IP.");
                }

                IPAddress deviceIP;
                if (!IPAddress.TryParse(ipParts[0], out deviceIP))
                {
                    throw new FailedConnectingException("Unknown IP.");
                }

                Device remoteDevice = Settings.SettingsData.GetDevice(deviceIP);
                if (remoteDevice == null)
                {
                    throw new FailedConnectingException("Unknown IP.");
                }


                CommunicationResult res = null;
                byte[] buffer           = null;


                // Check busy
                if (IsBusy)
                {
                    TrySend(ipPort, new byte[] { (byte)TTInstruction.Connection_RefuseBusy });
                    throw new FailedConnectingException($"Connection from {remoteDevice.Name} refused because busy.");
                }


                // Check permission
                if (remoteDevice.ReceiveMode == DeviceReceiveMode.Deny)
                {
                    TrySend(ipPort, new byte[] { (byte)TTInstruction.Connection_RefuseDeny });
                    throw new FailedConnectingException($"Connection from {remoteDevice.Name} refused because it's not allowed.");
                }
                if (remoteDevice.ReceiveMode == DeviceReceiveMode.AskEachTime)
                {
                    timer          = new Timer(Settings.SettingsData.MaxPermissionAskWaitMs);
                    timer.Elapsed += Events_TimerPermissionAskTimeout;
                    timer.Start();

                    bool allowed = false;
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        confirmationDialog       = new Settings.ConfirmationDialog("Accept connection?", $"Do you want to accept a connection from '{remoteDevice.Name}'?", "Yes", "No");
                        confirmationDialog.Owner = Application.Current.MainWindow;
                        allowed = confirmationDialog.ShowDialog() ?? false;
                    });
                    timer.Stop();
                    timer.Dispose();
                    if (!allowed)
                    {
                        timer.Stop();
                        timer.Dispose();


                        TrySend(ipPort, new byte[] { (byte)TTInstruction.Connection_RefuseDeny });
                        throw new FailedConnectingException($"Connection from {remoteDevice.Name} refused because you refused it.");
                    }
                }


                // Encryption
                DataEncryptor encryptor = null;
                if (remoteDevice.EncryptionEnabled)
                {
                    encryptor = new DataEncryptor(remoteDevice.EncryptionPassword);


                    // Ask for password
                    TrySend(ipPort, new byte[] { (byte)TTInstruction.Connection_AskPass });


                    // Receive password
                    res = TryRead(ipPort, 1 + TTNet.TimePasswordLength, false);
                    if (res.Instruction != TTInstruction.Connection_SendPass)
                    {
                        if (res.Instruction == TTInstruction.Connection_RefuseDeny)
                        {
                            throw new FailedConnectingException($"Connection from {remoteDevice.Name} refused refused because it did not have a password.");
                        }
                    }


                    // Check password
                    byte[] receivedTimePassword = encryptor.AESDecryptBytes(res.Data);
                    if (!TTNet.CheckTimePasswordValid(receivedTimePassword, remoteDevice, maxPingMs))
                    {
                        TrySend(ipPort, new byte[] { (byte)TTInstruction.Connection_RefusePass });
                        throw new FailedConnectingException($"Connection from {remoteDevice.Name} refused because it did not have the correct password.");
                    }
                    TrySend(ipPort, new byte[] { (byte)TTInstruction.Connection_AcceptPass });


                    // Send password
                    byte[] timePassword = TTNet.GenerateTimePasswordBytes();
                    buffer = new byte[1] {
                        (byte)TTInstruction.Connection_SendPass
                    }.ToList().Concat(encryptor.AESEncryptBytes(timePassword)).ToArray();
                    TrySend(ipPort, buffer);
                }
                else
                {
                    // Send connection accept
                    TrySend(ipPort, new byte[] { (byte)TTInstruction.Connection_Accept });
                }


                // Wait if client accepted connection
                res = TryRead(ipPort, 1, false);
                if (res.Instruction != TTInstruction.Connection_Accept)
                {
                    if (res.Instruction == TTInstruction.Connection_RefusePass)
                    {
                        throw new FailedConnectingException($"Connection from {remoteDevice.Name} refused because it requires a password and none is set.");
                    }
                }


                // Check busy again
                if (IsBusy)
                {
                    TrySend(ipPort, new byte[] { (byte)TTInstruction.Connection_RefuseBusy });
                    throw new FailedConnectingException($"Refused connection from {remoteDevice.Name} because busy.");
                }


                clientDevice    = remoteDevice;
                clientIpPort    = ipPort;
                clientEncryptor = encryptor;
                OnRecordableEvent($"Established { (clientDevice.EncryptionEnabled ? "secure " : "")}connection with {remoteDevice.Name}.", Console.ConsoleMessageType.Common);
            });
        }