public HostWebSocket CreateWebSocket(int id, string url, string[] protocols, dynamic callback) { InfoLog?.Invoke(this, $"{nameof(CreateWebSocket)}(url = {url}, protocols = {protocols?.ToDelimitedString(",").Bracket("[", "]")}, callback)"); var socket = new HostWebSocket(id, url, protocols ?? Enumerable.Empty <string>(), callback, _scheduler); ServiceCreated?.Invoke(this, socket); return(socket); }
public void ClearTimeout(int id) { InfoLog?.Invoke(this, $"{nameof(ClearTimeout)}(id = {id})"); if (!_cancellationTokenSources.TryGetValue(id, out var s)) { return; } s.Cancel(); }
public void CancelAll() { // Materialize before looping to prevent InvalidOperationException: // "Collection was modified; enumeration operation may not execute." foreach (var e in _cancellationTokenSources.ToArray()) { InfoLog?.Invoke(this, $"{nameof(CancelAll)}(id = {e.Key})"); e.Value.Cancel(); } }
public void Abort(int id) { InfoLog?.Invoke(this, $"{nameof(Abort)}(id = {id})"); if (!_cancellationTokenSources.TryGetValue(id, out var s)) { return; } _cancellationTokenSources.Remove(id); s.Cancel(); }
public int SetTimeout(Action callback, int milliseconds) { var id = ++_id; InfoLog?.Invoke(this, $"{nameof(SetTimeout)}(callback, milliseconds = {milliseconds}) -> {id}"); var cancellationTokenSource = _cancellationTokenSources[id] = new CancellationTokenSource(); Schedule( $"{nameof(TimerService)}[{id}]", cancellationTokenSource.Token, async cancellationToken => { await Task.Delay(milliseconds, cancellationToken); callback(); }, onFinally: () => { _cancellationTokenSources.Remove(id); cancellationTokenSource.Dispose(); }); return(id); }
public void Send(int id, string method, string url, bool async, object[] headers, object data, dynamic callback) { InfoLog?.Invoke(this, $"{nameof(Send)}(method = {method}, url = {url}, async = {async}) -> [{id}]"); var httpMethod = "GET".Equals(method, StringComparison.OrdinalIgnoreCase) ? HttpMethod.Get : "POST".Equals(method, StringComparison.OrdinalIgnoreCase) ? HttpMethod.Post : throw new NotSupportedException("Unsupported HTTP method: " + method); HttpContent content; switch (data) { case null: content = null; break; case string dataString: content = new StringContent(dataString); break; default: throw new NotSupportedException("Unsupported HTTP method: " + method); } var request = new HttpRequestMessage(httpMethod, url) { Content = content }; foreach (object[] kv in headers as IEnumerable) { var name = (string)kv[0]; var value = (string)kv[1]; var requestHeaders = name.StartsWith("Content-", StringComparison.OrdinalIgnoreCase) || name.Equals("Expires", StringComparison.OrdinalIgnoreCase) || name.Equals("Last-Modified", StringComparison.OrdinalIgnoreCase) || name.Equals("Allow", StringComparison.OrdinalIgnoreCase) ? (HttpHeaders)content.Headers : request.Headers; requestHeaders.Remove(name); requestHeaders.Add(name, value); } var cancellationTokenSource = new CancellationTokenSource(); _cancellationTokenSources.Add(id, cancellationTokenSource); Schedule( $"{nameof(XhrService)}[{id}]", cancellationTokenSource.Token, async cancellationToken => { var response = await HttpClient.SendAsync(request, cancellationToken); var statusCode = (int)response.StatusCode; if (statusCode >= 200 && statusCode < 300) { InfoLog?.Invoke(this, $"[{id}] {statusCode} {response.ReasonPhrase} ({response.Content.Headers.ContentType})"); } else { WarnLog?.Invoke(this, null, $"[{id}] {statusCode} {response.ReasonPhrase} ({response.Content.Headers.ContentType})"); } var str = await response.Content.ReadAsStringAsync(); callback(null, statusCode, response.ReasonPhrase, new[] { new[] { "Content-Type", response.Content.Headers.ContentType.MediaType } }, str); }, onError: e => callback(e.GetBaseException().Message), onFinally: () => { _cancellationTokenSources.Remove(id); cancellationTokenSource.Dispose(); }); }
public void Load(string module) { InfoLog?.Invoke(this, $"load: {module}"); _loader(module); }