Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
AltSvcHeaderParser.cs
Go to the documentation of this file.
2using System.Text;
3
5
6internal sealed class AltSvcHeaderParser : BaseHeaderParser
7{
8 public static AltSvcHeaderParser Parser { get; } = new AltSvcHeaderParser();
9
10
12 : base(supportsMultipleValues: true)
13 {
14 }
15
16 protected override int GetParsedValueLength(string value, int startIndex, object storeValue, out object parsedValue)
17 {
18 if (string.IsNullOrEmpty(value))
19 {
20 parsedValue = null;
21 return 0;
22 }
23 int num = startIndex;
24 if (!TryReadPercentEncodedAlpnProtocolName(value, num, out var result, out var readLength))
25 {
26 parsedValue = null;
27 return 0;
28 }
29 num += readLength;
30 if (result == "clear")
31 {
32 if (num != value.Length)
33 {
34 parsedValue = null;
35 return 0;
36 }
37 parsedValue = AltSvcHeaderValue.Clear;
38 return num - startIndex;
39 }
40 if (num == value.Length || value[num++] != '=')
41 {
42 parsedValue = null;
43 return 0;
44 }
45 if (!TryReadQuotedAltAuthority(value, num, out var host, out var port, out var readLength2))
46 {
47 parsedValue = null;
48 return 0;
49 }
50 num += readLength2;
51 int? num2 = null;
52 bool persist = false;
53 while (num != value.Length)
54 {
55 for (; num != value.Length && IsOptionalWhiteSpace(value[num]); num++)
56 {
57 }
58 if (num == value.Length)
59 {
60 parsedValue = null;
61 return 0;
62 }
63 switch (value[num])
64 {
65 default:
66 parsedValue = null;
67 return 0;
68 case ';':
69 {
70 for (num++; num != value.Length && IsOptionalWhiteSpace(value[num]); num++)
71 {
72 }
73 int tokenLength = HttpRuleParser.GetTokenLength(value, num);
74 if (tokenLength == 0)
75 {
76 parsedValue = null;
77 return 0;
78 }
79 if (num + tokenLength >= value.Length || value[num + tokenLength] != '=')
80 {
81 parsedValue = null;
82 return 0;
83 }
84 if (tokenLength == 2 && value[num] == 'm' && value[num + 1] == 'a')
85 {
86 num += 3;
87 if (!TryReadTokenOrQuotedInt32(value, num, out var result2, out var readLength3))
88 {
89 parsedValue = null;
90 return 0;
91 }
92 num2 = (num2.HasValue ? new int?(Math.Min(num2.GetValueOrDefault(), result2)) : new int?(result2));
93 num += readLength3;
94 }
95 else if (value.AsSpan(num).StartsWith("persist="))
96 {
97 num += 8;
98 if (TryReadTokenOrQuotedInt32(value, num, out var result3, out var readLength4))
99 {
100 persist = result3 == 1;
101 }
102 else if (!TrySkipTokenOrQuoted(value, num, out readLength4))
103 {
104 parsedValue = null;
105 return 0;
106 }
107 num += readLength4;
108 }
109 else
110 {
111 num += tokenLength + 1;
112 if (!TrySkipTokenOrQuoted(value, num, out var readLength5))
113 {
114 parsedValue = null;
115 return 0;
116 }
117 num += readLength5;
118 }
119 continue;
120 }
121 case ',':
122 break;
123 }
124 break;
125 }
126 TimeSpan maxAge = TimeSpan.FromTicks(((long?)num2 * 10000000L) ?? 864000000000L);
127 parsedValue = new AltSvcHeaderValue(result, host, port, maxAge, persist);
128 return num - startIndex;
129 }
130
131 private static bool IsOptionalWhiteSpace(char ch)
132 {
133 if (ch != ' ')
134 {
135 return ch == '\t';
136 }
137 return true;
138 }
139
140 private static bool TryReadPercentEncodedAlpnProtocolName(string value, int startIndex, [NotNullWhen(true)] out string result, out int readLength)
141 {
142 int tokenLength = HttpRuleParser.GetTokenLength(value, startIndex);
143 if (tokenLength == 0)
144 {
145 result = null;
146 readLength = 0;
147 return false;
148 }
149 ReadOnlySpan<char> readOnlySpan = value.AsSpan(startIndex, tokenLength);
150 readLength = tokenLength;
151 switch (readOnlySpan.Length)
152 {
153 case 2:
154 if (readOnlySpan[0] == 'h')
155 {
156 switch (readOnlySpan[1])
157 {
158 case '3':
159 result = "h3";
160 return true;
161 case '2':
162 result = "h2";
163 return true;
164 }
165 }
166 break;
167 case 3:
168 if (readOnlySpan[0] == 'h' && readOnlySpan[1] == '2' && readOnlySpan[2] == 'c')
169 {
170 result = "h2c";
171 readLength = 3;
172 return true;
173 }
174 break;
175 case 5:
176 if (readOnlySpan.SequenceEqual("clear"))
177 {
178 result = "clear";
179 return true;
180 }
181 break;
182 case 10:
183 if (readOnlySpan.StartsWith("http%2F1."))
184 {
185 switch (readOnlySpan[9])
186 {
187 case '1':
188 result = "http/1.1";
189 return true;
190 case '0':
191 result = "http/1.0";
192 return true;
193 }
194 }
195 break;
196 }
197 return TryReadUnknownPercentEncodedAlpnProtocolName(readOnlySpan, out result);
198 }
199
200 private static bool TryReadUnknownPercentEncodedAlpnProtocolName(ReadOnlySpan<char> value, [NotNullWhen(true)] out string result)
201 {
202 int num = value.IndexOf('%');
203 if (num == -1)
204 {
205 result = new string(value);
206 return true;
207 }
208 Span<char> initialBuffer = ((value.Length > 128) ? ((Span<char>)new char[value.Length]) : stackalloc char[128]);
209 System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer);
210 do
211 {
212 if (num != 0)
213 {
214 valueStringBuilder.Append(value.Slice(0, num));
215 }
216 if (value.Length - num < 3 || !TryReadAlpnHexDigit(value[1], out var nibble) || !TryReadAlpnHexDigit(value[2], out var nibble2))
217 {
218 result = null;
219 return false;
220 }
221 valueStringBuilder.Append((char)((nibble << 8) | nibble2));
222 value = value.Slice(num + 3);
223 num = value.IndexOf('%');
224 }
225 while (num != -1);
226 if (value.Length != 0)
227 {
228 valueStringBuilder.Append(value);
229 }
230 result = valueStringBuilder.ToString();
231 return true;
232 }
233
234 private static bool TryReadAlpnHexDigit(char ch, out int nibble)
235 {
237 if (num == 255)
238 {
239 nibble = 0;
240 return false;
241 }
242 nibble = num;
243 return true;
244 }
245
246 private static bool TryReadQuotedAltAuthority(string value, int startIndex, out string host, out int port, out int readLength)
247 {
249 {
250 ReadOnlySpan<char> span = value.AsSpan(startIndex + 1, length - 2);
251 int num = span.IndexOf(':');
252 if (num != -1 && TryReadQuotedInt32Value(span.Slice(num + 1), out port))
253 {
254 if (num == 0)
255 {
256 host = null;
257 }
258 else if (!TryReadQuotedValue(span.Slice(0, num), out host))
259 {
260 goto IL_0056;
261 }
262 readLength = length;
263 return true;
264 }
265 }
266 goto IL_0056;
267 IL_0056:
268 host = null;
269 port = 0;
270 readLength = 0;
271 return false;
272 }
273
274 private static bool TryReadQuotedValue(ReadOnlySpan<char> value, out string result)
275 {
276 int num = value.IndexOf('\\');
277 if (num == -1)
278 {
279 result = ((value.Length != 0) ? new string(value) : null);
280 return true;
281 }
282 Span<char> initialBuffer = stackalloc char[128];
283 System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer);
284 do
285 {
286 if (num + 1 == value.Length)
287 {
288 valueStringBuilder.Dispose();
289 result = null;
290 return false;
291 }
292 if (num != 0)
293 {
294 valueStringBuilder.Append(value.Slice(0, num));
295 }
296 valueStringBuilder.Append(value[num + 1]);
297 value = value.Slice(num + 2);
298 num = value.IndexOf('\\');
299 }
300 while (num != -1);
301 if (value.Length != 0)
302 {
303 valueStringBuilder.Append(value);
304 }
305 result = valueStringBuilder.ToString();
306 return true;
307 }
308
309 private static bool TryReadTokenOrQuotedInt32(string value, int startIndex, out int result, out int readLength)
310 {
311 if (startIndex >= value.Length)
312 {
313 result = 0;
314 readLength = 0;
315 return false;
316 }
318 {
320 }
322 {
323 readLength = length;
324 return TryReadQuotedInt32Value(value.AsSpan(1, length - 2), out result);
325 }
326 result = 0;
327 readLength = 0;
328 return false;
329 }
330
331 private static bool TryReadQuotedInt32Value(ReadOnlySpan<char> value, out int result)
332 {
333 if (value.Length == 0)
334 {
335 result = 0;
336 return false;
337 }
338 int num = 0;
339 ReadOnlySpan<char> readOnlySpan = value;
340 for (int i = 0; i < readOnlySpan.Length; i++)
341 {
342 char c = readOnlySpan[i];
343 switch (c)
344 {
345 default:
346 result = 0;
347 return false;
348 case '0':
349 case '1':
350 case '2':
351 case '3':
352 case '4':
353 case '5':
354 case '6':
355 case '7':
356 case '8':
357 case '9':
358 {
359 long num2 = (long)num * 10L + (c - 48);
360 if (num2 > int.MaxValue)
361 {
362 result = 0;
363 return false;
364 }
365 num = (int)num2;
366 break;
367 }
368 case '\\':
369 break;
370 }
371 }
372 result = num;
373 return true;
374 }
375
376 private static bool TrySkipTokenOrQuoted(string value, int startIndex, out int readLength)
377 {
378 if (startIndex >= value.Length)
379 {
380 readLength = 0;
381 return false;
382 }
384 {
386 return true;
387 }
389 {
390 readLength = length;
391 return true;
392 }
393 readLength = 0;
394 return false;
395 }
396}
static int FromUpperChar(int c)
static byte Min(byte val1, byte val2)
Definition Math.cs:912
override int GetParsedValueLength(string value, int startIndex, object storeValue, out object parsedValue)
static bool TrySkipTokenOrQuoted(string value, int startIndex, out int readLength)
static bool TryReadQuotedValue(ReadOnlySpan< char > value, out string result)
static bool TryReadQuotedAltAuthority(string value, int startIndex, out string host, out int port, out int readLength)
static bool TryReadUnknownPercentEncodedAlpnProtocolName(ReadOnlySpan< char > value, [NotNullWhen(true)] out string result)
static bool TryReadTokenOrQuotedInt32(string value, int startIndex, out int result, out int readLength)
static bool TryReadQuotedInt32Value(ReadOnlySpan< char > value, out int result)
static bool TryReadAlpnHexDigit(char ch, out int nibble)
static bool TryReadPercentEncodedAlpnProtocolName(string value, int startIndex, [NotNullWhen(true)] out string result, out int readLength)
static bool TryParseInt32(string value, out int result)
static HttpParseResult GetQuotedStringLength(string input, int startIndex, out int length)
static int GetTokenLength(string input, int startIndex)
static bool IsTokenChar(char character)
ReadOnlySpan< T > Slice(int start)
static TimeSpan FromTicks(long value)
Definition TimeSpan.cs:277