/// <summary> /// Gets or creates a new stream for the dictionary. /// </summary> /// <param name="streamId">The stream id.</param> /// <returns>The current stream.</returns> internal ContextStream GetStream(int streamId) { ContextStream stream; if (!_contextStreamDictionary.TryGetValue(streamId, out stream)) { // Get the max stream concurrent streams SettingsPair max = _settings[2]; // If more streams can be created. if (_contextStreamDictionary.Count < max.Value) { // Try to create the stream. stream = new ContextStream(streamId, this); stream.Opened = true; // Add the stream to the connection. _contextStreamDictionary.Add(streamId, stream); return(stream); } else { return(null); } } return(stream); }
/// <summary> /// Set the settings value internally. /// </summary> /// <param name="id">The setting id.</param> /// <param name="value">The setting value.</param> internal void SetSettingsPair(SettingsRegistry id, int value) { // For each setting. for (int i = 0; i < _settings.Length; i++) { // Get the item. SettingsPair item = _settings[i]; // If the id has been found. if (id == item.Id) { // Set the new value. _settings[i].Value = value; } } }
/// <summary> /// Http server context. /// </summary> /// <param name="requestInput">The request input stream containing the raw data.</param> /// <param name="responseOutput">The response output stream containing the raw data.</param> public HttpContext(System.IO.Stream requestInput, System.IO.Stream responseOutput) { // Create the initial settings. _settings = new SettingsPair[6]; _settings[0] = new SettingsPair(SettingsRegistry.Header_Table_Size, 4096); _settings[1] = new SettingsPair(SettingsRegistry.Enable_Push, 1); _settings[2] = new SettingsPair(SettingsRegistry.Max_Concurrent_Streams, Constants.DefaultMaxConcurrentStreams); _settings[3] = new SettingsPair(SettingsRegistry.Initial_Window_Size, Constants.InitialFlowControlWindowSize); _settings[4] = new SettingsPair(SettingsRegistry.Max_Frame_Size, Constants.MaxFramePayloadSize); _settings[5] = new SettingsPair(SettingsRegistry.Max_Header_List_Size, Int32.MaxValue); // Create the stream collections. _contextStreamDictionary = new Collections.CustomDictionary <int, ContextStream>(); _promisedResources = new Dictionary <int, string>(); // Set the request and response streams. Input = requestInput; Output = responseOutput; }
/// <summary> /// Process a setting frame request. /// </summary> /// <param name="httpContext">The current http context.</param> /// <param name="settingFrame">The setting frame.</param> private static void ProcessSettingFrameRequest(Nequeo.Net.Http2.HttpContext httpContext, SettingsFrame settingFrame) { bool isAck = false; /* If an endpoint receives a SETTINGS frame whose stream identifier * field is other than 0x0, the endpoint MUST respond with a connection * error of type PROTOCOL_ERROR. */ if (settingFrame.StreamId != 0) { throw new ProtocolError(ErrorCodeRegistry.Protocol_Error, "Settings frame stream id is not equal to 0."); } /* Receipt of a SETTINGS frame with the ACK flag set and a length * field value other than 0 MUST be treated as a connection error * of type FRAME_SIZE_ERROR. */ if (settingFrame.IsAck) { if (settingFrame.PayloadLength != 0) { throw new ProtocolError(ErrorCodeRegistry.Frame_Size_Error, "Settings frame with ACK flag set and non-zero payload."); } isAck = true; } // If is not acknowledged. if (!isAck) { // For the settings data received. for (int i = 0; i < settingFrame.EntryCount; i++) { SettingsPair setting = settingFrame[i]; switch (setting.Id) { case SettingsRegistry.Enable_Push: httpContext.SetSettingsPair(SettingsRegistry.Enable_Push, setting.Value); break; case SettingsRegistry.Header_Table_Size: httpContext.SetSettingsPair(SettingsRegistry.Header_Table_Size, setting.Value); break; case SettingsRegistry.Initial_Window_Size: httpContext.SetSettingsPair(SettingsRegistry.Initial_Window_Size, setting.Value); break; case SettingsRegistry.Max_Concurrent_Streams: httpContext.SetSettingsPair(SettingsRegistry.Max_Concurrent_Streams, setting.Value); break; case SettingsRegistry.Max_Frame_Size: httpContext.SetSettingsPair(SettingsRegistry.Max_Frame_Size, setting.Value); break; case SettingsRegistry.Max_Header_List_Size: httpContext.SetSettingsPair(SettingsRegistry.Max_Header_List_Size, setting.Value); break; default: /* An endpoint that receives a SETTINGS frame with any other identifier * MUST treat this as a connection error of type PROTOCOL_ERROR. */ throw new ProtocolError(ErrorCodeRegistry.Protocol_Error, "Unknown setting identifier."); } } } // If is not acknowledged. if (!settingFrame.IsAck) { // Sending ACK settings SettingsFrame frame = new SettingsFrame(new List <SettingsPair>(new SettingsPair[0]), true); // Write the frame. httpContext.ResponseWrite(frame.Buffer); } }