示例#1
0
		/// <summary>Constructs a MetainfoFile</summary>
		/// <param name="istream">Stream to read data from</param>
		public MetainfoFile(IO.Stream istream)
		{
			BEncode.Dictionary mainDictionary = (BEncode.Dictionary)BEncode.NextElement(istream);
			this.announceUrl = mainDictionary.GetString(new BEncode.String("announce"));
			
			if (mainDictionary.Contains("comment"))
				this.comment = mainDictionary.GetString("comment");
			if (mainDictionary.Contains("created by"))
				this.createdBy = mainDictionary.GetString("created by");
			if (mainDictionary.Contains("creation date"))
			{
				int creation = mainDictionary.GetInteger("creation date");
				this.creationDate = new System.DateTime(1970, 1, 1, 0, 0, 0);
				this.creationDate = this.creationDate.AddSeconds(creation);
			}
			
			BEncode.Dictionary infoDictionary = mainDictionary.GetDictionary("info");
			this.name = infoDictionary.GetString("name");
			this.pieceLength = infoDictionary.GetInteger("piece length");

			this.pieceFileName = this.name.ToLower().Replace(' ', '_');
			
			// Get SHA digests
			byte[] pieces = infoDictionary.GetBytes("pieces");
			int numPieces = pieces.Length / 20;
			
			this.shaDigestList.Capacity = numPieces;
			
			for (int i=0; i<numPieces; ++i)
			{
				this.shaDigestList.Add( new ByteField20(pieces, i*20) );
			}
			
			// Get filenames and lengths
			if (infoDictionary.Contains("length"))
			{
				// one file
				this.fileList.Add(name);
				
				int fileLength = infoDictionary.GetInteger("length");
				this.fileLengthList.Add(fileLength);
				this.totalSize = fileLength;
			}
			else
			{
				// multiple files - a list of dictionaries containing the filename and length
				BEncode.List files = infoDictionary.GetList("files");
				this.fileList.Capacity = this.fileLengthList.Capacity = files.Count;
				this.totalSize = 0;
				
				foreach (BEncode.Dictionary fileDic in files)
				{
					BEncode.List pathList = fileDic.GetList("path");
					string path = this.name + IO.Path.DirectorySeparatorChar;
					
					for (int i=0; i<pathList.Count-1; ++i)
					{
						path += pathList[i].ToString() + IO.Path.DirectorySeparatorChar;
					}

					path += pathList[ pathList.Count-1 ];
					
					this.fileList.Add(path);
					
					int fileLength = fileDic.GetInteger("length");
					this.fileLengthList.Add(fileLength);
					this.totalSize += fileLength;
				}
			}
			
			// calculate the SHA-1 digest of the info dictionary - this is required for the tracker protocol
			istream.Seek(infoDictionary.Position, IO.SeekOrigin.Begin);
			byte[] infoData = new byte[ infoDictionary.Length ];
			istream.Read(infoData, 0, infoData.Length);
			
			this.infoDigest = ByteField20.ComputeSHAHash(infoData);
		}
示例#2
0
		public BitField ReadBitfieldMessage(IO.Stream stream, int length)
		{
			byte[] bitfield = new byte[ length ];
			stream.Read(bitfield, 0, bitfield.Length);
			return new BitField(bitfield, 0, bitfield.Length);
		}
示例#3
0
		public static void ReceiveHandshake(IO.Stream stream, ref ByteField20 infoDigest)
		{
			// read in protocol string
			byte[] protocolVersionLength = new byte[1];
			if ( stream.Read( protocolVersionLength, 0, protocolVersionLength.Length ) != protocolVersionLength.Length )
				throw new System.Exception( "Invalid handshake protocol" );
			if ( protocolVersionLength[0] != 19 )
				throw new System.Exception( "Invalid handshake protocol" );
			byte[] protocolBytes = new byte[ protocolVersionLength[ 0 ] ];
			if ( stream.Read( protocolBytes, 0, protocolBytes.Length ) != protocolBytes.Length )
				throw new System.Exception( "Invalid handshake protocol" );
			string protocol = System.Text.ASCIIEncoding.ASCII.GetString(protocolBytes, 0, protocolBytes.Length);
			if (protocol != protocolString)
				throw new System.Exception( "Invalid handshake protocol" );

			// 8 zeros
			byte[] zeroes = new byte[ 8 ];
			if ( stream.Read( zeroes, 0, zeroes.Length ) != zeroes.Length )
				throw new System.Exception( "Invalid handshake protocol" );

			// SHA digest
			stream.Read(infoDigest.Data, 0, infoDigest.Data.Length);
		}
示例#4
0
		public static bool ReceivePeerId(IO.Stream stream, ref ByteField20 peerId)
		{
			return stream.Read(peerId.Data, 0, peerId.Data.Length) > 0;
		}
示例#5
0
		public void SendPiece(IO.Stream ostream, int pieceId, int begin, int length, IO.Stream istream, PeerFinishedPieceTransfer callback, object state)
		{
			SendMessageHeader(ostream, PeerMessage.Piece, 8 + length);
			WriteInt(ostream, pieceId);
			WriteInt(ostream, begin);

			byte[] writeData = new byte[length];
			istream.Read(writeData, 0, length);

			object[] objs = new object[4];
			objs[0] = ostream;
			objs[1] = callback;
			objs[2] = state;
			objs[3] = length;

			ostream.BeginWrite(writeData, 0, writeData.Length, new System.AsyncCallback(OnWriteFinished), (object)objs);
		}
示例#6
0
		/// <summary>
		/// Saves the stream to the torrent.
		/// </summary>
		/// <param name="pieceId">Piece index to save to</param>
		/// <param name="istream">Stream to read data from</param>
		/// <returns>True if the data saved checks out correctly with the SHA-1 digest, false otherwise. The bitfield
		/// property is automatically updated if true</returns>
		public bool SaveToFile(int pieceId, IO.Stream istream)
		{
			// it starts in this file, as it could be spread across several files keep looping till we finish
			int dataWritten = 0;
			int positionInFile = 0;
			int fileNum = 0;

			Crypto.SHA1 sha = new Crypto.SHA1CryptoServiceProvider();

			WhichFileIsPieceIn(pieceId, out fileNum, out positionInFile);

			while (dataWritten < this.infofile.GetPieceLength(pieceId) && fileNum < this.infofile.FileCount)
			{
				int fileLength = this.infofile.GetFileLength(fileNum);
				int dataToWrite = System.Math.Min(fileLength - positionInFile, this.infofile.GetPieceLength(pieceId) - dataWritten);

				IO.FileStream fstream = new IO.FileStream(this.infofile.GetFileName(fileNum), IO.FileMode.Open);

				// write data to file
				fstream.Seek(positionInFile, IO.SeekOrigin.Begin);
			
				byte[] data = new byte[ dataToWrite ];
				istream.Read(data, 0, data.Length);
			
				fstream.Write(data, 0, data.Length);
				dataWritten += dataToWrite;

				if (dataWritten >= this.infofile.GetPieceLength(pieceId))
					sha.TransformFinalBlock(data, 0, data.Length);
				else
					sha.TransformBlock(data, 0, data.Length, data, 0);

				fstream.Close();

				fileNum++; // move onto next file
				positionInFile = 0;
			}

			if (this.infofile.GetSHADigest(pieceId).Equals(new ByteField20(sha.Hash)))
			{
				this.piecesDownloaded.Set(pieceId, true);
				this.numBytesLeft -= dataWritten;

				if (this.PercentChanged != null)
					this.PercentChanged(this, this.PercentComplete);

				if (this.piecesDownloaded.AllTrue)
					Config.LogDebugMessage("Torrent finished!");

				return true;
			}
			else
				return false;
		}
示例#7
0
			/// <summary>Constructs a string from the bEncoded stream</summary>
			/// <param name="istream">Stream to construct string from</param>
			public String(IO.Stream istream, int firstchar)
			{
				if (istream.CanSeek)
					this.position = (int)istream.Position - 1;

				string numstr = new string((char)firstchar, 1);
				while (true)
				{
					int c = istream.ReadByte();
					if (c != ':')
						numstr += (char)c;
					else
						break;
				}
				int length = System.Int32.Parse(numstr);
				if (length < 0)
					throw new System.Exception("Invalid string length");

				this.data = new byte[length];
				istream.Read(this.data, 0, length);

				if (istream.CanSeek)
					this.length = (int)(istream.Position - this.position);

//				System.Diagnostics.Debugger.Log(0, "BEncode", "String: " + this.ToString() + "\n");
			}
示例#8
0
    private void Scan(IO.TextReader input)
    {
        while (input.Peek() != -1)
        {
            char ch = (char)input.Peek();

            // Scan individual tokens
            if (char.IsWhiteSpace(ch))
            {
                // eat the current char and skip ahead!
                input.Read();
            }
            else if (char.IsLetter(ch) || ch == '_')
            {
                // keyword or identifier

                Text.StringBuilder accum = new Text.StringBuilder();

                while (char.IsLetter(ch) || ch == '_')
                {
                    accum.Append(ch);
                    input.Read();

                    if (input.Peek() == -1)
                    {
                        break;
                    }
                    else
                    {
                        ch = (char)input.Peek();
                    }
                }

                this.result.Add(accum.ToString());
            }
            else if (ch == '"')
            {
                // string literal
                Text.StringBuilder accum = new Text.StringBuilder();

                input.Read(); // skip the '"'

                if (input.Peek() == -1)
                {
                    throw new System.Exception("unterminated string literal");
                }

                while ((ch = (char)input.Peek()) != '"')
                {
                    accum.Append(ch);
                    input.Read();

                    if (input.Peek() == -1)
                    {
                        throw new System.Exception("unterminated string literal");
                    }
                }

                // skip the terminating "
                input.Read();
                this.result.Add(accum);
            }
            else if (char.IsDigit(ch))
            {
                // numeric literal

                Text.StringBuilder accum = new Text.StringBuilder();

                while (char.IsDigit(ch))
                {
                    accum.Append(ch);
                    input.Read();

                    if (input.Peek() == -1)
                    {
                        break;
                    }
                    else
                    {
                        ch = (char)input.Peek();
                    }
                }

                this.result.Add(int.Parse(accum.ToString()));
            }
            else switch (ch)
            {
                case '+':
                    input.Read();
                    this.result.Add(Scanner.Add);
                    break;

                case '-':
                    input.Read();
                    this.result.Add(Scanner.Sub);
                    break;

                case '*':
                    input.Read();
                    this.result.Add(Scanner.Mul);
                    break;

                case '/':
                    input.Read();
                    this.result.Add(Scanner.Div);
                    break;

                case '=':
                    input.Read();
                    this.result.Add(Scanner.Equal);
                    break;

                case ';':
                    input.Read();
                    this.result.Add(Scanner.Semi);
                    break;

                default:
                    throw new System.Exception("Scanner encountered unrecognized character '" + ch + "'");
            }

        }
    }
示例#9
0
    private void Scan(IO.TextReader input)
    {
        while (input.Peek() != -1)
        {
            char caracter = (char)input.Peek();

            // Scan individual tokens
            if (char.IsWhiteSpace(caracter))
            {
                // eat the current char and skip ahead!
                input.Read();
            }
            else if (char.IsLetter(caracter) || caracter == '_')
            {
                // keyword or identifier

                Text.StringBuilder accum = new Text.StringBuilder();

                while (char.IsLetter(caracter) || caracter == '_')
                {
                    accum.Append(caracter);
                    input.Read();

                    if (input.Peek() == -1)
                    {
                        break;
                    }
                    else
                    {
                        caracter = (char)input.Peek();
                    }
                }

                this.resultado.Add(accum.ToString());
            }
            else if (caracter == '"')
            {
                // string literal
                Text.StringBuilder accum = new Text.StringBuilder();

                input.Read(); // skip the '"'

                if (input.Peek() == -1)
                {
                    throw new System.Exception("Cadena sin terminar");
                }

                while ((caracter = (char)input.Peek()) != '"')
                {
                    accum.Append(caracter);
                    input.Read();

                    if (input.Peek() == -1)
                    {
                        throw new System.Exception("Cadena sin terminar");
                    }
                }

                // skip the terminating "
                input.Read();
                this.resultado.Add(accum);
            }
            else if (char.IsDigit(caracter))
            {
                // numeric literal

                Text.StringBuilder accum = new Text.StringBuilder();

                while (char.IsDigit(caracter))
                {
                    accum.Append(caracter);
                    input.Read();

                    if (input.Peek() == -1)
                    {
                        break;
                    }
                    else
                    {
                        caracter = (char)input.Peek();
                    }
                }

                this.resultado.Add(int.Parse(accum.ToString()));
            }
            else switch (caracter)
            {
                case '+':
                    input.Read();
                    this.resultado.Add(Scanner.Sum);
                    break;

                case '-':
                    input.Read();
                    this.resultado.Add(Scanner.Res);
                    break;

                case '*':
                    input.Read();
                    this.resultado.Add(Scanner.Mul);
                    break;

                case '/':
                    input.Read();
                    this.resultado.Add(Scanner.Div);
                    break;

                case '=':
                    input.Read();
                    if (input.Peek() == '=')
                    {
                        input.Read();
                        this.resultado.Add(Scanner.Eq);
                    }
                    else
                        this.resultado.Add(Scanner.Igual);
                    break;

                case ';':
                    input.Read();
                    this.resultado.Add(Scanner.PyC);
                    break;
                case '>':
                    input.Read();
                    if (input.Peek() == '=')
                    {
                        input.Read();
                        this.resultado.Add(Scanner.Gte);
                    }
                    else
                        this.resultado.Add(Scanner.Gt);
                    break;
                case '<':
                    input.Read();
                    if (input.Peek() == '=')
                    {
                        input.Read();
                        this.resultado.Add(Scanner.Lte);
                    }
                    else
                        this.resultado.Add(Scanner.Lt);
                    break;
                case '!':
                    input.Read();
                    if (input.Peek() == '=')
                    {
                        input.Read();
                        this.resultado.Add(Scanner.Neq);
                    }
                    else
                        throw new System.Exception("No se reconoce el siguiente caracter: '" + caracter + "'");
                    break;
                default:
                    throw new System.Exception("No se reconoce el siguiente caracter: '" + caracter + "'");
            }

        }
    }
示例#10
0
		/// <summary>Writes data to the piece</summary>
		/// <param name="stream">Data to write</param>
		/// <param name="length">Amount of data to write</param>
		/// <param name="poffset">Offset within the piece to write data to</param>
		public void Write(IO.Stream stream, int length, int poffset)
		{
			byte[] tdata = new byte[length];
			stream.Read(tdata, 0, length);
			this.Write(tdata, 0, length, poffset);
		}