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