Exemple #1
0
 /// <summary>
 /// Cancel the task
 /// </summary>
 public override void Cancel()
 {
     if (AbortTransfer != null)
     {
         AbortTransfer.Cancel();
     }
     StopReceiving = true;
 }
Exemple #2
0
 /// <summary>
 /// Reject the transfer
 /// </summary>
 /// <param name="RejectAll">If I have to stop the thread</param>
 public void Reject(bool RejectAll = false)
 {
     try
     {
         byte[] response = Encoding.UTF8.GetBytes("KO");
         Stream.Write(response, 0, response.Length);
     }
     catch (Exception)
     {
         AbortTransfer.Cancel();
         /*if (RejectAll) */ StopReceiving = true;
         return;
     }
 }
Exemple #3
0
        /// <summary>
        /// Cancel current transfer
        /// </summary>
        public override void Cancel()
        {
            lock (Buffer)
            {
                //  Have to wake up who might be sleeping
                Monitor.PulseAll(Buffer);

                //  I put Cancel here, so that if the loader or sender are waiting for the lock,
                //  I am sure that they will get the cancellation when they get the lock
                //  NOTE: I may have been called *BEFORE* even starting the sender and the loader,
                //  that's why I am checking for null. No worries for Monitor.PulseAll, because it won't wake anyone.
                if (AbortTransfer != null)
                {
                    AbortTransfer.Cancel();
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Send the file
        /// </summary>
        private void Transmit()
        {
            //------------------------------------
            //  Init
            //------------------------------------

            long written = 0;

            //------------------------------------
            //  Get the file data
            //------------------------------------

            Progress.CurrentActivity = "Transferring file...";

            while (written < FileSize && !AbortTransfer.IsCancellationRequested)
            {
                //  How much should I write
                int    get  = (int)(FileSize - written < 4096 ? (FileSize - written) : 4096);
                byte[] data = new byte[get];

                //  Try to acquire the buffer. I can't write if nothing's there to write yet, man.
                lock (Buffer)
                {
                    if (Buffer.Count == 0)
                    {
                        /**
                         * Read considerations I wrote for Monitor.Wait in Loader's code
                         **/
                        if (!AbortTransfer.Token.IsCancellationRequested)
                        {
                            Monitor.Wait(Buffer);
                        }

                        //  Did you wake me up because there's data or because we have to exit?
                        //  Doing break, so it gracefully exits the method
                        if (AbortTransfer.Token.IsCancellationRequested)
                        {
                            break;
                        }
                    }

                    data = Buffer.Dequeue();

                    //  Wake up the sender if it was waiting for a dequeue
                    Monitor.Pulse(Buffer);
                }

                //------------------------------------
                //  Send data
                //------------------------------------

                try
                {
                    //  Send data
                    Task w = Stream.WriteAsync(data, 0, data.Length);

                    //  I really need the result now. Don't want to send packets out of order.
                    w.Wait(AbortTransfer.Token);
                    w.Dispose();

                    //  Update written count
                    written            += get;
                    Progress.Completion = written;
                }
                catch (Exception e)
                {
                    lock (Buffer)
                    {
                        //  I have to notify the Loader that I couldn't write!
                        //  Read the considerations in the Loader.

                        Monitor.Pulse(Buffer);

                        //  Cancel the loader.
                        AbortTransfer.Cancel();

                        if (e is SocketException)
                        {
                            Progress.CurrentActivity = "Socket has been closed";
                        }
                        else
                        {
                            if (e is OperationCanceledException)
                            {
                                Progress.CurrentActivity = "Operation cancelled";
                            }
                            else
                            {
                                Progress.CurrentActivity = "The other peer cancelled the operation";
                            }
                        }

                        Progress.IsError = true;
                        StopSending      = true;
                    }
                }
            }

            //  Send Digest
            if (written == FileSize && !AbortTransfer.Token.IsCancellationRequested)
            {
                lock (this)
                {
                    if (AbortTransfer.Token.IsCancellationRequested)
                    {
                        return;
                    }
                    if (Buffer.Count == 0)
                    {
                        Monitor.Wait(this);
                    }
                    if (AbortTransfer.Token.IsCancellationRequested)
                    {
                        return;
                    }

                    byte[] Digest = Buffer.Dequeue();

                    using (Task t = Stream.WriteAsync(Digest, 0, 32))
                    {
                        t.Wait(AbortTransfer.Token);
                    }
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Load bytes from the disk
        /// </summary>
        private void Load()
        {
            //------------------------------------
            //  Init
            //------------------------------------

            long read = 0;

            //  https://stackoverflow.com/questions/34325034/how-do-i-cancel-a-filestream-readasync-request/34325233#34325233
            //  If no IsAsync is specified, readasync does not really implement cancellation.
            //  NOTE: I started the project with the name FileShare, without knowing it was included in System.IO...
            using (FileStream file = new FileStream(FilePath, FileMode.Open, FileAccess.Read, System.IO.FileShare.Read, 4096))
            {
                //------------------------------------
                //  Load data
                //------------------------------------
                while (read < FileSize && !AbortTransfer.Token.IsCancellationRequested)
                {
                    //  How many bytes you should read
                    //  Casted to int as the maximum will always be 4096, which is the defaults size of Read btw
                    int    get   = (int)(FileSize - read < 4096 ? (FileSize - read) : 4096);
                    byte[] _data = new byte[get];
                    byte[] data;
                    int    _read = 0;

                    try
                    {
                        //  Actually load data
                        //  It seems that the overload ReadAsync(byte[], int32, int32, CancellationToken)
                        //  doesn't really support cancellation. So I made it with a Wait(CancellationToken)
                        using (Task <int> r = file.ReadAsync(_data, 0, get))
                        {
                            r.Wait(AbortTransfer.Token);
                            //  Completed?
                            _read = r.Result;

                            //  As per documentation, ReadAsync reads 0 bytes if EOF is reached,
                            //  I'm checking it anyway...
                            if (_read == 0)
                            {
                                throw new EndOfStreamException();
                            }
                            data = new byte[_read];
                            Array.Copy(_data, data, _read);
                        }
                    }
                    catch (Exception)
                    {
                        //  Notify the Sender that we must exit
                        lock (Buffer)
                        {
                            //  If you're here, it means that you were able to get the lock either
                            //  because the Sender is sending or because it's sleeping.
                            //  In the latter case I *MUST* tell it to wake up and exit
                            Monitor.Pulse(Buffer);

                            //  Set the cancellation token.
                            //  I *MUST* set the cancellation token *WHILE* still in lock,
                            //  so that i can cancel the operation while the sender is still blocked,
                            //  ensuring that it will catch the cancellation.
                            AbortTransfer.Cancel();
                        }

                        return;
                    }

                    //------------------------------------
                    //  Store data on buffer
                    //------------------------------------

                    lock (Buffer)
                    {
                        //  I only allow a maximum number of 5 elements,
                        //  so the >= is useless here.
                        if (Buffer.Count >= 5)
                        {
                            /**
                             * Note: I have to wrap Monitor.Wait in two if(Token.CancellationRequested)
                             * because I have to check if task has been cancelled!.
                             * The first one is because user might have interrupted it OR the sender had an exception.
                             * The second one is to check if I have been awoken because there is data OR I have to quit.
                             **/

                            if (!AbortTransfer.Token.IsCancellationRequested)
                            {
                                Monitor.Wait(Buffer);
                            }

                            //  Did you wake me up because there's data or because we have to exit?
                            //  Doing break, so it gracefully exits the loop
                            if (AbortTransfer.Token.IsCancellationRequested)
                            {
                                break;
                            }
                        }

                        //  Put data into buffer
                        Buffer.Enqueue(data);

                        //  Wake up the Sender if it was sleeping (which is probably so the first time)
                        Monitor.Pulse(Buffer);
                    }

                    //  Update how many data I have sent
                    read += _read;
                }

                //------------------------------------
                //  Send Digest
                //------------------------------------

                if (read == FileSize && !AbortTransfer.Token.IsCancellationRequested)
                {
                    ComputeDigest(file);
                }
            }
        }