예제 #1
0
        private void ReceiveItem()
        {
            CommunicationResult res;


            // Receive item info
            int length = 1 + 8 + 1024;

            if (clientEncryptor != null)
            {
                length = DataEncryptor.PredictAESLength(length);
            }
            res = TryRead(clientIpPort, length, true);

            if (!(res.Instruction == TTInstruction.Transfer_FileInfo || res.Instruction == TTInstruction.Transfer_FolderInfo))
            {
                throw new FailedReceivingException("Client sent unsupported item info.");
            }


            // Receive item
            long   size     = BitConverter.ToInt64(res.Data, 0);
            string fullName = Encoding.UTF8.GetString(res.Data, 8, 512 - 9).Replace("\0", string.Empty);

            if (res.Instruction == TTInstruction.Transfer_FileInfo)
            {
                ReceiveFile(fullName, size);
            }
            else
            {
                ReceiveFolder(fullName);
            };
        }
예제 #2
0
        public void TerminateConnection()
        {
            if (terminatingConnection || client == null)
            {
                return;
            }


            terminatingConnection = true;


            // TODO Cancellation token for sending


            if (client != null)
            {
                client.Disconnect();
                client = null;
            }

            serverEncryptor = null;
            serverDevice    = null;

            OnRecordableEvent("Connection terminated.", Console.ConsoleMessageType.Common);
            terminatingConnection = false;
        }
예제 #3
0
        private void TerminateConnection(string ipPort)
        {
            if (ipPort == "")
            {
                return;
            }


            // TODO Cancellation token for receiving


            if (server.GetClients().Contains(ipPort))
            {
                server.DisconnectClient(ipPort);
            }

            if (clientIpPort == ipPort)
            {
                clientIpPort    = "";
                clientDevice    = null;
                clientEncryptor = null;

                OnRecordableEvent("Connection terminated.", Console.ConsoleMessageType.Common);
            }
        }
예제 #4
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);
            });
        }
예제 #5
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);
            });
        }
예제 #6
0
        private void ReceiveFile(string fullName, long size)
        {
            string fileName = fullName;
            int    idx      = fullName.LastIndexOf('\\');

            if (idx != -1)
            {
                fileName = fullName.Substring(idx + 1);
            }


            // Receive
            long bytesToReceive           = size;
            bool useEncryption            = clientEncryptor != null;
            TransferProgressReport report = new TransferProgressReport();

            report.TotalBytes   = totalBytes;
            report.ActiveItem   = fileName;
            report.CurrentBytes = 0;
            report.IsSender     = false;
            transferProgress.Report(report);
            using (FileStream fs = File.Create($"{saveLocation}\\{fullName}"))
            {
                ReadResult result;
                int        bufferSize = 0;
                while (bytesToReceive > 0)
                {
                    try
                    {
                        bufferSize = (int)Math.Min(bytesToReceive, maxBufferSize);
                        byte[] receivedBuffer = null;
                        if (useEncryption)
                        {
                            result         = server.Read(clientIpPort, DataEncryptor.PredictAESLength(bufferSize));
                            receivedBuffer = clientEncryptor.AESDecryptBytes(result.Data);
                        }
                        else
                        {
                            result         = server.Read(clientIpPort, bufferSize);
                            receivedBuffer = result.Data;
                        }


                        if (result.Status != ReadResultStatus.Success)
                        {
                            fs.Flush();
                            throw new Exception("Did not receive data in time.");
                        }


                        fs.Write(receivedBuffer, 0, bufferSize);
                    }
                    catch (Exception e)
                    {
                        fs.Flush();
                        throw new FailedReceivingException($"Failed while receiving '{fileName}' ({e.Message}).");
                    }


                    bytesToReceive -= bufferSize;
                    bytesReceived  += bufferSize;


                    if (bytesReceived >= report.CurrentBytes + (totalBytes / 100) || bytesToReceive == 0)
                    {
                        report.CurrentBytes = bytesReceived;
                        transferProgress.Report(report);
                    }
                }
                fs.Flush();
            }
        }
예제 #7
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);
            });
        }