public void UploadFileByBlocking(BacnetClient comm, BacnetAddress adr, BacnetObjectId object_id, string filename, Action <int> progress_action)
        {
            Cancel = false;

            //open file
            System.IO.FileStream fs = null;
            try
            {
                fs = System.IO.File.OpenRead(filename);
            }
            catch (Exception ex)
            {
                throw new System.IO.IOException("Couldn't open file", ex);
            }

            try
            {
                int    position = 0;
                int    count    = comm.GetFileBufferMaxSize();
                byte[] buffer   = new byte[count];
                while (count > 0 && !Cancel)
                {
                    //read from disk
                    count = fs.Read(buffer, 0, count);
                    if (count < 0)
                    {
                        throw new System.IO.IOException("Couldn't read file");
                    }
                    else if (count == 0)
                    {
                        continue;
                    }

                    //write to device
                    if (!comm.WriteFileRequest(adr, object_id, ref position, count, buffer))
                    {
                        throw new System.IO.IOException("Couldn't write file");
                    }

                    //progress
                    if (count > 0)
                    {
                        position += count;
                        if (progress_action != null)
                        {
                            progress_action(position);
                        }
                    }
                }
            }
            finally
            {
                fs.Close();
            }
        }
        public void DownloadFileByBlocking(BacnetClient comm, BacnetAddress adr, BacnetObjectId object_id, string filename, Action <int> progress_action)
        {
            Cancel = false;

            //open file
            System.IO.FileStream fs = null;
            try
            {
                fs = System.IO.File.OpenWrite(filename);
            }
            catch (Exception ex)
            {
                throw new System.IO.IOException("Couldn't open file", ex);
            }

            int  position    = 0;
            uint count       = (uint)comm.GetFileBufferMaxSize();
            bool end_of_file = false;

            byte[] buffer;
            int    buffer_offset;

            try
            {
                while (!end_of_file && !Cancel)
                {
                    //read from device
                    if (!comm.ReadFileRequest(adr, object_id, ref position, ref count, out end_of_file, out buffer, out buffer_offset))
                    {
                        throw new System.IO.IOException("Couldn't read file");
                    }
                    position += (int)count;

                    //write to file
                    if (count > 0)
                    {
                        fs.Write(buffer, buffer_offset, (int)count);
                        if (progress_action != null)
                        {
                            progress_action(position);
                        }
                    }
                }
            }
            finally
            {
                fs.Close();
            }
        }
        private static void OnAtomicReadFileRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, bool is_stream, BacnetObjectId object_id, int position, uint count, BacnetMaxSegments max_segments)
        {
            lock (m_lockObject)
            {
                try
                {
                    if (object_id.Type != BacnetObjectTypes.OBJECT_FILE)
                    {
                        throw new Exception("File Reading on non file objects ... bah!");
                    }
                    else if (object_id.Instance != 0)
                    {
                        throw new Exception("Don't know this file");
                    }

                    //this is a test file for performance measuring
                    int  filesize    = m_storage.ReadPropertyValue(object_id, BacnetPropertyIds.PROP_FILE_SIZE);    //test file is ~10mb
                    bool end_of_file = (position + count) >= filesize;
                    count = (uint)Math.Min(count, filesize - position);
                    int max_filebuffer_size = sender.GetFileBufferMaxSize();
                    if (count > max_filebuffer_size && max_segments > 0)
                    {
                        //create segmented message!!!
                    }
                    else
                    {
                        count = (uint)Math.Min(count, max_filebuffer_size);     //trim
                    }

                    //fill file with bogus content
                    byte[] file_buffer = new byte[count];
                    byte[] bogus       = new byte[] { (byte)'F', (byte)'I', (byte)'L', (byte)'L' };
                    for (int i = 0; i < count; i += bogus.Length)
                    {
                        Array.Copy(bogus, 0, file_buffer, i, Math.Min(bogus.Length, count - i));
                    }

                    //send
                    HandleSegmentationResponse(sender, adr, invoke_id, max_segments, (seg) =>
                    {
                        sender.ReadFileResponse(adr, invoke_id, seg, position, count, end_of_file, file_buffer);
                    });
                }
                catch (Exception)
                {
                    sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER);
                }
            }
        }
        private static void handler_OnAtomicReadFileRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, bool is_stream, BacnetObjectId object_id, int position, uint count, BacnetMaxSegments max_segments)
        {
            lock (device)
            {
                BaCSharpObject File = device.FindBacnetObject(object_id);
                if (File is BacnetFile)
                {
                    try
                    {
                        BacnetFile f = (BacnetFile)File;

                        int  filesize    = (int)f.PROP_FILE_SIZE;
                        bool end_of_file = (position + count) >= filesize;
                        count = (uint)Math.Min(count, filesize - position);
                        int max_filebuffer_size = sender.GetFileBufferMaxSize();
                        if (count > max_filebuffer_size && max_segments > 0)
                        {
                            //create segmented message!!!
                        }
                        else
                        {
                            count = (uint)Math.Min(count, max_filebuffer_size);     //trim
                        }

                        byte[] file_buffer = f.ReadFileBlock(position, (int)count);
                        sender.ReadFileResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), position, count, end_of_file, file_buffer);
                    }
                    catch (Exception)
                    {
                        sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER);
                    }
                }
                else
                {
                    sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER);
                }
            }
        }
        /// <summary>
        /// This method is based upon increasing the MaxInfoFrames in the MSTP.
        /// In Bacnet/IP this will have bad effect due to the retries
        /// </summary>
        public void DownloadFileByAsync(BacnetClient comm, BacnetAddress adr, BacnetObjectId object_id, string filename, Action <int> progress_action)
        {
            Cancel = false;

            //open file
            System.IO.FileStream fs = null;
            try
            {
                fs = System.IO.File.OpenWrite(filename);
            }
            catch (Exception ex)
            {
                throw new System.IO.IOException("Couldn't open file", ex);
            }

            uint max_count = (uint)comm.GetFileBufferMaxSize();

            BacnetAsyncResult[] transfers = new BacnetAsyncResult[50];
            byte old_max_info_frames      = comm.Transport.MaxInfoFrames;

            comm.Transport.MaxInfoFrames = 50;      //increase max_info_frames so that we can occupy line more. This might be against 'standard'

            try
            {
                int  position = 0;
                bool eof      = false;

                while (!eof && !Cancel)
                {
                    //start many async transfers
                    for (int i = 0; i < transfers.Length; i++)
                    {
                        transfers[i] = (BacnetAsyncResult)comm.BeginReadFileRequest(adr, object_id, position + i * (int)max_count, max_count, false);
                    }

                    //wait for all transfers to finish
                    int current = 0;
                    int retries = comm.Retries;
                    while (current < transfers.Length)
                    {
                        if (!transfers[current].WaitForDone(comm.Timeout))
                        {
                            if (--retries > 0)
                            {
                                transfers[current].Resend();
                                continue;
                            }
                            else
                            {
                                throw new System.IO.IOException("Couldn't read file");
                            }
                        }
                        retries = comm.Retries;

                        uint      count;
                        byte[]    file_buffer;
                        int       file_buffer_offset;
                        Exception ex;
                        comm.EndReadFileRequest(transfers[current], out count, out position, out eof, out file_buffer, out file_buffer_offset, out ex);
                        transfers[current] = null;
                        if (ex != null)
                        {
                            throw ex;
                        }

                        if (count > 0)
                        {
                            //write to file
                            fs.Position = position;
                            fs.Write(file_buffer, file_buffer_offset, (int)count);
                            position += (int)count;
                            if (progress_action != null)
                            {
                                progress_action(position);
                            }
                        }
                        current++;
                    }
                }
            }
            finally
            {
                fs.Close();
                comm.Transport.MaxInfoFrames = old_max_info_frames;
            }
        }