public override void ExecuteRequest() { DataBuffer buf1 = new DataBuffer(); buf1.InsertInt16(20); buf1.InsertInt16(0x0200); buf1.InsertDwordString("IX86"); buf1.InsertDwordString(Product); if (m_ad) { buf1.InsertInt32(m_adId); buf1.InsertDwordString(m_adExt); } else { buf1.InsertInt64(0); } Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sck.Connect(Server, 6112); sck.Send(new byte[] { 2 }); sck.Send(buf1.UnderlyingBuffer, 0, buf1.Count, SocketFlags.None); NetworkStream ns = new NetworkStream(sck, false); DataReader rdr = new DataReader(ns, 4); int serverToken = rdr.ReadInt32(); DataBuffer buf2 = new DataBuffer(); buf2.InsertInt32(0); // no resuming if (FileTime.HasValue) { buf2.InsertInt64(FileTime.Value.ToFileTimeUtc()); } else { buf2.InsertInt64(0); } int clientToken = new Random().Next(); buf2.InsertInt32(clientToken); buf2.InsertInt32(m_key.Key.Length); buf2.InsertInt32(m_key.Product); buf2.InsertInt32(m_key.Value1); buf2.InsertInt32(0); buf2.InsertByteArray(m_key.GetHash(clientToken, serverToken)); buf2.InsertCString(FileName); sck.Send(buf2.UnderlyingBuffer, 0, buf2.Count, SocketFlags.None); rdr = new DataReader(ns, 4); int msg2Size = rdr.ReadInt32() - 4; rdr = new DataReader(ns, msg2Size); this.FileSize = rdr.ReadInt32(); rdr.Seek(8); long fileTime = rdr.ReadInt64(); DateTime time = DateTime.FromFileTimeUtc(fileTime); string name = rdr.ReadCString(); if (string.Compare(name, FileName, StringComparison.OrdinalIgnoreCase) != 0 || FileSize == 0) { throw new FileNotFoundException(Resources.bnftp_filenotfound); } byte[] data = ReceiveLoop(sck, FileSize); sck.Close(); FileStream fs = new FileStream(LocalFileName, FileMode.OpenOrCreate, FileAccess.Write); fs.Write(data, 0, FileSize); fs.Flush(); fs.Close(); }
/// <summary> /// Executes the BnFTP request, downloading the file to where <see cref="BnFtpRequestBase.LocalFileName">LocalFileName</see> /// specifies, and closes the connection. /// </summary> /// <remarks> /// <para>By default, <c>LocalFileName</c> is the same name as the remote file, which will cause the file /// to be saved in the local application path. The desired location of the file must be set before /// <b>ExecuteRequest</b> is called.</para> /// </remarks> /// <exception cref="IOException">Thrown if the local file cannot be written.</exception> /// <exception cref="SocketException">Thrown if the remote host closes the connection prematurely.</exception> public override void ExecuteRequest() { DataBuffer buffer = new DataBuffer(); buffer.InsertInt16((short)(33 + FileName.Length)); buffer.InsertInt16(0x0100); buffer.InsertDwordString("IX86"); buffer.InsertDwordString(Product); if (m_ad) { buffer.InsertInt32(m_adId); buffer.InsertDwordString(m_adExt); } else { buffer.InsertInt64(0); } // currently resuming is not supported buffer.InsertInt32(0); if (FileTime.HasValue) { buffer.InsertInt64(FileTime.Value.ToFileTimeUtc()); } else { buffer.InsertInt64(0); } buffer.InsertCString(FileName); Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sck.Connect(Server, 6112); sck.Send(new byte[] { 2 }); sck.Send(buffer.UnderlyingBuffer, 0, buffer.Count, SocketFlags.None); BattleNetClientResources.OutgoingBufferPool.FreeBuffer(buffer.UnderlyingBuffer); byte[] hdrLengthBytes = new byte[2]; sck.Receive(hdrLengthBytes, 2, SocketFlags.None); int hdrLen = BitConverter.ToInt16(hdrLengthBytes, 0); Debug.WriteLine(hdrLen, "Header Length"); byte[] hdrBytes = new byte[hdrLen - 2]; sck.Receive(hdrBytes, hdrLen - 2, SocketFlags.None); DataReader rdr = new DataReader(hdrBytes); rdr.Seek(2); int fileSize = rdr.ReadInt32(); this.FileSize = fileSize; rdr.Seek(8); long fileTime = rdr.ReadInt64(); string name = rdr.ReadCString(); if (string.Compare(name, FileName, StringComparison.OrdinalIgnoreCase) != 0 || FileSize == 0) { throw new FileNotFoundException(Resources.bnftp_filenotfound); } Debug.WriteLine(fileSize, "File Size"); byte[] data = ReceiveLoop(sck, fileSize); sck.Close(); FileStream fs = new FileStream(LocalFileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); fs.SetLength(fileSize); fs.Write(data, 0, fileSize); fs.Flush(); fs.Close(); DateTime time = DateTime.FromFileTimeUtc(fileTime); File.SetLastWriteTimeUtc(LocalFileName, time); }