private void ReadLoop() { if (!Reading) { return; } var _buffer = new byte[1024]; var _signal = new EventSignal <CallbackDetail <int> >(); _signal.Finished += (sender, e) => { if (e.Result.IsFaulted) { Exception exception = e.Result.Exception.GetBaseException(); if (!HttpBasedTransport.IsRequestAborted(exception)) { if (!(exception is IOException)) { m_connection.OnError(exception); } StopReading(true); } return; } int _read = e.Result.Result; if (_read > 0) { // Put chunks in the buffer m_buffer.Add(_buffer, _read); } if (_read == 0) { // Stop any reading we're doing StopReading(true); return; } // Keep reading the next set of data ReadLoop(); if (_read <= _buffer.Length) { // If we read less than we wanted or if we filled the buffer, process it ProcessBuffer(); } }; StreamExtensions.ReadAsync(_signal, m_stream, _buffer); }
public EventSignal <NegotiationResponse> Negotiate(IConnection connection) { return(HttpBasedTransport.GetNegotiationResponse(m_httpClient, connection)); }
private void OpenConnection(IConnection connection, string data, Action initializeCallback, Action <Exception> errorCallback) { // If we're reconnecting add /connect to the url bool _reconnecting = initializeCallback == null; string _url = (_reconnecting ? connection.Url : connection.Url + "connect"); Action <IRequest> _prepareRequest = PrepareRequest(connection); EventSignal <IResponse> _signal; if (shouldUsePost(connection)) { _url += GetReceiveQueryString(connection, data); Debug.WriteLine(string.Format("SSE: POST {0}", _url)); _signal = m_httpClient.PostAsync( _url, request => { _prepareRequest(request); request.Accept = "text/event-stream"; }, new Dictionary <string, string> { { "groups", GetSerializedGroups(connection) } }); } else { _url += GetReceiveQueryStringWithGroups(connection, data); Debug.WriteLine(string.Format("SSE: GET {0}", _url)); _signal = m_httpClient.GetAsync( _url, request => { _prepareRequest(request); request.Accept = "text/event-stream"; }); } _signal.Finished += (sender, e) => { if (e.Result.IsFaulted) { Exception _exception = e.Result.Exception.GetBaseException(); if (!HttpBasedTransport.IsRequestAborted(_exception)) { if (errorCallback != null && Interlocked.Exchange(ref m_initializedCalled, 1) == 0) { errorCallback(_exception); } else if (_reconnecting) { // Only raise the error event if we failed to reconnect connection.OnError(_exception); } } if (_reconnecting) { // Retry Reconnect(connection, data); return; } } else { // Get the reseponse stream and read it for messages IResponse _response = e.Result; Stream _stream = _response.GetResponseStream(); AsyncStreamReader _reader = new AsyncStreamReader( _stream, connection, () => { if (Interlocked.CompareExchange(ref m_initializedCalled, 1, 0) == 0) { initializeCallback(); } }, () => { _response.Close(); Reconnect(connection, data); }); if (_reconnecting) { // Raise the reconnect event if the connection comes back up connection.OnReconnected(); } _reader.StartReading(); // Set the reader for this connection connection.Items[m_readerKey] = _reader; } }; if (initializeCallback != null) { int _tryed = 0; while (true) { _tryed++; Debug.Write("Checking if connection initialized for the '" + _tryed.ToString() + "' time: "); Thread.Sleep(m_connectionTimeout); if (Interlocked.CompareExchange(ref m_initializedCalled, 1, 0) == 0) { if (_tryed < m_connectionRetry) { Debug.WriteLine("failed."); continue; } Debug.WriteLine("giving up."); // Stop the connection Stop(connection); // Connection timeout occurred errorCallback(new TimeoutException()); break; } else { Debug.WriteLine("success."); break; } } } }
private void ProcessChunks() { //Debug.WriteLine("AsyncStreamReader: ProcessChunks"); while (Reading && m_buffer.HasChunks) { string _line = m_buffer.ReadLine(); // No new lines in the buffer so stop processing if (_line == null) { break; } if (!Reading) { return; } // Try parsing the sseEvent SseEvent _sseEvent; if (!SseEvent.TryParse(_line, out _sseEvent)) { continue; } if (!Reading) { return; } //Debug.WriteLine("AsyncStreamReader: SSE READ [{0}]", _sseEvent.ToString()); switch (_sseEvent.Type) { case EventType.Id: m_connection.MessageId = _sseEvent.Data; break; case EventType.Data: if (_sseEvent.Data.Equals("initialized", StringComparison.OrdinalIgnoreCase)) { if (m_initializeCallback != null) { // Mark the connection as started m_initializeCallback(); } } else { if (Reading) { // We don't care about timeout messages here since it will just reconnect // as part of being a long running request bool _timedOutReceived; bool _disconnectReceived; HttpBasedTransport.ProcessResponse( m_connection, _sseEvent.Data, out _timedOutReceived, out _disconnectReceived); if (_disconnectReceived) { m_connection.Stop(); } if (_timedOutReceived) { return; } } } break; } } }