public async Task <float> measureDownloadSpeed(Uri uri)
        {
            Contract.Requires(uri != null);
            var req = WebRequest.Create(uri);

            req.Credentials = CredentialCache.DefaultCredentials;
            req.Proxy       = hch.Proxy;
            req.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
            emitProgressEvent(0);
            float speed;

            using (var devNull = new DevNullStream()) {
                using (var resp = await req.GetResponseAsync() as HttpWebResponse) {
                    var len = resp.ContentLength;
                    EventedStream.dataLoadListener cb = (o, bytes) => emitProgressEvent(bytes * 100 / len);
                    using (var str = resp.GetResponseStream()) {
                        devNull.onLoading += cb;
                        sw.Restart();
                        await str.CopyToAsync(devNull);

                        sw.Stop();
                        devNull.onLoading -= cb;
                    }
                    speed = (float)(len / (sw.Elapsed.TotalSeconds));
                }
            }
            return(speed);
        }
        public async Task <float> measureUploadSpeed(Server server, int size = 1024 *482)
        {
            Contract.Requires(server != null);
            Contract.Requires(size >= 0);
            var prefix = new[] {
                (byte)'&',
                (byte)'c',
                (byte)'o',
                (byte)'n',
                (byte)'t',
                (byte)'e',
                (byte)'n',
                (byte)'t',
                (byte)'0',
                (byte)'=',
            };

            stage = Stage.UPLOAD;

            var req = HttpWebRequest.Create(new Uri(server.uri, "upload.php")) as HttpWebRequest;

            req.Method        = "POST";
            req.ContentType   = "application/x-www-form-urlencoded";
            req.CachePolicy   = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
            req.ContentLength = countOfPieces * (defaultSize + prefix.Length);
            req.KeepAlive     = true;

            req.Credentials = CredentialCache.DefaultCredentials;
            req.Proxy       = hch.Proxy;

            emitProgressEvent(0);
            using (var str = req.GetRequestStream()) {
                using (var ums = new RangedRandomBytesStream(defaultSize, (byte)'A', (byte)'z'))
                {
                    int j = 0;
                    EventedStream.dataLoadListener evtListener = (o, bytes) => emitProgressEvent(100 * (j + bytes / defaultSize) / countOfPieces);
                    ums.onLoading += evtListener;
                    sw.Restart();
                    for (; j < countOfPieces; j++)
                    {
                        prefix[8] = (byte)('0' + j);
                        await str.WriteAsync(prefix, 0, prefix.Length);

                        await str.FlushAsync();

                        await ums.CopyToAsync(str);

                        ums.Position = 0;
                        await str.FlushAsync();
                    }
                    sw.Stop();
                    ums.onLoading -= evtListener;
                }
            }

            await req.GetResponseAsync().ContinueWith(t => t.Result.GetResponseStream().Close());

            float speed = (float)(req.ContentLength / (sw.Elapsed.TotalSeconds));

            emitProgressEvent(100);
            emitMeasuredEvent(speed);
            return(speed);
        }