Beispiel #1
0
        private static PeerInfo[] DecodePeers(BEncoding.List peerList)
        {
            var peerInfoList = new List <PeerInfo>(peerList.Count);

            foreach (var peer in peerList)
            {
                if (peer is BEncoding.Dictionary)
                {
                    var    peerDict = (peer as BEncoding.Dictionary);
                    byte[] peerIDBytes;
                    if (!peerDict.TryGetByteArray("peer id", out peerIDBytes) && !peerDict.TryGetByteArray("peer_id", out peerIDBytes))
                    {
                        peerIDBytes = null;
                    }

                    string peerIP;
                    long   peerPort;
                    if (peerDict.TryGetString("ip", out peerIP) && peerDict.TryGetInteger("port", out peerPort) && peerPort > 0 && peerPort <= ushort.MaxValue)
                    {
                        IPAddress ipAddress;
                        if (IPAddress.TryParse(peerIP, out ipAddress))
                        {
                            var endPoint = new IPEndPoint(ipAddress, (int)peerPort);
                            if (peerIDBytes != null && peerIDBytes.Length == 20)
                            {
                                var peerID = new PeerID(peerIDBytes);
                                peerInfoList.Add(new PeerInfo(peerID, endPoint));
                            }
                            else
                            {
                                peerInfoList.Add(new PeerInfo(endPoint));
                            }
                        }
                        else
                        {
                            Log.LogError("[HTTP Tracker] Unable to parse peer IP: {0}", peerIP);
                        }
                    }
                }
                else if (peer is byte[])
                {
                    var peerBytes    = peer as byte[];
                    var decodedPeers = DecodePeers(peerBytes);
                    if (decodedPeers != null)
                    {
                        peerInfoList.AddRange(decodedPeers);
                    }
                    else
                    {
                        Log.LogError("[HTTP Tracker] Unable to decode peer information from {0} bytes of compact data.", peerBytes.Length);
                    }
                }
                else
                {
                    Log.LogError("[HTTP Tracker] Unable decode get peer information with invalid BEncode type: {0}", (peer != null ? peer.GetType().Name : "<null>"));
                }
            }

            return(peerInfoList.ToArray());
        }
Beispiel #2
0
        private BEncoding.Dictionary Save()
        {
            var torrentInfo = new BEncoding.Dictionary();

            // Make sure that there is a piece size
            if (pieceSize == 0)
            {
                throw new InvalidOperationException("No piece size has been set yet.");
            }
            else if (!MathHelper.IsPowerOfTwo(pieceSize))
            {
                throw new InvalidOperationException("The piece size must be a power of two.");
            }
            else if (files == null || files.Length == 0)
            {
                throw new InvalidOperationException("No files have been defined yet.");
            }
            else if (totalSize == 0L)
            {
                throw new InvalidOperationException("The total size of the torrent cannot be 0.");
            }

            int pieceCount = (int)((totalSize - 1) / pieceSize) + 1;

            if (pieceCount != pieceHashes.Length)
            {
                throw new InvalidOperationException(string.Format("The calculated number of pieces is {0} while there are {1} piece hashes.", pieceCount, pieceHashes.Length));
            }

            if (announces != null && announces.Length > 0)
            {
                if (!string.IsNullOrEmpty(announces[0].Url))
                {
                    torrentInfo.Add("announce", announces[0].Url);
                }

                var trackerList = new BEncoding.List();
                for (int i = 0; i < announces.Length; i++)
                {
                    var urls = announces[i].Urls;
                    if (urls == null || urls.Length == 0)
                    {
                        continue;
                    }

                    var urlList = new BEncoding.List();
                    for (int j = 0; j < urls.Length; j++)
                    {
                        if (!string.IsNullOrEmpty(urls[j]))
                        {
                            urlList.Add(urls[j]);
                        }
                    }

                    if (urlList.Count > 0)
                    {
                        trackerList.Add(urlList);
                    }
                }

                if (trackerList.Count > 0)
                {
                    torrentInfo.Add("announce-list", trackerList);
                }
            }

            if (!string.IsNullOrEmpty(comment))
            {
                torrentInfo.Add("comment", comment);
            }
            if (!string.IsNullOrEmpty(createdBy))
            {
                torrentInfo.Add("created by", createdBy);
            }
            if (creationDate != DateTime.MinValue)
            {
                long creationDateTimestamp = TimeHelper.GetUnixTimestampFromDate(creationDate);
                torrentInfo.Add("creation date", creationDateTimestamp);
            }

            // Get the piece hash data
            byte[] pieceHashData = new byte[20 * pieceCount];
            for (int i = 0; i < pieceCount; i++)
            {
                Buffer.BlockCopy(pieceHashes[i].Hash, 0, pieceHashData, (i * 20), 20);
            }

            var info = new BEncoding.Dictionary();

            info.Add("piece length", pieceSize);
            info.Add("pieces", pieceHashData);
            info.Add("private", (isPrivate ? 1 : 0));

            if (!string.IsNullOrEmpty(source))
            {
                info.Add("source", source);
            }

            if (files != null)
            {
                if (files.Length == 1)
                {
                    var fileItem = files[0];
                    info.Add("length", fileItem.Size);

                    if (fileItem.MD5Hash != null && fileItem.MD5Hash.Length == 16)
                    {
                        string fileMD5HashHex = HexHelper.BytesToHex(fileItem.MD5Hash);
                        info.Add("md5sum", fileMD5HashHex);
                    }

                    info.Add("name", GetFileName(fileItem.Path));
                }
                else if (files.Length > 1)
                {
                    info.Add("name", name ?? "Unnamed");

                    var fileList = new BEncoding.List();
                    for (int i = 0; i < files.Length; i++)
                    {
                        var fileItem       = files[i];
                        var fileDictionary = new BEncoding.Dictionary();
                        fileDictionary.Add("length", fileItem.Size);

                        if (fileItem.MD5Hash != null && fileItem.MD5Hash.Length == 16)
                        {
                            string fileMD5HashHex = HexHelper.BytesToHex(fileItem.MD5Hash);
                            info.Add("md5sum", fileMD5HashHex);
                        }

                        string[] pathParts = fileItem.Path.Split(new char[] { '/' });
                        var      pathList  = new BEncoding.List(pathParts);
                        fileDictionary.Add("path", pathList);
                        fileList.Add(fileDictionary);
                    }

                    info.Add("files", fileList);
                }
            }

            infoHash = ComputeInfoHash(info);
            torrentInfo.Add("info", info);
            return(torrentInfo);
        }