public void TestSimpleUpload()
        {
            byte[] src  = new byte[ushort.MaxValue];
            byte[] work = null;
            byte[] dest = null;
            new Random().NextBytes(src);
            Hash hashSent = null;
            Guid transfer = Guid.Empty;

            SecureTransfer.Server server = new SecureTransfer.Server(ServerKey, ClientKey.PublicKey, new RegistryStorage());
            server.MaxInboundFileChunk = 1000;
            server.BeginTransfer += (o, e) => { work = new byte[e.TotalSize]; transfer = e.TransferId; };
            server.CompleteTransfer += (o, e) => { dest = work; hashSent = e.ContentHash; };
            server.BytesReceived +=
                (o, e) =>
                    {
                        Assert.AreEqual(transfer, e.TransferId);
                        Assert.AreEqual(src.Length, e.TotalSize);
                        Assert.AreEqual("bla", e.Location);
                        Array.Copy(e.BytesReceived, 0, work, e.WriteOffset, e.BytesReceived.Length);
                    };

            SecureTransfer.Client client = new SecureTransfer.Client(ClientKey, ServerKey.PublicKey,
                (id, name, stream) => server.Receive(stream));

            client.Upload("bla", src.Length, new MemoryStream(src, false));

            Assert.AreEqual(Hash.SHA256(src), hashSent);
            Assert.AreEqual(Hash.SHA256(src), Hash.SHA256(dest));
        }
        public void TestSimpleDownload()
        {
            byte[] src = new byte[ushort.MaxValue];
            MemoryStream dest = new MemoryStream();
            new Random().NextBytes(src);

            SecureTransfer.Server server = new SecureTransfer.Server(ServerKey, ClientKey.PublicKey, new RegistryStorage());
            server.MaxOutboundFileChunk = 1000;
            server.DownloadBytes +=
                (o, e) =>
                {
                    using (MemoryStream ms = new MemoryStream(e.ReadLength))
                    {
                        ms.Write(src, (int)e.ReadOffset, e.ReadLength);
                        e.SetBytes(src.Length, ms.ToArray());
                    }
                };

            SecureTransfer.Client client = new SecureTransfer.Client(ClientKey, ServerKey.PublicKey,
                (id, name, stream) => server.Receive(stream));

            client.Download("bla", dest);
            Assert.AreEqual(Hash.SHA256(src), Hash.SHA256(dest.ToArray()));
        }
        public void TestDownloadOneChunk()
        {
            byte[] src = new byte[1024];
            MemoryStream dest = new MemoryStream();
            new Random().NextBytes(src);
            Hash expectHash = Hash.SHA256(src);

            SecureTransfer.Server server = new SecureTransfer.Server(ServerKey, ClientKey.PublicKey, new RegistryStorage());
            server.MaxOutboundFileChunk = src.Length;
            server.DownloadBytes +=
                (o, e) =>
                {
                    if (e.ReadLength == 0)
                        e.SetBytes(src.Length, null);
                    else
                    {
                        e.SetBytes(src.Length, src);
                        src = null;
                    }
                };

            SecureTransfer.Client client = new SecureTransfer.Client(ClientKey, ServerKey.PublicKey,
                (id, name, stream) => server.Receive(stream));

            client.Download("bla", dest);
            Assert.IsNull(src);
            Assert.AreEqual(expectHash, Hash.SHA256(dest.ToArray()));
        }
        public void TestSendingError()
        {
            int count = 0;
            byte[] src = new byte[1024];
            SecureTransfer.Server server = new SecureTransfer.Server(ServerKey, ClientKey.PublicKey, new RegistryStorage());
            SecureTransfer.Client client = new SecureTransfer.Client(ClientKey, ServerKey.PublicKey,
                (id, name, stream) =>
                {
                    if (++count < 3)
                        return server.Receive(stream);
                    //Bombs after negotiation
                    throw new ApplicationException();
                }
            );

            client.Upload("bla", src.Length, new MemoryStream(src, false));
            Assert.Fail();
        }
        public void TestDownloadFails()
        {
            SecureTransfer.Server server = new SecureTransfer.Server(ServerKey, ClientKey.PublicKey, new RegistryStorage());
            server.MaxOutboundFileChunk = 1000;
            server.DownloadBytes += (o, e) => e.SetBytes(ushort.MaxValue, null);

            SecureTransfer.Client client = new SecureTransfer.Client(ClientKey, ServerKey.PublicKey,
                (id, name, stream) => server.Receive(stream));

            MemoryStream dest = new MemoryStream();
            try
            {
                client.Download("bla", dest);
                Assert.Fail();
            }
            catch(InvalidDataException) { }
        }
        public void TestAbortByEvent()
        {
            SecureTransfer.Server server = new SecureTransfer.Server(ServerKey, ClientKey.PublicKey, new RegistryStorage());
            SecureTransfer.Client client = new SecureTransfer.Client(ClientKey, ServerKey.PublicKey,
                (id, name, stream) => server.Receive(stream));

            client.ProgressChanged += (o, e) => { throw new OperationCanceledException(); };
            using (TempFile file = new TempFile())
            {
                file.WriteAllBytes(new byte[1024]);
                Assert.IsFalse(client.Upload("bla", file.TempPath));
            }
        }
        public void TestAbort()
        {
            byte[] src = new byte[1024];
            SecureTransfer.Server server = new SecureTransfer.Server(ServerKey, ClientKey.PublicKey, new RegistryStorage());
            SecureTransfer.Client client = new SecureTransfer.Client(ClientKey, ServerKey.PublicKey,
                (id, name, stream) => server.Receive(stream));

            client.Abort();
            Assert.IsFalse(client.Upload("bla", src.Length, new MemoryStream(src, false)));
        }
        public void Publish(Uri destination)
        {
            if(_rsaKeyPair == null)
                throw new FileNotFoundException("You must have a client publication key, see the command 'createkeys'", _keyfile);

            Console.WriteLine("Creating site archive...");
            string file = CreateArchiveFile();
            Console.WriteLine("Connecting to server...");
            
            SecureTransfer.Client client =
                new SecureTransfer.Client(
                    _rsaKeyPair.ClientPrivateKey,
                    _rsaKeyPair.ServerPublicKey,
                    (transferid, location, request) =>
                        {
                            byte[] body = IOStream.ReadAllBytes(request);
                            HttpRequestUtil http = new HttpRequestUtil(destination);

                            if (http.Post(_publishUri, "application/binary", body, body.Length) != HttpStatusCode.OK)
                                throw new WebException(String.Format(
                                    "The server returned an invalid response: {0}/{1}", 
                                    (int) http.StatusCode,
                                    http.StatusCode));

                            return new MemoryStream(http.Content);
                        }
                    );
            client.ProgressChanged += ProgressChanged;

            try { client.Upload(Path.GetFileName(file), file); }
            finally { Console.WriteLine(); }

            Console.WriteLine("Complete.");
        }