private PriorityFrame DecodePriorityFrame(DecodingContext context, int payloadLength, byte flags, int streamIdentifier) { if (streamIdentifier == 0) { throw new DecoderException(Http2ErrorCode.ProtocolError, "PRIORITY frames require a stream identifier."); } if (payloadLength != 5) { throw new DecoderException(Http2ErrorCode.FrameSizeError, "PRIORITY frame payload should be 5 bytes."); } var exlusive = (context.Buffer[context.Offset] & Bit32) == Bit32; var dependency = BitConverter.ToInt32(context.Buffer, context.Offset) & ~Bit32; var weight = context.Buffer[context.Offset + 4]; context.Offset += 5; context.BytesLeftToProcess -= 5; var frame = new PriorityFrame { DependencyStreamId = dependency, Weight = weight, IsExclusive = exlusive, StreamIdentifier = streamIdentifier, FrameFlags = flags }; return(frame); }
private void HandlePriority(PriorityFrame priorityFrame, out Http2Stream stream) { Http2Logger.LogDebug("PRIORITY frame: stream id={0}, exclusive={1}, dependency={2}, weight={3}", priorityFrame.StreamId, priorityFrame.Exclusive, priorityFrame.StreamDependency, priorityFrame.Weight); /* 12 -> 6.3 * The PRIORITY frame is associated with an existing stream. If a * PRIORITY frame is received with a stream identifier of 0x0, the * recipient MUST respond with a connection error of type PROTOCOL_ERROR. */ if (priorityFrame.StreamId == 0) { throw new ProtocolError(ResetStatusCode.ProtocolError, "Incoming priority frame with stream id=0"); } stream = GetStream(priorityFrame.StreamId); /* 12 -> 6.3 * The PRIORITY frame can be sent on a stream in any of the "reserved * (remote)", "open", "half-closed (local)", or "half closed (remote)" * states, though it cannot be sent between consecutive frames that * comprise a single header block. */ if (stream.Closed) { throw new Http2StreamNotFoundException(priorityFrame.StreamId); } if (!(stream.Opened || stream.ReservedRemote || stream.HalfClosedLocal)) { throw new ProtocolError(ResetStatusCode.ProtocolError, "priority for non opened or reserved stream"); } if (!_usePriorities) { return; } stream.Priority = priorityFrame.Weight; }
/// <summary> /// Process a priority frame request. /// </summary> /// <param name="httpContext">The current http context.</param> /// <param name="priorityFrame">The priority frame.</param> /// <param name="stream">The selected stream context.</param> private static void ProcessPriorityFrameRequest(Nequeo.Net.Http2.HttpContext httpContext, PriorityFrame priorityFrame, out ContextStream stream) { /* The PRIORITY frame is associated with an existing stream. If a * PRIORITY frame is received with a stream identifier of 0x0, the * recipient MUST respond with a connection error of type PROTOCOL_ERROR. */ if (priorityFrame.StreamId == 0) { throw new ProtocolError(ErrorCodeRegistry.Protocol_Error, "Incoming priority frame with stream id equal to 0."); } // Attempt to get the sepcific stream. stream = httpContext.GetStream(priorityFrame.StreamId); if (stream == null) { throw new MaxConcurrentStreamsLimitException(); } /* The PRIORITY frame can be sent on a stream in any of the "reserved * (remote)", "open", "half-closed (local)", or "half closed (remote)" * states, though it cannot be sent between consecutive frames that * comprise a single header block. */ if (stream.Closed) { throw new StreamNotFoundException(priorityFrame.StreamId); } if (!(stream.Opened || stream.ReservedRemote || stream.HalfClosedLocal)) { throw new ProtocolError(ErrorCodeRegistry.Protocol_Error, "Priority for non opened or reserved stream."); } // If using priorities. if (httpContext.UsePriorities) { // Set the priority weight. stream.Priority = priorityFrame.Weight; } }