public void Int64_ToBytes_ReturnsExpectedValue(long input, long expectedResult)
        {
            // Act
            var result = PackHelper.Int64(input);

            // Assert
            result.Should().ContainInOrder(BitConverter.GetBytes(expectedResult));
        }
        public AnnounceInfo Announce(string url, string hash, string peerId, Int64 bytesDownloaded, Int64 bytesLeft, Int64 bytesUploaded,
                                     Int32 eventTypeFilter, Int32 ipAddress, Int32 numWant, Int32 listenPort, Int32 extensions)
        {
            List <IPEndPoint> returnValue = new List <IPEndPoint>();

            this.ValidateInput(url, new[] { hash }, ScraperType.UDP);

            this._currentConnectionId = this.BaseCurrentConnectionId;
            Int32 trasactionId = this.Random.Next(0, 65535);

            UdpClient udpClient = new UdpClient(this.Tracker, this.Port)
            {
                DontFragment = true,
                Client       =
                {
                    SendTimeout    = this.Timeout * 1000,
                    ReceiveTimeout = this.Timeout * 1000
                }
            };

            byte[] sendBuf = this._currentConnectionId.Concat(PackHelper.Int32(0)).Concat(PackHelper.Int32(trasactionId)).ToArray();
            udpClient.Send(sendBuf, sendBuf.Length);

            IPEndPoint endPoint = null;

            byte[] recBuf;

            try
            {
                recBuf = udpClient.Receive(ref endPoint);
            }
            catch (Exception)
            {
                return(null);
            }

            if (recBuf == null)
            {
                throw new NoNullAllowedException("udpClient failed to receive");
            }

            if (recBuf.Length < 0)
            {
                throw new InvalidOperationException("udpClient received no response");
            }

            if (recBuf.Length < 16)
            {
                throw new InvalidOperationException("udpClient did not receive entire response");
            }

            UInt32 recAction       = UnpackHelper.UInt32(recBuf, 0, UnpackHelper.Endianness.Big);
            UInt32 recTrasactionId = UnpackHelper.UInt32(recBuf, 4, UnpackHelper.Endianness.Big);

            if (recAction != 0 || recTrasactionId != trasactionId)
            {
                throw new Exception("Invalid response from tracker");
            }

            this._currentConnectionId = CopyBytes(recBuf, 8, 8);

            byte[] hashBytes = PackHelper.Hex(hash).ToArray();

            Int32 key = this.Random.Next(0, 65535);

            sendBuf = this._currentConnectionId.                      /*connection id*/
                      Concat(PackHelper.Int32(1)).                    /*action*/
                      Concat(PackHelper.Int32(trasactionId)).         /*trasaction Id*/
                      Concat(hashBytes).                              /*hash*/
                      Concat(Encoding.ASCII.GetBytes(peerId)).        /*my peer id*/
                      Concat(PackHelper.Int64(bytesDownloaded)).      /*bytes downloaded*/
                      Concat(PackHelper.Int64(bytesLeft)).            /*bytes left*/
                      Concat(PackHelper.Int64(bytesUploaded)).        /*bytes uploaded*/
                      Concat(PackHelper.Int32(eventTypeFilter)).      /*event, 0 for none, 2 for just started*/
                      Concat(PackHelper.Int32(ipAddress)).            /*ip, 0 for this one*/
                      Concat(PackHelper.Int32(key)).                  /*unique key*/
                      Concat(PackHelper.Int32(numWant)).              /*num want, -1 for as many as pos*/
                      Concat(PackHelper.Int32(listenPort)).           /*listen port*/
                      Concat(PackHelper.Int32(extensions)).ToArray(); /*extensions*/
            udpClient.Send(sendBuf, sendBuf.Length);

            try
            {
                recBuf = udpClient.Receive(ref endPoint);
            }
            catch (Exception)
            {
                return(null);
            }

            recAction       = UnpackHelper.UInt32(recBuf, 0, UnpackHelper.Endianness.Big);
            recTrasactionId = UnpackHelper.UInt32(recBuf, 4, UnpackHelper.Endianness.Big);

            int waitTime = (int)UnpackHelper.UInt32(recBuf, 8, UnpackHelper.Endianness.Big);
            int Leechers = (int)UnpackHelper.UInt32(recBuf, 12, UnpackHelper.Endianness.Big);
            int seeders  = (int)UnpackHelper.UInt32(recBuf, 16, UnpackHelper.Endianness.Big);

            if (recAction != 1 || recTrasactionId != trasactionId)
            {
                throw new Exception("Invalid response from tracker");
            }

            for (Int32 i = 20; i < recBuf.Length; i += 6)
            {
                UInt32 ip   = UnpackHelper.UInt32(recBuf, i, UnpackHelper.Endianness.Big);
                UInt16 port = UnpackHelper.UInt16(recBuf, i + 4, UnpackHelper.Endianness.Big);

                returnValue.Add(new IPEndPoint(ip, port));
            }

            udpClient.Close();

            return(new AnnounceInfo(returnValue, waitTime, seeders, Leechers));
        }