示例#1
0
        }                                                       // Torrent file name
        /// <summary>
        /// Get a list of dictionaries from metainfo file that have been come under the main level dictionary
        /// key of "files". The output being a entry in the internal dictionary that contains a comma
        /// separated string of the fields (name, length, md5sum) for each list entry (file). Each file found is
        /// stored under the numeric key  value representing the number of the dictionary within the list
        /// (ie. "0", "1"..... "N").
        /// </summary>
        /// <param name="bNodeRoot">BNode root of list.</param>
        /// <param name="field">Field.</param>
        private void GetListOfDictionarys(BNodeBase bNodeRoot, string field)
        {
            BNodeBase fieldBytes = _Bencode.GetDictionaryEntry(bNodeRoot, field);

            if (fieldBytes is BNodeList bNodeList)
            {
                int fileNo = 0;
                foreach (var listItem in (bNodeList).list)
                {
                    if (listItem is BNodeDictionary bNodeDictionary)
                    {
                        BNodeBase fileDictionaryItem = (bNodeDictionary);
                        BNodeBase fileField          = null;
                        string    fileEntry          = String.Empty;
                        fileField = _Bencode.GetDictionaryEntry(fileDictionaryItem, "path");
                        if (fileField != null)
                        {
                            string path = string.Empty;
                            foreach (var file in ((BNodeList)(fileField)).list)
                            {
                                path += $"{Path.DirectorySeparatorChar}" + Encoding.ASCII.GetString(((BitTorrentLibrary.BNodeString)file).str);
                            }
                            fileEntry = path;
                        }
                        fileEntry += ",";
                        fileEntry += _Bencode.GetDictionaryEntryString(fileDictionaryItem, "length");
                        fileEntry += ",";
                        fileEntry += _Bencode.GetDictionaryEntryString(fileDictionaryItem, "md5string");
                        metaInfoDict[fileNo.ToString()] = Encoding.ASCII.GetBytes(fileEntry);
                        fileNo++;
                    }
                }
            }
        }
示例#2
0
        /// <summary>
        /// Return string representation of a given BNode dictionary entry.
        /// </summary>
        /// <returns>String value of a given byte encoded number or string.</returns>
        /// <param name="bNode">bNode - Entry to extract.</param>
        /// <param name="entryKey">entryKey - Key of dictionary entry to extract.</param>
        public string GetDictionaryEntryString(BNodeBase bNode, string entryKey)
        {
            BNodeBase entryNode;

            try
            {
                entryNode = GetDictionaryEntry(bNode, entryKey);
                if (entryNode != null)
                {
                    if (entryNode is BNodeString bNodeString)
                    {
                        return(Encoding.ASCII.GetString((bNodeString).str));
                    }
                    if (entryNode is BNodeNumber bNodeNumber)
                    {
                        return(Encoding.ASCII.GetString((bNodeNumber).number));
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Debug(ex);
                throw new Exception("Could not get string from BNode structure." + ex.Message);
            }
            return("");
        }
        public void TestMultiFileTorrentWithErrorDecode()
        {
            Bencode bEncode = new Bencode();

            byte[] expected = System.IO.File.ReadAllBytes(Constants.MultiFileWithErrorTorrent);
            Assert.Throws <Exception>(() => { BNodeBase torrentBase = bEncode.Decode(expected); });
        }
        public void TestDecodeThenEncodeTheSamString(string expected)
        {
            Bencode   bEncode = new Bencode();
            BNodeBase bNode   = bEncode.Decode(Encoding.ASCII.GetBytes(expected));

            byte[] actual = bEncode.Encode(bNode);
            Assert.Equal(Encoding.ASCII.GetBytes(expected), actual);
        }
示例#5
0
        /// <summary>
        /// Calculates the info hash for metainfo and stores in internal dictionary.
        /// </summary>
        /// <param name="bNodeRoot">BNode root of meta info.</param>
        private void CalculateInfoHash(BNodeBase bNodeRoot)
        {
            BNodeBase infoEncodedBytes = _Bencode.GetDictionaryEntry(bNodeRoot, "info");

            if (infoEncodedBytes != null)
            {
                metaInfoDict["info hash"] = new SHA1CryptoServiceProvider().ComputeHash(_Bencode.Encode(infoEncodedBytes));
            }
        }
        public void TestMultiFileTorrentDecodeEncodeCheckTheSameAfter()
        {
            Bencode bEncode = new Bencode();

            byte[]    expected    = System.IO.File.ReadAllBytes(Constants.MultiFileTorrent);
            BNodeBase torrentBase = bEncode.Decode(expected);

            byte[] actual = bEncode.Encode(torrentBase);
            Assert.Equal(expected, actual);
        }
示例#7
0
        /// <summary>
        /// Gets the bytes representing a string or number (characters of number).
        /// </summary>
        /// <param name="bNodeRoot">BNode root of string number.</param>
        /// <param name="field">Field.</param>
        private void GetStringOrNumeric(BNodeBase bNodeRoot, string field)
        {
            BNodeBase fieldBytes = _Bencode.GetDictionaryEntry(bNodeRoot, field);

            if (fieldBytes is BNodeNumber bNodeNumber)
            {
                metaInfoDict[field] = (bNodeNumber).number;
            }
            else if (fieldBytes is BNodeString bNodeString)
            {
                metaInfoDict[field] = (bNodeString).str;
            }
        }
示例#8
0
        /// <summary>
        /// Gets the list of strings from a BNode and create a comma separated string representing the
        /// list in the internal dictionary under the key value of field.
        /// </summary>
        /// <param name="bNodeRoot">BNode root of list of strings.</param>
        /// <param name="field">Field.</param>
        private void GetListOfStrings(BNodeBase bNodeRoot, string field)
        {
            BNodeBase fieldBytes = _Bencode.GetDictionaryEntry(bNodeRoot, field);

            if (fieldBytes is BNodeList bNodeList)
            {
                List <string> listString = new List <string>();
                foreach (var innerList in (bNodeList).list)
                {
                    if (innerList is BNodeList bNodeList2)
                    {
                        BNodeString stringItem = (BNodeString)(bNodeList2).list[0];
                        listString.Add(Encoding.ASCII.GetString(stringItem.str));
                    }
                }
                metaInfoDict[field] = Encoding.ASCII.GetBytes(string.Join(",", listString));
            }
        }
示例#9
0
 /// <summary>
 /// Recursively parse BNode structure to produce Bencoding for it.
 /// </summary>
 /// <returns>Bencoded representation of BNode structure.</returns>
 /// <param name="bNode">Root <paramref name="bNode"/>.</param>
 private void EncodeFromBNode(BNodeBase bNode)
 {
     try
     {
         if (bNode is BNodeDictionary bNodeDictionary)
         {
             _workBuffer.Add((byte)'d');
             foreach (var key in (bNodeDictionary).dict.Keys)
             {
                 _workBuffer.AddRange(Encoding.ASCII.GetBytes($"{key.Length}:{key}"));
                 EncodeFromBNode((bNodeDictionary).dict[key]);
             }
             _workBuffer.Add((byte)'e');
         }
         else if (bNode is BNodeList bNodeList)
         {
             _workBuffer.Add((byte)'l');
             foreach (var node in (bNodeList).list)
             {
                 EncodeFromBNode(node);
             }
             _workBuffer.Add((byte)'e');
         }
         else if (bNode is BNodeNumber bNodeNumber)
         {
             _workBuffer.Add((byte)'i');
             _workBuffer.AddRange((bNodeNumber).number);
             _workBuffer.Add((byte)'e');
         }
         else if (bNode is BNodeString bNodeString)
         {
             _workBuffer.AddRange(Encoding.ASCII.GetBytes($"{(bNodeString).str.Length}:"));
             _workBuffer.AddRange((bNodeString).str);
         }
     }
     catch (Exception ex)
     {
         Log.Logger.Debug(ex);
         throw new Exception("Failure to encode BNode structure." + ex.Message);
     }
 }
示例#10
0
        /// <summary>
        /// Get a BNode entry for a given dictionary key. Note that it recursively searches
        /// until the key is found in the BNode structure structure.
        /// </summary>
        /// <returns>BNode entry for dictionary key.</returns>
        /// <param name="bNode">bNode - Bnode root of dictionary.</param>
        /// <param name="entryKey">entryKey - Dictionary key of Bnode entry to return.</param>
        public BNodeBase GetDictionaryEntry(BNodeBase bNode, string entryKey)
        {
            BNodeBase bNodeEntry = null;

            try
            {
                if (bNode is BNodeDictionary bNodeDictionary)
                {
                    if ((bNodeDictionary).dict.ContainsKey(entryKey))
                    {
                        return((bNodeDictionary).dict[entryKey]);
                    }
                    foreach (var key in (bNodeDictionary).dict.Keys)
                    {
                        bNodeEntry = GetDictionaryEntry((bNodeDictionary).dict[key], entryKey);
                        if (bNodeEntry != null)
                        {
                            break;
                        }
                    }
                }
                else if (bNode is BNodeList bNodeList)
                {
                    foreach (var node in (bNodeList).list)
                    {
                        bNodeEntry = GetDictionaryEntry(node, entryKey);
                        if (bNodeEntry != null)
                        {
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Debug(ex);
                throw new Exception("Could not get dictionary from BNode structure." + ex.Message);
            }
            return(bNodeEntry);
        }
示例#11
0
 /// <summary>
 /// Decode Bencoded torrent file and load internal dictionary from its contents
 /// for later retrieval by other modules.
 /// </summary>
 public void Parse()
 {
     try
     {
         BNodeBase bNodeRoot = _Bencode.Decode(_metaInfoData);
         GetStringOrNumeric(bNodeRoot, "announce");
         GetListOfStrings(bNodeRoot, "announce-list");
         GetStringOrNumeric(bNodeRoot, "comment");
         GetStringOrNumeric(bNodeRoot, "created by");
         GetStringOrNumeric(bNodeRoot, "creation date");
         GetStringOrNumeric(bNodeRoot, "name");
         GetStringOrNumeric(bNodeRoot, "piece length");
         GetStringOrNumeric(bNodeRoot, "pieces");
         GetStringOrNumeric(bNodeRoot, "private");
         GetStringOrNumeric(bNodeRoot, "url-list");
         if (_Bencode.GetDictionaryEntry(bNodeRoot, "files") == null)
         {
             GetStringOrNumeric(bNodeRoot, "length");
             GetStringOrNumeric(bNodeRoot, "md5sum");
         }
         else
         {
             GetListOfDictionarys(bNodeRoot, "files");
         }
         CalculateInfoHash(bNodeRoot);
         foreach (var key in metaInfoDict.Keys)
         {
             if ((key != "pieces") && (key != "info") && (key != "info hash"))
             {
                 Log.Logger.Error($"{key}={Encoding.ASCII.GetString(metaInfoDict[key])}");
             }
         }
     }
     catch (Exception ex)
     {
         Log.Logger.Error(ex);
         throw new BitTorrentException(ex.Message);
     }
 }
示例#12
0
 /// <summary>
 /// Produce Bencoded output given the root of a BNode structure.
 /// </summary>
 /// <param name="bNode"></param>
 /// <returns></returns>
 public byte[] Encode(BNodeBase bNode)
 {
     _workBuffer.Clear();
     EncodeFromBNode(bNode);
     return(_workBuffer.ToArray());
 }
示例#13
0
 private readonly Bencode _Bencode;      // Bencode encode/decode
 /// <summary>
 /// Decodes the announce request BEncoded response recieved from a tracker.
 /// </summary>
 /// <param name="announceResponse">Announce response.</param>
 /// <param name="decodedResponse">Response.</param>
 private void DecodeAnnounceResponse(Tracker tracker, byte[] announceResponse, ref AnnounceResponse decodedResponse)
 {
     if (announceResponse.Length != 0)
     {
         BNodeBase decodedAnnounce = _Bencode.Decode(announceResponse);
         decodedResponse.statusMessage = _Bencode.GetDictionaryEntryString(decodedAnnounce, "failure reason");
         if (decodedResponse.statusMessage != "")
         {
             decodedResponse.failure = true;
             return; // If failure present then ignore rest of reply.
         }
         int.TryParse(_Bencode.GetDictionaryEntryString(decodedAnnounce, "complete"), out decodedResponse.complete);
         int.TryParse(_Bencode.GetDictionaryEntryString(decodedAnnounce, "incomplete"), out decodedResponse.incomplete);
         BNodeBase field = _Bencode.GetDictionaryEntry(decodedAnnounce, "peers");
         if (field != null)
         {
             decodedResponse.peerList = new List <PeerDetails>();
             if (field is BNodeString bNodeString) // Compact peer list reply
             {
                 decodedResponse.peerList = tracker.GetCompactPeerList((bNodeString).str, 0);
             }
             else if (field is BNodeList bNodeList)  // Non-compact peer list reply
             {
                 foreach (var listItem in (bNodeList).list)
                 {
                     if (listItem is BNodeDictionary bNodeDictionary)
                     {
                         PeerDetails peer = new PeerDetails
                         {
                             infoHash = tracker.InfoHash
                         };
                         BNodeBase peerDictionaryItem = (bNodeDictionary);
                         BNodeBase peerField          = _Bencode.GetDictionaryEntry(peerDictionaryItem, "ip");
                         if (peerField != null)
                         {
                             peer.ip = Encoding.ASCII.GetString(((BitTorrentLibrary.BNodeString)peerField).str);
                         }
                         if (peer.ip.Contains(":"))
                         {
                             peer.ip = peer.ip.Substring(peer.ip.LastIndexOf(":", StringComparison.Ordinal) + 1);
                         }
                         peerField = _Bencode.GetDictionaryEntry(peerDictionaryItem, "port");
                         if (peerField != null)
                         {
                             peer.port = int.Parse(Encoding.ASCII.GetString(((BitTorrentLibrary.BNodeNumber)peerField).number));
                         }
                         if (peer.ip != tracker.Ip) // Ignore self in peers list
                         {
                             Log.Logger.Trace($"(Tracker) Peer {peer.ip} Port {peer.port} found.");
                             decodedResponse.peerList.Add(peer);
                         }
                     }
                 }
             }
         }
         int.TryParse(_Bencode.GetDictionaryEntryString(decodedAnnounce, "interval"), out decodedResponse.interval);
         int.TryParse(_Bencode.GetDictionaryEntryString(decodedAnnounce, "min interval"), out decodedResponse.minInterval);
         decodedResponse.trackerID     = _Bencode.GetDictionaryEntryString(decodedAnnounce, "tracker id");
         decodedResponse.statusMessage = _Bencode.GetDictionaryEntryString(decodedAnnounce, "warning message");
         decodedResponse.announceCount++;
     }
 }