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); }
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; } } } }