public bool Download(Peer peer, RingInfo ringInfo, ResourceHeader resourceHeader, 
     UICallBack UIHndlr)
 {
     Download download = new Download(peer, ringInfo, resourceHeader, UIHndlr);
     int downloadIndex = Add(download);
     if (downloadIndex < 0)
     {
         Queue(download);
         return false;
     }
     Download_Internal(download);
     return true;
 }
        public void Download_Internal(Download download)
        {
            //REVISIT:first try downloading from single source and then try parallelizing
            byte[] message = new byte[Constants.WRITEBUFFSIZE];
            byte[] buffer = new Byte[Constants.READBUFFSIZE];
            MemoryStream stream;
            BinaryReader reader = null;
            BinaryWriter writer = null;

            //REVISIT: when implementing parallel downloads, need to change these dynamically
            int offset = 0;
            int bytesToDownload = (int)download.header.size;

            try
            {
                BinaryFormatter serializer = new BinaryFormatter();
                stream = new MemoryStream(message);

                NetLib.insertEntropyHeader(serializer, stream);

                serializer.Serialize(stream, Constants.MessageTypes.MSG_DOWNLOADREQUEST);
                serializer.Serialize(stream, download.ringInfo.token);
                serializer.Serialize(stream, download.ringInfo.ring.ringID);
                serializer.Serialize(stream, User.getInstance().node.syncCommunicationPoint);
                serializer.Serialize(stream, download.header);
                serializer.Serialize(stream, offset);
                serializer.Serialize(stream, bytesToDownload);

                //Send out the request for download
                NetworkStream networkStream = NetLib.OpenCommunicationChannel(download.peer.node.syncCommunicationPoint);

                reader = new BinaryReader(networkStream);
                writer = new BinaryWriter(networkStream);

                writer.Write(message);
                writer.Flush();

                stream.Close();

                reader.Read(buffer, 0, buffer.Length);
                BinaryFormatter deserializer = new BinaryFormatter();

                stream = new MemoryStream(buffer);
                NetLib.bypassEntropyHeader(deserializer, stream);
                Constants.MessageTypes replyMsg = (Constants.MessageTypes)deserializer.Deserialize(stream);

                switch(replyMsg)
                {
                    case Constants.MessageTypes.MSG_DOWNLOADREPLY:
                        long leftToDownload = download.header.size;
                        byte[] firstResourceChunk = (byte[])deserializer.Deserialize(stream);

                        //Insert the initial chunk into the download buffer.
                        //REVISIT: figure a way to just deserialize into download.buffer (avoids a copy)
                        firstResourceChunk.CopyTo(download.buffer, 0);

                        long bytesReadOnThisRead = firstResourceChunk.Length;
                        download.bytesRead += bytesReadOnThisRead;
                        leftToDownload -= bytesReadOnThisRead;
                        download.UIHandler.Invoke(bytesReadOnThisRead);

                        while (leftToDownload > 0 && bytesReadOnThisRead > 0)
                        {
                            bytesReadOnThisRead = reader.Read(download.buffer, (int)download.bytesRead,
                                download.buffer.Length-(int)download.bytesRead);
                            download.bytesRead += bytesReadOnThisRead;
                            leftToDownload -= bytesReadOnThisRead;
                            download.UIHandler.Invoke(bytesReadOnThisRead);
                            System.Threading.Thread.Sleep(10);
                        }

                        Debug.Assert(download.bytesRead == download.header.size, "Did not receive the entire file");
                        break;
                    default:
                        Remove(download);
                        Queue(download);
                        break;
                }
            }
            catch (Exception e)
            {
                int x = 2;  //REVISIT: probably need to send info to logger.
            }
            finally
            {
                if (reader != null && writer != null)
                {
                    reader.Close();
                    writer.Close();
                }
            }
        }
 private void Queue(Download download)
 {
     pendingDownloads.Enqueue(download);
 }
 private void Remove(Download download)
 {
     for (int index = 0; index < downloads.Length; index++)
     {
         if (downloads[index] == download)
             downloads[index] = null;
     }
 }
 private int Add(Download download)
 {
     for (int index = 0; index < downloads.Length; index++)
     {
         if (downloads[index] == null)
         {
             downloads[index] = download;
             return index;
         }
     }
     return -1;
 }