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 }