Esempio n. 1
0
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="parent">Parent view model</param>
            public Abort(TransferProgress parent)
            {
                Parent = parent;

                CanExecuteChanged?.Invoke(this, EventArgs.Empty);
            }
Esempio n. 2
0
        /// <summary>
        /// Actually do stuff
        /// </summary>
        /// <param name="UseExistingProgress">If a new progress bar should be created</param>
        private void Work(bool UseExistingProgress = false)
        {
            if (!UseExistingProgress)
            {
                Progress = new TransferProgress
                {
                    UserName    = Receiver.Name,
                    UserPicture = Receiver.PicBytes,
                    FromOrTo    = "to",
                    Parent      = this
                };

                //  Add new Progress Bar
                Application.Current.Dispatcher.Invoke(() =>
                {
                    ((ObservableCollection <TransferProgress>)Application.Current.Properties["TransferProgresses"]).Insert(0, Progress);
                });
            }

            //  Check the file
            if (!GetFileData())
            {
                return;
            }

            //  Update the progress bar with the new data just obtained
            Progress.FileName = FileName;
            Progress.Maximum  = FileSize;

            //  Don't even start transferring if user already cancelled
            if (!MainCancellationToken.IsCancellationRequested)
            {
                //  Set up the cancellation token
                AbortTransfer = new CancellationTokenSource();

                //  Send File data
                Response response = SendHello();
                if (response != Response.ACCEPTED)
                {
                    if (response == Response.REJECTED)
                    {
                        StopSending = true;
                    }

                    Progress.CurrentActivity = "Request rejected";
                    Progress.IsError         = true;
                    return;
                }

                if (AbortTransfer.Token.IsCancellationRequested)
                {
                    Progress.CurrentActivity = "Operation Cancelled.";
                    Progress.IsError         = true;

                    //  Useless, but just to keep things clean
                    StopSending = true;
                    return;
                }

                //  If the main token (the one thrown by the main application) requests cancellation,
                //  then cancel the trasfer too.
                using (CancellationTokenRegistration ctr = MainCancellationToken.Register(() => Cancel()))
                {
                    //------------------------------------
                    //  Load the file
                    //------------------------------------

                    Loader = Task.Run(() => { Load(); }, AbortTransfer.Token);

                    //------------------------------------
                    //  Send the file
                    //------------------------------------

                    Sender = Task.Run(() => { Transmit(); }, AbortTransfer.Token);

                    Progress.CurrentActivity = "Transferring...";

                    //  Wait for them to finish (Or that the user cancels them).
                    //  NOTE: I can't wrap the Task definition in using(),
                    //  because I need to wait for them to finish! I can't dispose them earlier!
                    Sender.Wait();
                    Loader.Wait();

                    //  Dispose the tasks
                    Sender.Dispose();
                    Loader.Dispose();

                    if (!Progress.IsError)
                    {
                        Progress.CurrentActivity = "Transfer completed";
                        Progress.TextColor       = "Green";
                    }
                }

                //  Dispose it;
                AbortTransfer.Dispose();

                //  Clean up
                //  If you're here, it means that the sender and loader have exited, so no need to lock.
                Buffer.Clear();
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Parse the connection request
        /// </summary>
        /// <returns>True if request is valid, false if not.</returns>
        /// <remarks>I should change this method, making it throw exceptions when something happens instead of
        /// return bool. Remember this.</remarks>
        public bool ParseHello()
        {
            //------------------------------------
            //  Init
            //------------------------------------

            int length = 0,
                i      = 0;

            byte[] buffer;

            try
            {
                //  NOTE: I have no guarantees that I will read as much as I specified.
                //  In the first implementation, I was just doing something like Stream.Read(buffer,0,n),
                //  ignoring the fact that I could read less than n, trusting the fact that I was reading small data.
                //  Now, I am doing it like this to prevent such cases in which I read less than how much specified
                Debug.WriteLine("------------------------");
                Stream.ReadTimeout = 5 * 1000;

                //------------------------------------
                //  The type of message
                //------------------------------------

                //  Get the message
                buffer = new byte[5];
                while (i < 5)
                {
                    i += Stream.Read(buffer, 0, 5 - i);
                }

                Debug.WriteLine("Received {0}", Encoding.UTF8.GetString(buffer));

                //  Parse the message type
                string MessageType = Encoding.UTF8.GetString(buffer);

                //  ENDOC means that I don't want to send you anything else (= End the connection),
                //  so the return true is useless
                if (MessageType.Equals("ENDOC"))
                {
                    //  Did I receive a ENDOC as very first message?
                    if (StopReceiving)
                    {
                        return(false);
                    }
                    StopReceiving = true;
                    return(true);

                    /**
                     * SECURITY IMPLICATIONS
                     *
                     * If an attacker spoofs their IP addres and sends ENDOC as very first message, this will
                     * stop the communication even before starting it. This is because this is not an authenticated protocol.
                     *
                     * POSSIBILE SOLUTIONS
                     *
                     * The ones listed in the HELLO below
                     **/
                }

                //  If is not ENDOC and not even HELLO, then discard the packet.
                //  NOTE: the first time, when this return false, the communication will be instantly ended.
                //  But if you're sending a list of files, this will tell the sender to proceed with next file.
                if (!MessageType.Equals("HELLO"))
                {
                    return(false);
                }

                int isprivate = Stream.ReadByte();
                if (isprivate == -1)
                {
                    StopReceiving = true;
                    return(true);
                }

                //  User is not private, but do I know who this is?
                if (((byte)isprivate).Equals(1))
                {
                    IPAddress ip    = ((IPEndPoint)Client.Client.RemoteEndPoint).Address;
                    bool      found = false;
                    ObservableCollection <User> users = (ObservableCollection <User>)Application.Current.Properties["Users"];
                    foreach (User u in users)
                    {
                        Debug.WriteLine("IP from remote endpoint: {0}, IP to check {1}", ip, u.IP);
                        if (u.IP.Equals(ip))
                        {
                            found      = true;
                            SenderUser = new User(u);
                            break;
                        }
                    }

                    //  Don't accept transfer if I don't know who this is.
                    //  But what about private users? I don't know who they are either!
                    //  Well, software's requirements say that private users don't communicate their existence,
                    //  but can still send, so...
                    if (found == false)
                    {
                        Progress.CurrentActivity = "User not found";
                        Progress.IsError         = true;
                        StopReceiving            = true;
                        return(false);
                    }
                }
                else
                {
                    if (((byte)isprivate).Equals(0))
                    {
                        SenderUser = null;
                    }
                    else
                    {
                        Progress.CurrentActivity = "Invalid request";
                        Progress.IsError         = true;

                        //  I don't understand your message...
                        StopReceiving = true;
                        return(false);
                    }
                }

                //------------------------------------
                //  The file name
                //------------------------------------

                //  Get its length first
                //  At first, I used the set a fixed length of 200 bytes for file name,
                //  but wasn't sure if it would play nice with UNICODE. So I made it TLV-Style
                buffer = new byte[4];
                i      = 0;
                while (i < 4)
                {
                    i += Stream.Read(buffer, 0, 4 - i);
                }
                length = BitConverter.ToInt32(buffer, 0);

                //  Name of files can be like: "file", "folder1/file", "folder1/folder2/file"
                //  So, it must be at least one byte long
                if (length < 2)
                {
                    return(false);
                }

                //  Now get the name
                buffer = new byte[length];
                i      = 0;
                while (i < length)
                {
                    i += Stream.Read(buffer, 0, length - i);
                }
                FileName = Encoding.Unicode.GetString(buffer).Trim('/').Trim('\0');
                if (FileName.Length - FileName.Replace("/", "").Length > 0)
                {
                    IsFolder = true;
                }

                Debug.WriteLine("Filename: {0}", FileName);
                //  Was wondering if there was a better method to count occurrences in a string than just looping it c-style.
                //  So I found this:
                //  https://stackoverflow.com/questions/541954/how-would-you-count-occurrences-of-a-string-within-a-string

                //------------------------------------
                //  The file's extension
                //------------------------------------

                //  Get its length
                buffer = new byte[4];
                i      = 0;
                while (i < 4)
                {
                    i += Stream.Read(buffer, 0, 4 - i);
                }
                length = BitConverter.ToInt32(buffer, 0);

                //  Now get the actual extension
                buffer = new byte[length];
                i      = 0;
                while (i < length)
                {
                    i += Stream.Read(buffer, 0, length - i);
                }
                FileExtension = Encoding.Unicode.GetString(buffer).Trim('\0');

                Debug.WriteLine("Extension: {0}", FileExtension);

                //------------------------------------
                //  Get the file size
                //------------------------------------

                buffer = new byte[8];
                i      = 0;
                while (i < 8)
                {
                    i += Stream.Read(buffer, 0, 8 - i);
                }
                FileSize = BitConverter.ToInt64(buffer, 0);

                //  Return true and don't stop receiving, meaning that the request is valid
                StopReceiving = false;

                Progress = new TransferProgress
                {
                    Maximum         = FileSize,
                    FileName        = FileName,
                    UserName        = SenderUser != null ? SenderUser.Name : "Private User",
                    UserPicture     = SenderUser?.PicBytes,
                    FromOrTo        = "from",
                    CurrentActivity = "Parsing Request...",
                    Parent          = this
                };

                //  Add new Progress Bar
                Application.Current.Dispatcher.InvokeAsync(() =>
                {
                    ((ObservableCollection <TransferProgress>)Application.Current.Properties["TransferProgresses"]).Insert(0, Progress);
                });
                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Start transferring
        /// </summary>
        public override void Start()
        {
            //  Before getting here, are there any errors?
            if (SendType == PathType.UKNOWN)
            {
                return;
            }

            Worker = Task.Run(() =>
            {
                Progress = new TransferProgress
                {
                    UserName    = Receiver.Name,
                    UserPicture = Receiver.PicBytes,
                    FromOrTo    = "to",
                    Parent      = this
                };

                //  Add new Progress Bar
                Application.Current.Dispatcher.Invoke(() =>
                {
                    ((ObservableCollection <TransferProgress>)Application.Current.Properties["TransferProgresses"]).Insert(0, Progress);
                });

                using (Client = new TcpClient(AddressFamily.InterNetworkV6))
                {
                    //------------------------------------
                    //  Try To Connect
                    //------------------------------------

                    if (!Connect())
                    {
                        //  Set Error Message as not responding
                        return;
                    }

                    //------------------------------------
                    //  Send the "Hello" message
                    //------------------------------------

                    using (Stream = Client.GetStream())
                    {
                        Stream.Flush();

                        //  At this point, I have already notified the receiver that I'm goin to send a directory.
                        //  So from now on, I'm going to send files, not directories
                        SendType = PathType.FILE;

                        //  Tells if you need to create a new progress bar
                        //  The first time, you won't have to, but for subsequent files yes you do.
                        bool _progress = true;

                        //  Loop through the files
                        foreach (string file in Files)
                        {
                            FilePath = file;
                            Work(_progress);

                            _progress = false;
                            if (StopSending)
                            {
                                break;
                            }
                        }

                        Stop();
                    }   //  Dispose the stream

                    Client.Close();
                }   //  Dispose the client
            });

            Worker.Wait();
            Worker.Dispose();
            Worker = null;
        }