private async void AddRelay(string filename) { try { IRelay relay; var file = new FileInfo(filename); var stream = file.OpenRead(); string code; if (remote) { relay = new SocketRelayClient(); code = await(relay as SocketRelayClient).AddRelay(new Uri(remoteHost), stream, file.Name); } else { relay = new LocalRelay(stream, file.Name); code = server.AddRelay(relay); } relay.OnComplete += () => stream.Close(); relay.OnCancel += () => stream.Close(); AddRelayStatus(file.FullName, file.Length, urlBase + code, relay); Clipboard.SetDataObject(urlBase + code, true); } catch (Exception e) { MessageBox.Show(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); if (relayStatus.Relays.Count == 1 && !stayOpen) { Shutdown(); } } }
private static void HandleRelay(Stream stream, Options options) { IRelay relay; string code, urlBase = options.ListenPrefix.Replace("*", HostName).Replace("+", HostName).Replace(":80", ""); var done = new TaskCompletionSource <bool>(); Task <bool> listenTask = null; if (!string.IsNullOrEmpty(options.RemoteHost)) { relay = new SocketRelayClient(); code = (relay as SocketRelayClient).AddRelay(new Uri(options.RemoteHost), stream, options.FinalFilename, options.FinalContentType).Result; urlBase = options.RemoteHost.Replace("ws", "http"); } else if (options.ListenPrefix.AlreadyListening()) { // if something is listening on the requested port, assume it's our service and try to connect to it.. try { relay = new SocketRelayClient(); code = (relay as SocketRelayClient).AddRelay(new Uri(urlBase.Replace("http", "ws")), stream, options.FinalFilename, options.FinalContentType).Result; } catch (Exception e) { throw new Exception($"Another process is already listening on {options.ListenPrefix}\r\n" + "Try a different port or install the service to avoid this error.", e); } } else { relay = new LocalRelay(stream, options.FinalFilename, options.FinalContentType); var server = new RelayServer() { AcceptSocketConnections = false }; code = server.AddRelay(relay); listenTask = server.Listen(options.ListenPrefix, options.MaxConnections.Value, done); if (listenTask.IsFaulted) { throw listenTask.Exception.InnerException; } } int lastLen = Console.BufferWidth - 1; void PrintStatus(string status) { string line = string.Format("Status: {0}", status); int lineLen = line.Length; if (lineLen < lastLen) { line = line.PadRight(lastLen); } lastLen = lineLen; Console.CursorLeft = 0; Console.Write(line); } relay.OnStart += () => PrintStatus("download starting.."); relay.OnComplete += () => { PrintStatus("download complete"); done.TrySetResult(true); }; relay.OnDisconnect += () => PrintStatus("disconnected, waiting for resume.."); relay.OnCancel += () => { PrintStatus("canceled"); done.TrySetResult(false); }; long lastDownloaded = 0; double lastLastBps = 0, lastBps = 0, inverseTotal = (stream.CanSeek && stream.Length > 0) ? 100.0 / stream.Length : 1.0; void ProgressUpdate(long downloaded, long?total) { double bps = downloaded - lastDownloaded; bps = (bps + (lastBps > 0 ? lastBps : bps) + (lastLastBps > 0 ? lastLastBps : bps)) / 3.0; lastLastBps = lastBps; lastBps = bps; lastDownloaded = downloaded; if (total.HasValue) { var remaining = bps > 0 ? TimeSpan.FromSeconds((total.Value - downloaded) / bps).ToString("hh\\:mm\\:ss") : "--:--:--"; PrintStatus($"{downloaded.FormatBytes()} ({downloaded * inverseTotal:0}%) downloaded, time remaining {remaining} (at {((long)bps).FormatBytes()}/sec)"); } else { PrintStatus($"{downloaded.FormatBytes()} downloaded (at {((long)bps).FormatBytes()}/sec)"); } } relay.OnProgress += (transferred, total) => ProgressUpdate(transferred, total); Console.WriteLine($"Download link: {urlBase.TrimEnd('/')}/{code}"); Console.WriteLine($"Press {(Console.IsInputRedirected ? "CTRL+C" : "any key")} to cancel"); Console.WriteLine(); PrintStatus("waiting for connection.."); if (Console.IsInputRedirected) { Console.CancelKeyPress += (e, args) => { done.TrySetResult(false); relay.Cancel(); }; done.Task.Wait(); } else { while (!done.Task.IsCompleted) { Thread.Sleep(100); if (Console.KeyAvailable) { done.TrySetResult(false); relay.Cancel(); } } } if (listenTask != null && listenTask.IsFaulted) { PrintStatus("error"); Console.WriteLine(); throw listenTask.Exception.InnerException; } if (done.Task.Result) { PrintStatus("completed successfully"); } else { PrintStatus("canceled"); } }