1 /* 2 * Copyright 2021 The Netty Project 3 * 4 * The Netty Project licenses this file to you under the Apache License, 5 * version 2.0 (the "License"); you may not use this file except in compliance 6 * with the License. You may obtain a copy of the License at: 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 package io.netty.handler.codec.http3; 17 18 import io.netty.channel.ChannelHandlerContext; 19 import io.netty.channel.ChannelPromise; 20 import io.netty.util.ReferenceCountUtil; 21 import io.netty.util.internal.StringUtil; 22 import org.jetbrains.annotations.Nullable; 23 24 final class Http3FrameValidationUtils { 25 26 private Http3FrameValidationUtils() { 27 // no instances 28 } 29 30 @SuppressWarnings("unchecked") 31 private static <T> T cast(Object msg) { 32 return (T) msg; 33 } 34 35 private static <T> boolean isValid(Class<T> frameType, Object msg) { 36 return frameType.isInstance(msg); 37 } 38 39 /** 40 * Check if the passed {@code msg} is of the {@code expectedFrameType} and return the expected type, else return 41 * {@code null}. 42 * 43 * @param expectedFrameType {@link Class} of the expected frame type. 44 * @param msg to validate. 45 * @param <T> Expected type. 46 * @return {@code msg} as expected frame type or {@code null} if it can not be converted to the expected type. 47 */ 48 @Nullable 49 static <T> T validateFrameWritten(Class<T> expectedFrameType, Object msg) { 50 if (isValid(expectedFrameType, msg)) { 51 return cast(msg); 52 } 53 return null; 54 } 55 56 /** 57 * Check if the passed {@code msg} is of the {@code expectedFrameType} and return the expected type, else return 58 * {@code null}. 59 * 60 * @param expectedFrameType {@link Class} of the expected frame type. 61 * @param msg to validate. 62 * @param <T> Expected type. 63 * @return {@code msg} as expected frame type or {@code null} if it can not be converted to the expected type. 64 */ 65 @Nullable 66 static <T> T validateFrameRead(Class<T> expectedFrameType, Object msg) { 67 if (isValid(expectedFrameType, msg)) { 68 return cast(msg); 69 } 70 return null; 71 } 72 73 /** 74 * Handle unexpected frame type by failing the passed {@link ChannelPromise}. 75 * 76 * @param promise to fail. 77 * @param frame which is unexpected. 78 */ 79 static void frameTypeUnexpected(ChannelPromise promise, Object frame) { 80 String type = StringUtil.simpleClassName(frame); 81 ReferenceCountUtil.release(frame); 82 promise.setFailure(new Http3Exception(Http3ErrorCode.H3_FRAME_UNEXPECTED, 83 "Frame of type " + type + " unexpected")); 84 } 85 86 /** 87 * Handle unexpected frame type by propagating a connection error with code: 88 * {@link Http3ErrorCode#H3_FRAME_UNEXPECTED}. 89 * 90 * @param ctx to use for propagation of failure. 91 * @param frame which is unexpected. 92 */ 93 static void frameTypeUnexpected(ChannelHandlerContext ctx, Object frame) { 94 ReferenceCountUtil.release(frame); 95 Http3CodecUtils.connectionError(ctx, Http3ErrorCode.H3_FRAME_UNEXPECTED, "Frame type unexpected", true); 96 } 97 }