/// <summary>
        /// Processes file information response packet
        /// </summary>
        private void ProcessFileInfoResponse()
        {
            string file_operation_id;
            PendingFileOperationInfo file_operation_info;
            PacketFileInfoResponse   packet = (PacketFileInfoResponse)CommunicationManager.Default.ReceiverQueue.Pop(typeof(PacketFileInfoResponse));

            CommunicationManager.Default.PacketLogWrite("R", packet);

            // check file operation ID
            file_operation_id = packet.FileOperationID;
            if (!m_pending_file_operations.ContainsKey(file_operation_id))
            {
                return;
            }

            // check pending file operation
            file_operation_info = m_pending_file_operations[file_operation_id];
            if (file_operation_info.Packet.PacketType != PacketType.FileInfoRequest)
            {
                return;
            }

            // remove file operation from the peding list
            FileOperationEnd(packet);

            // if no callback if defined, this is regular system file operation
            if (file_operation_info.Callback == null)
            {
                if (packet.ID == InvalidSystemFileID)
                {
                    // if file not found -> error
                    m_file_transfer_state = FileTransferState.Idle;

                    CallFileTransferFinishedCallback(new FileTransferResultInfo(FileTransferResult.NotFound));
                }
                else
                {
                    m_file_transfer_current_position = 0;
                    m_file_transfer_current_size     = packet.Length;
                    m_file_transfer_current_id       = packet.ID;

                    string cached_file_name = m_file_transfer_current_name + "[" + CommunicationManager.Default.ConnectedDeviceUniqueID.ToString("x4") + "]";

                    // file exists -> check file in the cache
                    if (DeviceFileCache.IsFileExists(cached_file_name, packet.Length, packet.Hash))
                    {
                        // file exists in the cache -> call callback with success code
                        string file_path;
                        file_path = Path.Combine(DeviceFileCache.GetFileCachePath(), cached_file_name);

                        m_file_transfer_current_position = m_file_transfer_current_size;
                        m_file_transfer_state            = FileTransferState.Idle;

                        UpdateFileTransferState();

                        CallFileTransferFinishedCallback(new FileTransferResultInfo(FileTransferResult.Success, m_file_transfer_current_id, file_path));
                    }
                    else
                    {
                        // file doesn't exists in the cache create file in the cache and download it
                        m_file_transfer_current_file = DeviceFileCache.CreateFile(cached_file_name, 0);

                        // start download
                        m_file_transfer_state = FileTransferState.ReadData;

                        UpdateFileTransferState();

                        SendFileDataReadRequest();
                    }
                }
            }
            else
            {
                file_operation_info.Callback(packet);
            }
        }
        /// <summary>
        /// Processes received file data block
        /// </summary>
        private void ProcessFileDataReadResponse()
        {
            byte[]   packet;
            byte     packet_length;
            byte     interface_index;
            DateTime packet_timestamp;
            PacketFileDataReadResponseHeader packet_header;
            int    data_offset;
            int    data_length;
            string file_operation_id;
            PendingFileOperationInfo file_operation_info;

            if (CommunicationManager.Default.ReceiverQueue.PopBegin(out packet, out packet_length, out interface_index, out packet_timestamp))
            {
                // get packet header
                packet_header = (PacketFileDataReadResponseHeader)RawBinarySerialization.DeserializeObject(packet, typeof(PacketFileDataReadResponseHeader));
                CommunicationManager.Default.PacketLogWrite("R", packet_header);

                // check pending file operation
                file_operation_id = packet_header.FileOperationID;
                if (m_pending_file_operations.ContainsKey(file_operation_id))
                {
                    file_operation_info = m_pending_file_operations[file_operation_id];

                    // finish file operation
                    FileOperationEnd(packet_header);

                    if (file_operation_info.Packet.PacketType == PacketType.FileDataReadRequest)
                    {
                        // determine file data block position and length within the packet
                        data_offset = Marshal.SizeOf(typeof(PacketFileDataReadResponseHeader));
                        data_length = packet_header.PacketLength - PacketConstants.PacketCRCLength - Marshal.SizeOf(typeof(PacketFileDataReadResponseHeader));

                        // if no callback if defined, this is regular system file operation
                        if (file_operation_info.Callback == null)
                        {
                            m_file_transfer_current_file.Write(packet, data_offset, data_length);

                            m_file_transfer_current_position += (uint)data_length;

                            UpdateFileTransferState();

                            if (m_file_transfer_current_position < m_file_transfer_current_size)
                            {
                                SendFileDataReadRequest();
                            }
                            else
                            {
                                m_file_transfer_current_file.Close();

                                m_file_transfer_state = FileTransferState.Idle;

                                CallFileTransferFinishedCallback(new FileTransferResultInfo(FileTransferResult.Success, m_file_transfer_current_id, m_file_transfer_current_file.FullFilePath));
                                m_file_transfer_current_file.Dispose();
                                m_file_transfer_current_file = null;
                            }
                        }
                        else
                        {
                            // prepare deserialized packet for further file data processing
                            PacketFileDataReadResponse response = new PacketFileDataReadResponse(packet_header);

                            response.SetData(packet, data_offset, data_length);

                            file_operation_info.Callback(response);
                        }
                    }
                }

                // close packet processing
                CommunicationManager.Default.ReceiverQueue.PopEnd();
            }
        }
 public FileTransferManager()
 {
     m_pending_file_operations    = new Dictionary <string, PendingFileOperationInfo>();
     m_file_transfer_state        = FileTransferState.Idle;
     m_file_transfer_current_file = null;
 }