public void InitiateTransfer(CustomConnection connection)
        {
            PeerId id = new PeerId(new Peer("", connection.Uri), rig.Manager);

            id.Connection = connection;
            byte[] data;

            EncryptorFactory.EndCheckEncryption(EncryptorFactory.BeginCheckEncryption(id, 68, null, null, new InfoHash[] { id.TorrentManager.InfoHash }), out data);
            decryptor = id.Decryptor;
            encryptor = id.Encryptor;
            TestHandshake(data, connection);
        }
예제 #2
0
        private void SendMessage(PeerMessage message, CustomConnection connection)
        {
            byte[] b = message.Encode();
            encryptor.Encrypt(b);
            IAsyncResult result = connection.BeginSend(b, 0, b.Length, null, null);

            if (!result.AsyncWaitHandle.WaitOne(5000, true))
            {
                throw new Exception("Message didn't send correctly");
            }
            connection.EndSend(result);
        }
예제 #3
0
        public ConnectionPair(int port)
        {
            socketListener = new TcpListener(IPAddress.Loopback, port);
            socketListener.Start();

            Socket s1a = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            s1a.Connect(IPAddress.Loopback, port);
            Socket s1b = socketListener.AcceptSocket();

            Incoming = new CustomConnection(s1a, true);
            Outgoing = new CustomConnection(s1b, false);
            socketListener.Stop();
        }
        public static PeerMessage ReceiveMessage(CustomConnection connection, IEncryption decryptor, TorrentManager manager)
        {
            byte[] buffer = new byte[4];
            Receive(connection, buffer, 0, buffer.Length);
            decryptor.Decrypt(buffer);

            int count = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(buffer, 0));

            byte[] message = new byte[count + 4];
            Buffer.BlockCopy(buffer, 0, message, 0, 4);

            Receive(connection, message, 4, count);
            decryptor.Decrypt(message, 4, count);

            return(PeerMessage.DecodeMessage(message, 0, message.Length, manager));
        }
        public void TestHandshake(byte[] buffer, CustomConnection connection)
        {
            // 1) Send local handshake
            SendMessage(new HandshakeMessage(rig.Manager.Torrent.infoHash, new string('g', 20), VersionInfo.ProtocolStringV100, true, false), connection);

            // 2) Receive remote handshake
            if (buffer == null || buffer.Length == 0)
            {
                buffer = new byte[68];
                Receive(connection, buffer, 0, 68);
                decryptor.Decrypt(buffer);
            }

            HandshakeMessage handshake = new HandshakeMessage();

            handshake.Decode(buffer, 0, buffer.Length);
            Assert.AreEqual(rig.Engine.PeerId, handshake.PeerId, "#2");
            Assert.AreEqual(VersionInfo.ProtocolStringV100, handshake.ProtocolString, "#3");
            Assert.AreEqual(ClientEngine.SupportsFastPeer, handshake.SupportsFastPeer, "#4");
            Assert.AreEqual(ClientEngine.SupportsExtended, handshake.SupportsExtendedMessaging, "#5");

            // 2) Send local bitfield
            SendMessage(new BitfieldMessage(rig.Manager.Bitfield), connection);

            // 3) Receive remote bitfield - have none
            PeerMessage message = ReceiveMessage(connection);

            Assert.IsTrue(message is HaveNoneMessage || message is BitfieldMessage, "HaveNone");

            // 4) Send a few allowed fast
            SendMessage(new AllowedFastMessage(1), connection);
            SendMessage(new AllowedFastMessage(2), connection);
            SendMessage(new AllowedFastMessage(3), connection);
            SendMessage(new AllowedFastMessage(0), connection);

            // 5) Receive a few allowed fast
            ReceiveMessage(connection);
            ReceiveMessage(connection);
            ReceiveMessage(connection);
            ReceiveMessage(connection);
            ReceiveMessage(connection);
            ReceiveMessage(connection);
            ReceiveMessage(connection);
            ReceiveMessage(connection);
            ReceiveMessage(connection);
            ReceiveMessage(connection);
        }
예제 #6
0
        public void RequestMetadata()
        {
            Setup(false, "path.torrent");
            CustomConnection connection = pair.Incoming;

            // 1) Send local handshake. We've already received the remote handshake as part
            // of the Connect method.
            SendMessage(new HandshakeMessage(rig.Manager.Torrent.infoHash, new string('g', 20), VersionInfo.ProtocolStringV100, true, true), connection);
            ExtendedHandshakeMessage exHand = new ExtendedHandshakeMessage(rig.TorrentDict.LengthInBytes());

            exHand.Supports.Add(LTMetadata.Support);
            SendMessage(exHand, connection);

            // 2) Send all our metadata requests
            int length = (rig.TorrentDict.LengthInBytes() + 16383) / 16384;

            for (int i = 0; i < length; i++)
            {
                SendMessage(new LTMetadata(LTMetadata.Support.MessageId, LTMetadata.eMessageType.Request, i, null), connection);
            }
            // 3) Receive all the metadata chunks
            PeerMessage m;
            var         stream = new MemoryStream();

            while (length > 0 && (m = ReceiveMessage(connection)) != null)
            {
                LTMetadata metadata = m as LTMetadata;
                if (metadata != null)
                {
                    if (metadata.MetadataMessageType == LTMetadata.eMessageType.Data)
                    {
                        stream.Write(metadata.MetadataPiece, 0, metadata.MetadataPiece.Length);
                        length--;
                    }
                }
            }

            // 4) Verify the hash is the same.
            stream.Position = 0;
#if NETSTANDARD1_5
            Assert.Equal(rig.Torrent.InfoHash, new InfoHash(SHA1.Create().ComputeHash(stream)));
#else
            Assert.Equal(rig.Torrent.InfoHash, new InfoHash(new SHA1Managed().ComputeHash(stream)));
#endif
        }
예제 #7
0
        public ConnectionPair(int port)
        {
            socketListener = new TcpListener(IPAddress.Loopback, port);
            socketListener.Start();

            Socket s1a = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            s1a.Connect(IPAddress.Loopback, port);
#if NETSTANDARD1_5
            Socket s1b = socketListener.AcceptSocketAsync().GetAwaiter().GetResult();
#else
            Socket s1b = socketListener.AcceptSocket();
#endif

            Incoming = new CustomConnection(s1a, true);
            Outgoing = new CustomConnection(s1b, false);
            socketListener.Stop();
        }
 public static void Receive(CustomConnection connection, byte[] buffer, int offset, int count)
 {
     while (count > 0)
     {
         var r = connection.BeginReceive(buffer, offset, count, null, null);
         if (!r.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(4)))
         {
             throw new Exception("Could not receive required data");
         }
         int transferred = connection.EndReceive(r);
         if (transferred == 0)
         {
             throw new Exception("The socket was gracefully killed");
         }
         offset += transferred;
         count  -= transferred;
     }
 }
예제 #9
0
        public void SendMetadataCore(string expectedPath)
        {
            CustomConnection connection = pair.Incoming;

            // 1) Send local handshake. We've already received the remote handshake as part
            // of the Connect method.
            SendMessage(new HandshakeMessage(rig.Manager.InfoHash, new string('g', 20), VersionInfo.ProtocolStringV100, true, true), connection);
            ExtendedHandshakeMessage exHand = new ExtendedHandshakeMessage(rig.Torrent.Metadata.Length);

            exHand.Supports.Add(LTMetadata.Support);
            SendMessage(exHand, connection);

            // 2) Receive the metadata requests from the other peer and fulfill them
            byte[]      buffer = rig.Torrent.Metadata;
            int         length = (buffer.Length + 16383) / 16384;
            PeerMessage m;

            while (length > 0 && (m = ReceiveMessage(connection)) != null)
            {
                LTMetadata metadata = m as LTMetadata;
                if (metadata != null)
                {
                    if (metadata.MetadataMessageType == LTMetadata.eMessageType.Request)
                    {
                        metadata = new LTMetadata(LTMetadata.Support.MessageId, LTMetadata.eMessageType.Data, metadata.Piece, buffer);
                        SendMessage(metadata, connection);
                        length--;
                    }
                }
            }

            // We've sent all the pieces. Now we just wait for the torrentmanager to process them all.
            while (rig.Manager.Mode is MetadataMode)
            {
                System.Threading.Thread.Sleep(10);
            }

            Assert.True(File.Exists(expectedPath), "#1");
            Torrent torrent = Torrent.Load(expectedPath);

            Assert.Equal(rig.Manager.InfoHash, torrent.InfoHash);
        }
예제 #10
0
 private PeerMessage ReceiveMessage(CustomConnection connection)
 {
     return(TransferTest.ReceiveMessage(connection, decryptor, rig.Manager));
 }
 PeerMessage ReceiveMessage(CustomConnection connection)
 {
     return(ReceiveMessage(connection, decryptor, rig.Manager));
 }
 void SendMessage(PeerMessage message, CustomConnection connection)
 {
     byte[] b = message.Encode();
     encryptor.Encrypt(b);
     Send(connection, b, 0, b.Length);
 }