1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.quic;
17
18 import io.netty.channel.Channel;
19 import io.netty.channel.ChannelHandler;
20 import io.netty.channel.ChannelOption;
21 import io.netty.util.AttributeKey;
22 import io.netty.util.internal.ObjectUtil;
23 import io.netty.util.internal.logging.InternalLogger;
24 import org.jetbrains.annotations.Nullable;
25
26 import java.util.HashMap;
27 import java.util.LinkedHashMap;
28 import java.util.Map;
29
30 public final class Quic {
31 @SuppressWarnings("unchecked")
32 static final Map.Entry<ChannelOption<?>, Object>[] EMPTY_OPTION_ARRAY = new Map.Entry[0];
33 @SuppressWarnings("unchecked")
34 static final Map.Entry<AttributeKey<?>, Object>[] EMPTY_ATTRIBUTE_ARRAY = new Map.Entry[0];
35
36 static final int MAX_DATAGRAM_SIZE = 1350;
37
38 static final int RESET_TOKEN_LEN = 16;
39
40 private static final Throwable UNAVAILABILITY_CAUSE;
41
42 static {
43 Throwable cause = null;
44
45 try {
46 String version = Quiche.quiche_version();
47 assert version != null;
48 } catch (Throwable error) {
49 cause = error;
50 }
51
52 UNAVAILABILITY_CAUSE = cause;
53 }
54
55
56
57
58
59 public static final int MAX_CONN_ID_LEN = 20;
60
61
62
63
64
65
66
67 public static boolean isVersionSupported(int version) {
68 return isAvailable() && Quiche.quiche_version_is_supported(version);
69 }
70
71
72
73
74
75
76 public static boolean isAvailable() {
77 return UNAVAILABILITY_CAUSE == null;
78 }
79
80
81
82
83
84
85 public static void ensureAvailability() {
86 if (UNAVAILABILITY_CAUSE != null) {
87 throw (Error) new UnsatisfiedLinkError(
88 "failed to load the required native library").initCause(UNAVAILABILITY_CAUSE);
89 }
90 }
91
92
93
94
95
96
97 @Nullable
98 public static Throwable unavailabilityCause() {
99 return UNAVAILABILITY_CAUSE;
100 }
101
102 static Map.Entry<ChannelOption<?>, Object>[] toOptionsArray(Map<ChannelOption<?>, Object> opts) {
103 return new HashMap<>(opts).entrySet().toArray(EMPTY_OPTION_ARRAY);
104 }
105
106 static Map.Entry<AttributeKey<?>, Object>[] toAttributesArray(Map<AttributeKey<?>, Object> attributes) {
107 return new LinkedHashMap<>(attributes).entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY);
108 }
109
110 private static void setAttributes(Channel channel, Map.Entry<AttributeKey<?>, Object>[] attrs) {
111 for (Map.Entry<AttributeKey<?>, Object> e: attrs) {
112 @SuppressWarnings("unchecked")
113 AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
114 channel.attr(key).set(e.getValue());
115 }
116 }
117
118 private static void setChannelOptions(
119 Channel channel, Map.Entry<ChannelOption<?>, Object>[] options, InternalLogger logger) {
120 for (Map.Entry<ChannelOption<?>, Object> e: options) {
121 setChannelOption(channel, e.getKey(), e.getValue(), logger);
122 }
123 }
124
125 @SuppressWarnings("unchecked")
126 private static void setChannelOption(
127 Channel channel, ChannelOption<?> option, Object value, InternalLogger logger) {
128 try {
129 if (!channel.config().setOption((ChannelOption<Object>) option, value)) {
130 logger.warn("Unknown channel option '{}' for channel '{}'", option, channel);
131 }
132 } catch (Throwable t) {
133 logger.warn(
134 "Failed to set channel option '{}' with value '{}' for channel '{}'", option, value, channel, t);
135 }
136 }
137
138
139
140
141
142 static <T> void updateOptions(Map<ChannelOption<?>, Object> options, ChannelOption<T> option, @Nullable T value) {
143 ObjectUtil.checkNotNull(option, "option");
144 if (value == null) {
145 options.remove(option);
146 } else {
147 options.put(option, value);
148 }
149 }
150
151
152
153
154
155 static <T> void updateAttributes(Map<AttributeKey<?>, Object> attributes, AttributeKey<T> key, @Nullable T value) {
156 ObjectUtil.checkNotNull(key, "key");
157 if (value == null) {
158 attributes.remove(key);
159 } else {
160 attributes.put(key, value);
161 }
162 }
163
164 static void setupChannel(Channel ch, Map.Entry<ChannelOption<?>, Object>[] options,
165 Map.Entry<AttributeKey<?>, Object>[] attrs, @Nullable ChannelHandler handler,
166 InternalLogger logger) {
167 Quic.setChannelOptions(ch, options, logger);
168 Quic.setAttributes(ch, attrs);
169 if (handler != null) {
170 ch.pipeline().addLast(handler);
171 }
172 }
173
174 private Quic() { }
175 }