using System.Net.WebSockets; using System.Web; using cli.Model; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace cli { public class Streamer: ICommander { private readonly ClientWebSocket _client; private readonly ILogger _logger; private readonly ConnectionSettings _cxSettings; private readonly UserConnectionSettings _userCxSettings; private CommandArgument _sourceArg; private CommandArgument _destArg; private CancellationTokenSource _tokenSource; public Streamer(ILoggerFactory loggerFactory, IOptions cxSettings, IOptions userCxSettings ) { _logger = loggerFactory.CreateLogger(); _cxSettings = cxSettings.Value; _userCxSettings = userCxSettings.Value; _client = new ClientWebSocket(); _client.Options.SetRequestHeader("Authorization", $"Bearer {_userCxSettings.AccessToken}"); } public CommandLineApplication Integrate(CommandLineApplication rootApp) { CommandLineApplication streamCmd = rootApp.Command("nstream", (target) => { target.FullName = "Stream to server"; target.Description = "Stream arbitrary binary data to your server channel"; _sourceArg = target.Argument("source", "Source file to send, use '-' for standard input", false); _destArg = target.Argument("destination", "destination file name", false); target.HelpOption("-? | -h | --help"); }); streamCmd.OnExecute(async() => await DoExecute()); return streamCmd; } private async Task DoExecute() { if (_sourceArg.Value != "-") { var fi = new FileInfo(_sourceArg.Value); if (!fi.Exists) { _logger.LogError("Input file doesn´t exist."); return -2; } using (var stream = fi.OpenRead()) { _logger.LogInformation("DoExecute from given file"); await DoStream(stream); } return 0; } else { using(var stream = Console.OpenStandardInput()) { _logger.LogInformation("DoExecute from standard input"); await DoStream(stream); } return 0; } } async Task DoStream (Stream stream) { _tokenSource = new CancellationTokenSource(); var url = _cxSettings.StreamingUrl + "/" + HttpUtility.UrlEncode(_destArg.Value); _logger.LogInformation("Connecting to " + url); await _client.ConnectAsync(new Uri(url), _tokenSource.Token); _logger.LogInformation("Connected"); const int bufLen = Yavsc.YavscConstants.WebSocketsMaxBufLen; byte [] buffer = new byte[bufLen]; const int offset=0; int read; bool lastFrame; WebSocketMessageType pckType = WebSocketMessageType.Binary; do { read = await stream.ReadAsync(buffer, offset, bufLen); lastFrame = read < Yavsc.YavscConstants.WebSocketsMaxBufLen; ArraySegment segment = new ArraySegment(buffer, offset, read); await _client.SendAsync(segment, pckType, lastFrame, _tokenSource.Token); _logger.LogInformation($"sent {segment.Count} "); } while (!lastFrame); _logger.LogInformation($"Closing socket"); await _client.CloseAsync(WebSocketCloseStatus.NormalClosure, "EOF", _tokenSource.Token); } } }