Beispiel #1
0
        public MoreContainer(BencodedValue bencoded)
        {
            byId   = new Dictionary <byte, string>();
            byCode = new Dictionary <string, byte>();

            Decode(bencoded, byId, byCode);
        }
Beispiel #2
0
        private static void Handle(FileHash hash, PeerHash peer, byte[] payload, Action <FileHash, PeerHash, NetworkAddress[]> callback)
        {
            BencodedValue value = Bencoder.Decode(payload);

            byte[] added = value.Find("added", x => x?.Data?.GetBytes());
            List <NetworkAddress> peers = new List <NetworkAddress>();

            if (added != null)
            {
                for (int i = 0; i < added.Length; i += 6)
                {
                    string host = GetHost(added, i);
                    int    port = GetPort(added, i);

                    if (port > 0)
                    {
                        peers.Add(new NetworkAddress(host, port));
                    }
                }
            }

            if (added?.Length > 0)
            {
                callback(hash, peer, peers.ToArray());
            }
        }
        public static BencodedValue GetBencoded(this NetworkIncomingMessage incoming)
        {
            byte[]        binary   = incoming.ToBytes(6);
            BencodedValue bencoded = Bencoder.Decode(binary);

            return(bencoded);
        }
Beispiel #4
0
        public void OnMessageSent(FileHash hash, PeerHash peer, byte[] payload)
        {
            BencodedValue bencoded = Bencoder.Decode(payload);
            int?          message  = bencoded.Find("msg_type", x => x?.ToInt32());
            int?          piece    = bencoded.Find("piece", x => x?.ToInt32());
            int?          size     = bencoded.Find("total_size", x => x?.ToInt32());

            if (message == 0 && piece != null)
            {
                hooks.CallMetadataRequestSent(hash, peer, piece.Value);
            }

            if (message == 1 && size != null)
            {
                hooks.CallMetadataMeasured(hash, peer, size.Value);
            }

            if (message == 1 && piece != null)
            {
                byte[] content = Bytes.Copy(payload, bencoded.Data.Length);
                hooks.MetadataPieceSent(hash, peer, piece.Value, content);
            }

            if (message == 2 && piece != null)
            {
                hooks.CallMetadataRejectSent(hash, peer, piece.Value);
            }
        }
Beispiel #5
0
        private static void FindEntriesList(BencodedValue value, List <MetainfoEntry> entries)
        {
            BencodedValue files = value.Find("files", x => x);

            if (files?.Array != null)
            {
                foreach (BencodedValue item in files.Array)
                {
                    long?         size = item.Find("length", x => x?.ToInt64());
                    BencodedValue path = item.Find("path", x => x);

                    if (size != null && path?.Array != null)
                    {
                        List <string> names = new List <string>();

                        foreach (BencodedValue name in path.Array)
                        {
                            names.Add(name.ToText(Encoding.UTF8));
                        }

                        entries.Add(new MetainfoEntry(names.ToArray(), size.Value));
                    }
                }
            }
        }
Beispiel #6
0
        public static Metainfo FromBytes(byte[] bytes)
        {
            BencodedValue decoded  = Bencoder.Decode(bytes);
            Metainfo      metainfo = DecodeMetainfo(decoded);

            return(metainfo);
        }
Beispiel #7
0
        public static void SendMetadataRequest(this CoordinatorService glue, PeerHash peer, int piece)
        {
            BencodedValue bencoded = new BencodedValue
            {
                Dictionary = new[]
                {
                    new BencodedEntry
                    {
                        Key = new BencodedValue {
                            Text = new BencodedText("msg_type")
                        },
                        Value = new BencodedValue {
                            Number = new BencodedNumber(0)
                        }
                    },
                    new BencodedEntry
                    {
                        Key = new BencodedValue {
                            Text = new BencodedText("piece")
                        },
                        Value = new BencodedValue {
                            Number = new BencodedNumber(piece)
                        }
                    }
                }
            };

            glue.SendExtension(peer, MetadataPlugin.Name, Bencoder.Encode(bencoded));
        }
Beispiel #8
0
        public Metainfo ToMetainfo(out byte[] bytes)
        {
            BencodedValue entries = Build();

            bytes = Bencoder.Encode(entries);
            return(MetainfoFactory.FromBytes(bytes));
        }
Beispiel #9
0
        private static MetainfoProperties FindProperties(BencodedValue value, MetainfoEntry[] entries, MetainfoHash[] pieces)
        {
            long totalSize = entries.Sum(x => x.Size);
            int  blockSize = 16384;
            int  pieceSize = value.Find("piece length", x => (int)x.ToInt64());

            return(new MetainfoProperties(totalSize, pieces.Length, pieceSize, blockSize));
        }
Beispiel #10
0
        public Extended GetHandshake()
        {
            BencodedValue encoded = more.Encode(metadata?.Size);

            byte[] binary = Bencoder.Encode(encoded);

            return(new Extended(0, binary));
        }
Beispiel #11
0
        public byte[] ToBytes()
        {
            BencodedValue entries = Build();

            byte[] bytes = Bencoder.Encode(entries);

            return(bytes);
        }
Beispiel #12
0
        private static MetainfoEntry[] FindEntries(BencodedValue value)
        {
            List <MetainfoEntry> entries = new List <MetainfoEntry>();

            FindEntriesValue(value, entries);
            FindEntriesList(value, entries);

            return(entries.ToArray());
        }
Beispiel #13
0
        private static string[] FindTrackers(BencodedValue value)
        {
            HashSet <string> trackers = new HashSet <string>();

            FindTrackerValue(value, trackers);
            FindTrackerList(value, trackers);

            return(trackers.ToArray());
        }
Beispiel #14
0
        public void ShouldDecodeAsInteger()
        {
            byte[]        data  = Encoding.ASCII.GetBytes("i10e");
            BencodedValue value = Bencoder.Decode(data);

            value.Should().NotBeNull();
            value.Number.Should().NotBeNull();
            value.Number.ToInt32().Should().Be(10);
        }
Beispiel #15
0
        private static void FindEntriesValue(BencodedValue value, List <MetainfoEntry> entries)
        {
            string name = value.Find("name", x => x?.ToText(Encoding.UTF8));
            long?  size = value.Find("length", x => x?.ToInt64());

            if (name != null && size != null)
            {
                entries.Add(new MetainfoEntry(name, size.Value));
            }
        }
Beispiel #16
0
        public void OnHandshake(FileHash hash, PeerHash peer, byte[] payload)
        {
            BencodedValue bencoded = Bencoder.Decode(payload);
            int?          size     = bencoded.Find("metadata_size", x => x?.ToInt32());

            if (size != null)
            {
                hooks.CallMetadataMeasured(hash, peer, size.Value);
            }
        }
Beispiel #17
0
        private static Metainfo DecodeMetainfo(BencodedValue value)
        {
            FileHash hash = ComputeHash(value.Data);

            MetainfoEntry[]    entries    = FindEntries(value);
            MetainfoHash[]     pieces     = FindPieces(value);
            MetainfoProperties properties = FindProperties(value, entries, pieces);

            return(new Metainfo(hash, entries, pieces, properties));
        }
Beispiel #18
0
        private BencodedValue Build()
        {
            BencodedValue entries = new BencodedValue
            {
                Dictionary = new[]
                {
                    new BencodedEntry
                    {
                        Key = new BencodedValue
                        {
                            Text = new BencodedText("name")
                        },
                        Value = new BencodedValue
                        {
                            Text = new BencodedText(this.entries[0].Name)
                        }
                    },
                    new BencodedEntry
                    {
                        Key = new BencodedValue
                        {
                            Text = new BencodedText("length")
                        },
                        Value = new BencodedValue
                        {
                            Number = new BencodedNumber(this.entries[0].Size)
                        }
                    },
                    new BencodedEntry
                    {
                        Key = new BencodedValue
                        {
                            Text = new BencodedText("pieces")
                        },
                        Value = new BencodedValue
                        {
                            Data = new BencodedData(ComputePieceHashes())
                        }
                    },
                    new BencodedEntry
                    {
                        Key = new BencodedValue
                        {
                            Text = new BencodedText("piece length")
                        },
                        Value = new BencodedValue
                        {
                            Number = new BencodedNumber(16384)
                        }
                    }
                }
            };

            return(entries);
        }
Beispiel #19
0
        public FileHash ToHash()
        {
            BencodedValue entries = Build();

            byte[] bytes = Bencoder.Encode(entries);

            Metainfo metainfo = MetainfoFactory.FromBytes(bytes);
            FileHash hash     = metainfo.Hash;

            return(hash);
        }
Beispiel #20
0
        public static MetainfoFile FromFile(string path)
        {
            byte[]        bytes   = File.ReadAllBytes(path);
            BencodedValue decoded = Bencoder.Decode(bytes);
            BencodedValue info    = decoded.Find("info", x => x);

            Metainfo metainfo = DecodeMetainfo(info);

            string[] trackers = FindTrackers(decoded);

            return(new MetainfoFile(metainfo, trackers));
        }
Beispiel #21
0
        private static void FindTrackerValue(BencodedValue value, HashSet <string> trackers)
        {
            value.Find("announce", node =>
            {
                if (node != null)
                {
                    trackers.Add(node.ToText());
                }

                return(node);
            });
        }
Beispiel #22
0
        private static MetainfoHash[] FindPieces(BencodedValue value)
        {
            byte[] data = value.Find("pieces", x => x.Data.GetBytes());
            List <MetainfoHash> pieces = new List <MetainfoHash>();

            for (int i = 0; i < data.Length; i += 20)
            {
                pieces.Add(new MetainfoHash(Bytes.Copy(data, i, 20)));
            }

            return(pieces.ToArray());
        }
Beispiel #23
0
        private static void FindTrackerList(BencodedValue value, HashSet <string> trackers)
        {
            value.Find("announce-list", node =>
            {
                if (node != null)
                {
                    foreach (string text in node.AllTexts())
                    {
                        if (Uri.IsWellFormedUriString(text, UriKind.Absolute))
                        {
                            trackers.Add(text);
                        }
                    }
                }

                return(node);
            });
        }
Beispiel #24
0
        private static void Decode(BencodedValue bencoded, IDictionary <byte, string> byId, IDictionary <string, byte> byCode)
        {
            BencodedValue received = bencoded.Find("m", x => x);

            if (received?.Dictionary != null)
            {
                foreach (BencodedEntry entry in received.Dictionary)
                {
                    byte?  id   = entry.Value?.Number?.ToByte();
                    string code = entry.Key?.Text?.GetString();

                    if (id != null && code != null)
                    {
                        byId.Add(id.Value, code.ToLower());
                        byCode.Add(code.ToLower(), id.Value);
                    }
                }
            }
        }
Beispiel #25
0
        public static void SendPeers(this CoordinatorService glue, PeerHash peer, params NetworkAddress[] remotes)
        {
            BencodedValue bencoded = new BencodedValue
            {
                Dictionary = new[]
                {
                    new BencodedEntry
                    {
                        Key = new BencodedValue {
                            Text = new BencodedText("added")
                        },
                        Value = new BencodedValue {
                            Data = ToData(remotes)
                        }
                    }
                }
            };

            glue.SendExtension(peer, PeersPlugin.Name, Bencoder.Encode(bencoded));
        }
Beispiel #26
0
        public static void SendMetadataPiece(this CoordinatorService glue, PeerHash peer, int piece, int total, byte[] data)
        {
            BencodedValue bencoded = new BencodedValue
            {
                Dictionary = new[]
                {
                    new BencodedEntry
                    {
                        Key = new BencodedValue {
                            Text = new BencodedText("msg_type")
                        },
                        Value = new BencodedValue {
                            Number = new BencodedNumber(1)
                        }
                    },
                    new BencodedEntry
                    {
                        Key = new BencodedValue {
                            Text = new BencodedText("piece")
                        },
                        Value = new BencodedValue {
                            Number = new BencodedNumber(piece)
                        }
                    },
                    new BencodedEntry
                    {
                        Key = new BencodedValue {
                            Text = new BencodedText("total_size")
                        },
                        Value = new BencodedValue {
                            Number = new BencodedNumber(total)
                        }
                    }
                }
            };

            byte[] payload = Bencoder.Encode(bencoded);

            Bytes.Append(ref payload, data);
            glue.SendExtension(peer, MetadataPlugin.Name, payload);
        }
Beispiel #27
0
        private TcpSocketReceiveCallback OnReceived(TrackerGetHttpEntry entry)
        {
            return(received =>
            {
                if (received.Status == SocketStatus.OK)
                {
                    context.Queue.Add(() =>
                    {
                        byte[] data = Bytes.Copy(entry.Buffer.Data, entry.Buffer.Offset, received.Count);
                        string text = Encoding.ASCII.GetString(data);

                        context.CallPacketReceived(entry.Endpoint, data.Length);

                        if (text.StartsWith(TrackerGetHttpProtocol.ResponseHeader) == false)
                        {
                            context.CallPacketIgnored(entry.Endpoint, data.Length);
                            return;
                        }

                        int counter = 0, position = 0;
                        bool r = false, n = false;

                        for (int i = 0; i < data.Length; i++)
                        {
                            if (data[i] == '\r')
                            {
                                r = true;
                                counter++;
                                continue;
                            }

                            if (data[i] == '\n')
                            {
                                n = true;
                                counter++;
                                continue;
                            }

                            if (counter == 4 && r && n)
                            {
                                position = i;
                                break;
                            }

                            if (counter == 2 && !(r && n))
                            {
                                position = i;
                                break;
                            }

                            counter = 0;
                        }

                        if (position == 0)
                        {
                            context.CallPacketIgnored(entry.Endpoint, data.Length);
                            return;
                        }

                        BencodedValue decoded = Bencoder.Decode(data, position);
                        if (decoded.Dictionary == null)
                        {
                            context.CallPacketIgnored(entry.Endpoint, data.Length);
                            return;
                        }

                        string failure = decoded.Find("failure reason", x => x?.Text?.GetString());
                        if (failure != null)
                        {
                            context.CallFailed(entry.Address, entry.Request.Hash, failure);
                            return;
                        }

                        int?interval = decoded.Find("interval", x => x?.ToInt32());
                        BencodedValue peers = decoded.Find("peers", x => x);

                        if (interval != null && peers.Text != null && peers.Text.Length % 6 == 0)
                        {
                            List <NetworkAddress> result = new List <NetworkAddress>(peers.Text.Length / 6);
                            byte[] bytes = peers.Data.GetBytes();

                            for (int i = 0; i < bytes.Length; i += 6)
                            {
                                int port = Bytes.ReadUInt16(bytes, i + 4);
                                StringBuilder address = new StringBuilder();

                                address.Append(bytes[i].ToString());
                                address.Append('.');
                                address.Append(bytes[i + 1].ToString());
                                address.Append('.');
                                address.Append(bytes[i + 2].ToString());
                                address.Append('.');
                                address.Append(bytes[i + 3].ToString());

                                if (port > 0)
                                {
                                    result.Add(new NetworkAddress(address.ToString(), port));
                                }
                            }

                            collection.Remove(entry.Socket);
                            entry.Callback.Invoke(TimeSpan.FromSeconds(interval.Value));
                            context.CallAnnounced(entry.Address, entry.Request.Hash, TimeSpan.FromSeconds(interval.Value), result.ToArray());
                        }
                    });
                }
            });
        }
Beispiel #28
0
 public static byte[] Encode(BencodedValue value)
 {
     return(new BencoderDecoder().Encode(value));
 }