public void UpdateFromFrame(SettingsFrame frame, IFlowControlManager flowControlStateManager) { if (frame.EnablePush.HasValue) { EnablePush = frame.EnablePush.Value; } if (frame.HeaderTableSize.HasValue) { HeaderTableSize = frame.HeaderTableSize.Value; } if (frame.MaxConcurrentStreams.HasValue) { MaxConcurrentStreams = frame.MaxConcurrentStreams.Value; } if (frame.MaxFrameSize.HasValue) { MaxFrameSize = frame.MaxFrameSize.Value; } if (frame.MaxHeaderListSize.HasValue) { MaxHeaderListSize = frame.MaxHeaderListSize.Value; } if (frame.InitialWindowSize.HasValue) { InitialWindowSize = frame.InitialWindowSize.Value; // Try and update the flow control manager's initial size if (flowControlStateManager != null) { flowControlStateManager.InitialWindowSize = InitialWindowSize; } } }
public void UpdateFromFrame (SettingsFrame frame, IFlowControlManager flowControlStateManager) { if (frame.EnablePush.HasValue) EnablePush = frame.EnablePush.Value; if (frame.HeaderTableSize.HasValue) HeaderTableSize = frame.HeaderTableSize.Value; if (frame.MaxConcurrentStreams.HasValue) MaxConcurrentStreams = frame.MaxConcurrentStreams.Value; if (frame.MaxFrameSize.HasValue) MaxFrameSize = frame.MaxFrameSize.Value; if (frame.MaxHeaderListSize.HasValue) MaxHeaderListSize = frame.MaxHeaderListSize.Value; if (frame.InitialWindowSize.HasValue) { InitialWindowSize = frame.InitialWindowSize.Value; // Try and update the flow control manager's initial size if (flowControlStateManager != null) flowControlStateManager.InitialWindowSize = InitialWindowSize; } }
async void read() { int rx = 0; byte[] b = new byte[4096]; while (true) { try { rx = await clientStream.ReadAsync(b, 0, b.Length); } catch { rx = -1; } if (rx > 0) { Console.WriteLine("RX: {0} bytes", rx); for (int i = 0; i < rx; i++) { buffer.Add(b [i]); } while (true) { // We need at least 9 bytes to process the frame // 9 octets is the frame header length if (buffer.Count < 9) { break; } // Find out the frame length // which is a 24 bit uint, so we need to convert this as c# uint is 32 bit var flen = new byte[4]; flen [0] = 0x0; flen [1] = buffer.ElementAt(0); flen [2] = buffer.ElementAt(1); flen [3] = buffer.ElementAt(2); var frameLength = BitConverter.ToUInt32(flen.EnsureBigEndian(), 0); // If we are expecting a payload that's bigger than what's in our buffer // we should keep reading from the stream if (buffer.Count - 9 < frameLength) { break; } // If we made it this far, the buffer has all the data we need, let's get it out to process var data = buffer.GetRange(0, (int)frameLength + 9).ToArray(); // remove the processed info from the buffer buffer.RemoveRange(0, (int)frameLength + 9); // Get the Frame Type so we can instantiate the right subclass var frameType = data [3]; // 4th byte in frame header is TYPE // Don't need the flags yet //var frameFlags = data [4]; // 5th byte is FLAGS // we need to turn the stream id into a uint var frameStreamIdData = new byte[4]; Array.Copy(data, 5, frameStreamIdData, 0, 4); uint frameStreamId = Util.ConvertFromUInt31(frameStreamIdData.EnsureBigEndian()); Frame frame = null; var ft = (FrameType)frameType; switch (ft) { case FrameType.Data: frame = new DataFrame(); break; case FrameType.Headers: frame = new HeadersFrame(); break; case FrameType.Priority: frame = new PriorityFrame(); break; case FrameType.RstStream: frame = new RstStreamFrame(); break; case FrameType.Settings: frame = new SettingsFrame(); break; case FrameType.PushPromise: frame = new PushPromiseFrame(); break; case FrameType.Ping: frame = new PingFrame(); break; case FrameType.GoAway: frame = new GoAwayFrame(); break; case FrameType.WindowUpdate: frame = new WindowUpdateFrame(); break; case FrameType.Continuation: frame = new ContinuationFrame(); break; } try { // Call the specific subclass implementation to parse if (frame != null) { frame.Parse(data); } } catch (Exception ex) { Console.WriteLine("Parsing Frame Failed: " + ex); throw ex; } // If we are waiting on the connection preface from server // and it's the right frame type, set our resetevent if (ft == FrameType.Settings && resetEventConnectionSettingsFrame != null && !resetEventConnectionSettingsFrame.IsSet) { var settingsFrame = frame as SettingsFrame; // ack the settings from the server settingsFrame.Ack = true; await SendFrame(settingsFrame); resetEventConnectionSettingsFrame.Set(); } try { if (frameStreamId == 0) { foreach (var s in Streams) { if (s.Value.State != StreamState.Closed) { s.Value.ProcessFrame(frame); } } } else { var stream = await GetStream(frameStreamId); stream.ProcessFrame(frame); } } catch (Exception ex) { Console.WriteLine("Error Processing Frame: " + ex); throw ex; } } } else { // TODO: Connection error //throw new Exception ("Connection Error"); break; } } Disconnect(); }
public async Task Connect() { if (IsConnected()) { return; } tcp = new TcpClient { // Disable Nagle for HTTP/2 NoDelay = true }; await tcp.ConnectAsync(ConnectionSettings.Host, (int)ConnectionSettings.Port).ConfigureAwait(false); if (ConnectionSettings.UseTls) { sslStream = new SslStream(tcp.GetStream(), false, (sender, certificate, chain, sslPolicyErrors) => true); #if NETCOREAPP2_1 // .NET Core 2.1 introduces SslClientAuthenticationOptions // which allows us to set the SslApplicationProtocol (ALPN) which // for HTTP/2 is required, and should be set to h2 for direct to TLS connections // (h2c should be set for upgraded connections) var authOptions = new SslClientAuthenticationOptions { ApplicationProtocols = new List <SslApplicationProtocol> { SslApplicationProtocol.Http2 }, // ALPN h2 EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12, TargetHost = ConnectionSettings.Host, ClientCertificates = ConnectionSettings.Certificates ?? new X509CertificateCollection() }; await sslStream.AuthenticateAsClientAsync( authOptions, new CancellationToken(false)) .ConfigureAwait(false); #else // Fall back to no ALPN support for frameworks which don't support it await sslStream.AuthenticateAsClientAsync( ConnectionSettings.Host, ConnectionSettings.Certificates ?? new X509CertificateCollection(), System.Security.Authentication.SslProtocols.Tls12, false).ConfigureAwait(false); #endif clientStream = sslStream; } else { clientStream = tcp.GetStream(); } // Ensure we have a size for the stream '0' flowControlManager.GetWindowSize(0); // Send out preface data var prefaceData = System.Text.Encoding.ASCII.GetBytes(ConnectionPreface); await clientStream.WriteAsync(prefaceData, 0, prefaceData.Length).ConfigureAwait(false); await clientStream.FlushAsync().ConfigureAwait(false); // Start reading the stream on another thread var readTask = Task.Factory.StartNew(() => { try { Read(); } catch (Exception ex) { Log.Debug("Read error: " + ex); Disconnect(); } }, TaskCreationOptions.LongRunning); readTask.ContinueWith(t => { // TODO: Handle the error Disconnect(); }, TaskContinuationOptions.OnlyOnFaulted).Forget(); // Start a thread to handle writing queued frames to the stream var writeTask = Task.Factory.StartNew(Write, TaskCreationOptions.LongRunning); writeTask.ContinueWith(t => { // TODO: Handle the error Disconnect(); }, TaskContinuationOptions.OnlyOnFaulted).Forget(); // Send initial blank settings frame var s = new SettingsFrame(); if (ConnectionSettings.DisablePushPromise) { s.EnablePush = false; } await QueueFrame(s).ConfigureAwait(false); }
public async Task Connect() { if (IsConnected()) { return; } tcp = new TcpClient { // Disable Nagle for HTTP/2 NoDelay = true }; await tcp.ConnectAsync(ConnectionSettings.Host, (int)ConnectionSettings.Port).ConfigureAwait(false); if (ConnectionSettings.UseTls) { sslStream = new SslStream(tcp.GetStream(), false, (sender, certificate, chain, sslPolicyErrors) => true); await sslStream.AuthenticateAsClientAsync( ConnectionSettings.Host, ConnectionSettings.Certificates ?? new X509CertificateCollection(), System.Security.Authentication.SslProtocols.Tls12, false).ConfigureAwait(false); clientStream = sslStream; } else { clientStream = tcp.GetStream(); } // Ensure we have a size for the stream '0' flowControlManager.GetWindowSize(0); // Send out preface data var prefaceData = System.Text.Encoding.ASCII.GetBytes(ConnectionPreface); await clientStream.WriteAsync(prefaceData, 0, prefaceData.Length).ConfigureAwait(false); await clientStream.FlushAsync().ConfigureAwait(false); // Start reading the stream on another thread var readTask = Task.Factory.StartNew(() => { try { Read(); } catch (Exception ex) { Log.Debug("Read error: " + ex); Disconnect(); } }, TaskCreationOptions.LongRunning); readTask.ContinueWith(t => { // TODO: Handle the error Disconnect(); }, TaskContinuationOptions.OnlyOnFaulted).Forget(); // Start a thread to handle writing queued frames to the stream var writeTask = Task.Factory.StartNew(Write, TaskCreationOptions.LongRunning); writeTask.ContinueWith(t => { // TODO: Handle the error Disconnect(); }, TaskContinuationOptions.OnlyOnFaulted).Forget(); // Send initial blank settings frame var s = new SettingsFrame(); if (ConnectionSettings.DisablePushPromise) { s.EnablePush = false; } await QueueFrame(s).ConfigureAwait(false); }
public void Connect() { if (IsConnected()) { return; } tcp = new TcpClient(); // Disable Nagle for HTTP/2 tcp.NoDelay = true; tcp.Connect(ConnectionSettings.Host, (int)ConnectionSettings.Port); if (ConnectionSettings.UseTls) { sslStream = new SslStream(tcp.GetStream(), false, (sender, certificate, chain, sslPolicyErrors) => true); sslStream.AuthenticateAsClient( ConnectionSettings.Host, ConnectionSettings.Certificates ?? new X509CertificateCollection(), System.Security.Authentication.SslProtocols.Tls, false); clientStream = sslStream; } else { clientStream = tcp.GetStream(); } // Ensure we have a size for the stream '0' flowControlManager.GetWindowSize(0); // Send out preface data var prefaceData = System.Text.Encoding.ASCII.GetBytes(ConnectionPreface); clientStream.Write(prefaceData, 0, prefaceData.Length); clientStream.Flush(); // Start reading the stream on another thread var readTask = new Thread(() => { try { read(); } catch (Exception ex) { Log.Debug("Read error: " + ex); Disconnect(); } Disconnect(); }); readTask.Start(); // Start a thread to handle writing queued frames to the stream var writeTask = new Thread(() => { try { write(); } catch { Disconnect(); } }); writeTask.Start(); // Send initial blank settings frame var s = new SettingsFrame(); if (ConnectionSettings.DisablePushPromise) { s.EnablePush = false; } QueueFrame(s); }
public async Task Connect() { if (IsConnected()) { return; } tcp = new TcpClient(); // Disable Nagle for HTTP/2 tcp.NoDelay = true; await tcp.ConnectAsync(ConnectionSettings.Host, (int)ConnectionSettings.Port).ConfigureAwait(false); try { if (ConnectionSettings.UseTls) { clientStream = await ConnectionSettings.CreateStream(tcp); } else { clientStream = tcp.GetStream(); } } catch { if (!IsConnected()) { tcp.Close(); } throw; } // Ensure we have a size for the stream '0' flowControlManager.GetWindowSize(0); // Send out preface data var prefaceData = System.Text.Encoding.ASCII.GetBytes(ConnectionPreface); await clientStream.WriteAsync(prefaceData, 0, prefaceData.Length).ConfigureAwait(false); await clientStream.FlushAsync().ConfigureAwait(false); // Start reading the stream on another thread var readTask = Task.Factory.StartNew(() => { try { read(); } catch (Exception ex) { Log.Debug("Read error: " + ex); Disconnect(); } }, TaskCreationOptions.LongRunning); readTask.ContinueWith(t => { // TODO: Handle the error Disconnect(); }, TaskContinuationOptions.OnlyOnFaulted).Forget(); // Start a thread to handle writing queued frames to the stream var writeTask = Task.Factory.StartNew <Task>(write, TaskCreationOptions.LongRunning); writeTask.ContinueWith(t => { // TODO: Handle the error Disconnect(); }, TaskContinuationOptions.OnlyOnFaulted).Forget(); // Send initial blank settings frame var s = new SettingsFrame(); if (ConnectionSettings.DisablePushPromise) { s.EnablePush = false; } await QueueFrame(s).ConfigureAwait(false); }
public async Task Connect () { if (IsConnected ()) return; tcp = new TcpClient (); // Disable Nagle for HTTP/2 tcp.NoDelay = true; await tcp.ConnectAsync (ConnectionSettings.Host, (int)ConnectionSettings.Port); if (ConnectionSettings.UseTls) { sslStream = new SslStream (tcp.GetStream (), false, (sender, certificate, chain, sslPolicyErrors) => true); await sslStream.AuthenticateAsClientAsync ( ConnectionSettings.Host, ConnectionSettings.Certificates ?? new X509CertificateCollection (), System.Security.Authentication.SslProtocols.Tls12, false); clientStream = sslStream; } else { clientStream = tcp.GetStream (); } // Ensure we have a size for the stream '0' flowControlManager.GetWindowSize (0); // Send out preface data var prefaceData = System.Text.Encoding.ASCII.GetBytes (ConnectionPreface); await clientStream.WriteAsync (prefaceData, 0, prefaceData.Length); await clientStream.FlushAsync (); // Start reading the stream on another thread var readTask = Task.Factory.StartNew (() => { try { read (); } catch (Exception ex) { Log.Debug ("Read error: " + ex); Disconnect (); } }, TaskCreationOptions.LongRunning); readTask.ContinueWith (t => { // TODO: Handle the error Disconnect (); }, TaskContinuationOptions.OnlyOnFaulted); // Start a thread to handle writing queued frames to the stream var writeTask = Task.Factory.StartNew (write, TaskCreationOptions.LongRunning); writeTask.ContinueWith (t => { // TODO: Handle the error Disconnect (); }, TaskContinuationOptions.OnlyOnFaulted); // Send initial blank settings frame var s = new SettingsFrame (); if (ConnectionSettings.DisablePushPromise) s.EnablePush = false; await QueueFrame (s); }
async void read () { int rx = 0; byte[] b = new byte[4096]; while (true) { try { rx = await clientStream.ReadAsync(b, 0, b.Length); } catch { rx = -1; } if (rx > 0) { Console.WriteLine ("RX: {0} bytes", rx); for (int i = 0; i < rx; i++) buffer.Add (b [i]); while (true) { // We need at least 9 bytes to process the frame // 9 octets is the frame header length if (buffer.Count < 9) break; // Find out the frame length // which is a 24 bit uint, so we need to convert this as c# uint is 32 bit var flen = new byte[4]; flen [0] = 0x0; flen [1] = buffer.ElementAt (0); flen [2] = buffer.ElementAt (1); flen [3] = buffer.ElementAt (2); var frameLength = BitConverter.ToUInt32 (flen.EnsureBigEndian (), 0); // If we are expecting a payload that's bigger than what's in our buffer // we should keep reading from the stream if (buffer.Count - 9 < frameLength) break; // If we made it this far, the buffer has all the data we need, let's get it out to process var data = buffer.GetRange (0, (int)frameLength + 9).ToArray (); // remove the processed info from the buffer buffer.RemoveRange (0, (int)frameLength + 9); // Get the Frame Type so we can instantiate the right subclass var frameType = data [3]; // 4th byte in frame header is TYPE // Don't need the flags yet //var frameFlags = data [4]; // 5th byte is FLAGS // we need to turn the stream id into a uint var frameStreamIdData = new byte[4]; Array.Copy (data, 5, frameStreamIdData, 0, 4); uint frameStreamId = Util.ConvertFromUInt31 (frameStreamIdData.EnsureBigEndian ()); Frame frame = null; var ft = (FrameType)frameType; switch (ft) { case FrameType.Data: frame = new DataFrame (); break; case FrameType.Headers: frame = new HeadersFrame (); break; case FrameType.Priority: frame = new PriorityFrame (); break; case FrameType.RstStream: frame = new RstStreamFrame (); break; case FrameType.Settings: frame = new SettingsFrame (); break; case FrameType.PushPromise: frame = new PushPromiseFrame (); break; case FrameType.Ping: frame = new PingFrame (); break; case FrameType.GoAway: frame = new GoAwayFrame (); break; case FrameType.WindowUpdate: frame = new WindowUpdateFrame (); break; case FrameType.Continuation: frame = new ContinuationFrame (); break; } try { // Call the specific subclass implementation to parse if (frame != null) frame.Parse (data); } catch (Exception ex) { Console.WriteLine ("Parsing Frame Failed: " + ex); throw ex; } // If we are waiting on the connection preface from server // and it's the right frame type, set our resetevent if (ft == FrameType.Settings && resetEventConnectionSettingsFrame != null && !resetEventConnectionSettingsFrame.IsSet) { var settingsFrame = frame as SettingsFrame; // ack the settings from the server settingsFrame.Ack = true; await SendFrame (settingsFrame); resetEventConnectionSettingsFrame.Set (); } try { if (frameStreamId == 0) { foreach (var s in Streams) { if (s.Value.State != StreamState.Closed) s.Value.ProcessFrame(frame); } } else { var stream = await GetStream(frameStreamId); stream.ProcessFrame(frame); } } catch (Exception ex) { Console.WriteLine ("Error Processing Frame: " + ex); throw ex; } } } else { // TODO: Connection error //throw new Exception ("Connection Error"); break; } } Disconnect(); }