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; }