Beispiel #1
0
        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;
                }
            }
        }
Beispiel #2
0
        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;
            }
        }
Beispiel #3
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #9
0
        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();
        }