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.buffer.ByteBuf;
19 import io.netty.buffer.Unpooled;
20 import io.netty.util.collection.IntObjectHashMap;
21 import io.netty.util.internal.ClassInitializerUtil;
22 import io.netty.util.internal.NativeLibraryLoader;
23 import io.netty.util.internal.PlatformDependent;
24 import io.netty.util.internal.logging.InternalLogger;
25 import io.netty.util.internal.logging.InternalLoggerFactory;
26 import org.jetbrains.annotations.Nullable;
27
28 import javax.net.ssl.SSLException;
29 import javax.net.ssl.SSLHandshakeException;
30 import java.nio.ByteBuffer;
31 import java.nio.ByteOrder;
32
33 final class Quiche {
34 private static final InternalLogger logger = InternalLoggerFactory.getInstance(Quiche.class);
35 private static final boolean TRACE_LOGGING_ENABLED = logger.isTraceEnabled();
36 private static final IntObjectHashMap<QuicTransportErrorHolder> ERROR_MAPPINGS = new IntObjectHashMap<>();
37
38 static {
39
40
41
42
43
44 ClassInitializerUtil.tryLoadClasses(Quiche.class,
45
46 byte[].class, String.class, BoringSSLCertificateCallback.class,
47 BoringSSLCertificateVerifyCallback.class, BoringSSLHandshakeCompleteCallback.class,
48
49
50 QuicheLogger.class
51 );
52
53 try {
54
55
56 quiche_version();
57 } catch (UnsatisfiedLinkError ignore) {
58
59 loadNativeLibrary();
60 }
61
62
63 if (TRACE_LOGGING_ENABLED) {
64 quiche_enable_debug_logging(new QuicheLogger(logger));
65 }
66 }
67
68 private static void loadNativeLibrary() {
69
70
71 String libName = "netty_quiche42";
72 ClassLoader cl = PlatformDependent.getClassLoader(Quiche.class);
73
74 if (!PlatformDependent.isAndroid()) {
75 libName += '_' + PlatformDependent.normalizedOs()
76 + '_' + PlatformDependent.normalizedArch();
77 }
78
79 try {
80 NativeLibraryLoader.load(libName, cl);
81 } catch (UnsatisfiedLinkError e) {
82 logger.debug("Failed to load {}", libName, e);
83 throw e;
84 }
85 }
86
87 static final short AF_INET = (short) QuicheNativeStaticallyReferencedJniMethods.afInet();
88 static final short AF_INET6 = (short) QuicheNativeStaticallyReferencedJniMethods.afInet6();
89 static final int SIZEOF_SOCKADDR_STORAGE = QuicheNativeStaticallyReferencedJniMethods.sizeofSockaddrStorage();
90 static final int SIZEOF_SOCKADDR_IN = QuicheNativeStaticallyReferencedJniMethods.sizeofSockaddrIn();
91 static final int SIZEOF_SOCKADDR_IN6 = QuicheNativeStaticallyReferencedJniMethods.sizeofSockaddrIn6();
92 static final int SOCKADDR_IN_OFFSETOF_SIN_FAMILY =
93 QuicheNativeStaticallyReferencedJniMethods.sockaddrInOffsetofSinFamily();
94 static final int SOCKADDR_IN_OFFSETOF_SIN_PORT =
95 QuicheNativeStaticallyReferencedJniMethods.sockaddrInOffsetofSinPort();
96 static final int SOCKADDR_IN_OFFSETOF_SIN_ADDR =
97 QuicheNativeStaticallyReferencedJniMethods.sockaddrInOffsetofSinAddr();
98 static final int IN_ADDRESS_OFFSETOF_S_ADDR = QuicheNativeStaticallyReferencedJniMethods.inAddressOffsetofSAddr();
99 static final int SOCKADDR_IN6_OFFSETOF_SIN6_FAMILY =
100 QuicheNativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6Family();
101 static final int SOCKADDR_IN6_OFFSETOF_SIN6_PORT =
102 QuicheNativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6Port();
103 static final int SOCKADDR_IN6_OFFSETOF_SIN6_FLOWINFO =
104 QuicheNativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6Flowinfo();
105 static final int SOCKADDR_IN6_OFFSETOF_SIN6_ADDR =
106 QuicheNativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6Addr();
107 static final int SOCKADDR_IN6_OFFSETOF_SIN6_SCOPE_ID =
108 QuicheNativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6ScopeId();
109 static final int IN6_ADDRESS_OFFSETOF_S6_ADDR =
110 QuicheNativeStaticallyReferencedJniMethods.in6AddressOffsetofS6Addr();
111 static final int SIZEOF_SOCKLEN_T = QuicheNativeStaticallyReferencedJniMethods.sizeofSocklenT();
112 static final int SIZEOF_SIZE_T = QuicheNativeStaticallyReferencedJniMethods.sizeofSizeT();
113
114 static final int SIZEOF_TIMESPEC = QuicheNativeStaticallyReferencedJniMethods.sizeofTimespec();
115
116 static final int SIZEOF_TIME_T = QuicheNativeStaticallyReferencedJniMethods.sizeofTimeT();
117 static final int SIZEOF_LONG = QuicheNativeStaticallyReferencedJniMethods.sizeofLong();
118
119 static final int TIMESPEC_OFFSETOF_TV_SEC =
120 QuicheNativeStaticallyReferencedJniMethods.timespecOffsetofTvSec();
121
122 static final int TIMESPEC_OFFSETOF_TV_NSEC =
123 QuicheNativeStaticallyReferencedJniMethods.timespecOffsetofTvNsec();
124
125 static final int QUICHE_RECV_INFO_OFFSETOF_FROM =
126 QuicheNativeStaticallyReferencedJniMethods.quicheRecvInfoOffsetofFrom();
127 static final int QUICHE_RECV_INFO_OFFSETOF_FROM_LEN =
128 QuicheNativeStaticallyReferencedJniMethods.quicheRecvInfoOffsetofFromLen();
129
130 static final int QUICHE_RECV_INFO_OFFSETOF_TO =
131 QuicheNativeStaticallyReferencedJniMethods.quicheRecvInfoOffsetofTo();
132 static final int QUICHE_RECV_INFO_OFFSETOF_TO_LEN =
133 QuicheNativeStaticallyReferencedJniMethods.quicheRecvInfoOffsetofToLen();
134
135 static final int SIZEOF_QUICHE_RECV_INFO = QuicheNativeStaticallyReferencedJniMethods.sizeofQuicheRecvInfo();
136 static final int QUICHE_SEND_INFO_OFFSETOF_TO =
137 QuicheNativeStaticallyReferencedJniMethods.quicheSendInfoOffsetofTo();
138 static final int QUICHE_SEND_INFO_OFFSETOF_TO_LEN =
139 QuicheNativeStaticallyReferencedJniMethods.quicheSendInfoOffsetofToLen();
140
141 static final int QUICHE_SEND_INFO_OFFSETOF_FROM =
142 QuicheNativeStaticallyReferencedJniMethods.quicheSendInfoOffsetofFrom();
143 static final int QUICHE_SEND_INFO_OFFSETOF_FROM_LEN =
144 QuicheNativeStaticallyReferencedJniMethods.quicheSendInfoOffsetofFromLen();
145
146 static final int QUICHE_SEND_INFO_OFFSETOF_AT =
147 QuicheNativeStaticallyReferencedJniMethods.quicheSendInfoOffsetofAt();
148 static final int SIZEOF_QUICHE_SEND_INFO = QuicheNativeStaticallyReferencedJniMethods.sizeofQuicheSendInfo();
149
150 static final int QUICHE_PROTOCOL_VERSION = QuicheNativeStaticallyReferencedJniMethods.quiche_protocol_version();
151 static final int QUICHE_MAX_CONN_ID_LEN = QuicheNativeStaticallyReferencedJniMethods.quiche_max_conn_id_len();
152
153
154
155
156 static final int QUICHE_SHUTDOWN_READ = QuicheNativeStaticallyReferencedJniMethods.quiche_shutdown_read();
157
158
159
160
161 static final int QUICHE_SHUTDOWN_WRITE = QuicheNativeStaticallyReferencedJniMethods.quiche_shutdown_write();
162
163
164
165
166 static final int QUICHE_ERR_DONE = QuicheNativeStaticallyReferencedJniMethods.quiche_err_done();
167
168
169
170
171
172 static final int QUICHE_ERR_BUFFER_TOO_SHORT =
173 QuicheNativeStaticallyReferencedJniMethods.quiche_err_buffer_too_short();
174
175
176
177
178
179 static final int QUICHE_ERR_UNKNOWN_VERSION =
180 QuicheNativeStaticallyReferencedJniMethods.quiche_err_unknown_version();
181
182
183
184
185
186 static final int QUICHE_ERR_INVALID_FRAME = QuicheNativeStaticallyReferencedJniMethods.quiche_err_invalid_frame();
187
188
189
190
191
192 static final int QUICHE_ERR_INVALID_PACKET = QuicheNativeStaticallyReferencedJniMethods.quiche_err_invalid_packet();
193
194
195
196
197
198 static final int QUICHE_ERR_INVALID_STATE = QuicheNativeStaticallyReferencedJniMethods.quiche_err_invalid_state();
199
200
201
202
203
204 static final int QUICHE_ERR_INVALID_STREAM_STATE =
205 QuicheNativeStaticallyReferencedJniMethods.quiche_err_invalid_stream_state();
206
207
208
209
210
211 static final int QUICHE_ERR_INVALID_TRANSPORT_PARAM =
212 QuicheNativeStaticallyReferencedJniMethods.quiche_err_invalid_transport_param();
213
214
215
216
217
218 static final int QUICHE_ERR_CRYPTO_FAIL = QuicheNativeStaticallyReferencedJniMethods.quiche_err_crypto_fail();
219
220
221
222
223
224 static final int QUICHE_ERR_TLS_FAIL = QuicheNativeStaticallyReferencedJniMethods.quiche_err_tls_fail();
225
226
227
228
229
230 static final int QUICHE_ERR_FLOW_CONTROL = QuicheNativeStaticallyReferencedJniMethods.quiche_err_flow_control();
231
232
233
234
235
236 static final int QUICHE_ERR_STREAM_LIMIT = QuicheNativeStaticallyReferencedJniMethods.quiche_err_stream_limit();
237
238
239
240
241
242 static final int QUICHE_ERR_FINAL_SIZE = QuicheNativeStaticallyReferencedJniMethods.quiche_err_final_size();
243
244
245
246
247
248 static final int QUICHE_ERR_CONGESTION_CONTROL =
249 QuicheNativeStaticallyReferencedJniMethods.quiche_err_congestion_control();
250
251
252
253
254
255 static final int QUICHE_ERR_STREAM_RESET =
256 QuicheNativeStaticallyReferencedJniMethods.quiche_err_stream_reset();
257
258
259
260
261
262 static final int QUICHE_ERR_STREAM_STOPPED =
263 QuicheNativeStaticallyReferencedJniMethods.quiche_err_stream_stopped();
264
265
266 static final int QUICHE_ERR_ID_LIMIT =
267 QuicheNativeStaticallyReferencedJniMethods.quiche_err_id_limit();
268
269
270 static final int QUICHE_ERR_OUT_OF_IDENTIFIERS =
271 QuicheNativeStaticallyReferencedJniMethods.quiche_err_out_of_identifiers();
272
273
274 static final int QUICHE_ERR_KEY_UPDATE =
275 QuicheNativeStaticallyReferencedJniMethods.quiche_err_key_update();
276
277 static final int QUICHE_ERR_CRYPTO_BUFFER_EXCEEDED =
278 QuicheNativeStaticallyReferencedJniMethods.quiche_err_crypto_buffer_exceeded();
279
280
281
282
283
284 static final int QUICHE_CC_RENO = QuicheNativeStaticallyReferencedJniMethods.quiche_cc_reno();
285
286
287
288
289
290 static final int QUICHE_CC_CUBIC = QuicheNativeStaticallyReferencedJniMethods.quiche_cc_cubic();
291
292
293
294
295
296 static final int QUICHE_CC_BBR = QuicheNativeStaticallyReferencedJniMethods.quiche_cc_bbr();
297
298 static final int QUICHE_PATH_EVENT_NEW = QuicheNativeStaticallyReferencedJniMethods.quiche_path_event_new();
299 static final int QUICHE_PATH_EVENT_VALIDATED =
300 QuicheNativeStaticallyReferencedJniMethods.quiche_path_event_validated();
301 static final int QUICHE_PATH_EVENT_FAILED_VALIDATION =
302 QuicheNativeStaticallyReferencedJniMethods.quiche_path_event_failed_validation();
303 static final int QUICHE_PATH_EVENT_CLOSED = QuicheNativeStaticallyReferencedJniMethods.quiche_path_event_closed();
304 static final int QUICHE_PATH_EVENT_REUSED_SOURCE_CONNECTION_ID =
305 QuicheNativeStaticallyReferencedJniMethods.quiche_path_event_reused_source_connection_id();
306 static final int QUICHE_PATH_EVENT_PEER_MIGRATED =
307 QuicheNativeStaticallyReferencedJniMethods.quiche_path_event_peer_migrated();
308
309
310
311
312 @Nullable
313 static native String quiche_version();
314
315
316
317
318
319 static native boolean quiche_version_is_supported(int version);
320
321
322
323
324 static native int quiche_negotiate_version(
325 long scidAddr, int scidLen, long dcidAddr, int dcidLen, long outAddr, int outLen);
326
327
328
329
330 static native int quiche_retry(long scidAddr, int scidLen, long dcidAddr, int dcidLen, long newScidAddr,
331 int newScidLen, long tokenAddr, int tokenLen, int version, long outAddr, int outLen);
332
333
334
335
336 static native long quiche_conn_new_with_tls(long scidAddr, int scidLen, long odcidAddr, int odcidLen,
337 long localAddr, int localLen,
338 long peerAddr, int peerLen,
339 long configAddr, long ssl, boolean isServer);
340
341
342
343
344
345 static native boolean quiche_conn_set_qlog_path(long connAddr, String path, String logTitle, String logDescription);
346
347
348
349
350 static native int quiche_conn_recv(long connAddr, long bufAddr, int bufLen, long infoAddr);
351
352
353
354
355 static native int quiche_conn_send(long connAddr, long outAddr, int outLen, long infoAddr);
356
357
358
359
360 static native void quiche_conn_free(long connAddr);
361
362 @Nullable
363 static QuicConnectionCloseEvent quiche_conn_peer_error(long connAddr) {
364 Object[] error = quiche_conn_peer_error0(connAddr);
365 if (error == null) {
366 return null;
367 }
368 return new QuicConnectionCloseEvent((Boolean) error[0], (Integer) error[1], (byte[]) error[2]);
369 }
370
371 private static native Object @Nullable [] quiche_conn_peer_error0(long connAddr);
372
373
374
375
376
377 static native long quiche_conn_peer_streams_left_bidi(long connAddr);
378
379
380
381
382
383 static native long quiche_conn_peer_streams_left_uni(long connAddr);
384
385
386
387
388
389 static native int quiche_conn_stream_priority(
390 long connAddr, long streamId, byte urgency, boolean incremental);
391
392 static native int quiche_conn_send_quantum(long connAddr);
393
394
395
396
397 static native byte @Nullable [] quiche_conn_trace_id(long connAddr);
398
399 static native byte[] quiche_conn_source_id(long connAddr);
400
401 static native byte[] quiche_conn_destination_id(long connAddr);
402
403
404
405
406 static native int quiche_conn_stream_recv(long connAddr, long streamId, long outAddr, int bufLen, long finAddr);
407
408
409
410
411 static native int quiche_conn_stream_send(long connAddr, long streamId, long bufAddr, int bufLen, boolean fin);
412
413
414
415
416
417 static native int quiche_conn_stream_shutdown(long connAddr, long streamId, int direction, long err);
418
419
420
421
422
423 static native int quiche_conn_stream_capacity(long connAddr, long streamId);
424
425
426
427
428
429 static native boolean quiche_conn_stream_finished(long connAddr, long streamId);
430
431
432
433
434
435 static native int quiche_conn_close(long connAddr, boolean app, long err, long reasonAddr, int reasonLen);
436
437
438
439
440
441 static native boolean quiche_conn_is_established(long connAddr);
442
443
444
445
446
447 static native boolean quiche_conn_is_in_early_data(long connAddr);
448
449
450
451
452
453 static native boolean quiche_conn_is_closed(long connAddr);
454
455
456
457
458
459
460 static native boolean quiche_conn_is_timed_out(long connAddr);
461
462
463
464
465
466
467
468
469 static native long @Nullable [] quiche_conn_stats(long connAddr);
470
471
472
473
474
475
476 static native long @Nullable [] quiche_conn_peer_transport_params(long connAddr);
477
478
479
480
481
482 static native long quiche_conn_timeout_as_nanos(long connAddr);
483
484
485
486
487
488 static native void quiche_conn_on_timeout(long connAddr);
489
490
491
492
493
494 static native long quiche_conn_readable(long connAddr);
495
496
497
498
499
500 static native long quiche_conn_writable(long connAddr);
501
502
503
504
505
506
507
508
509
510 static native int quiche_stream_iter_next(long iterAddr, long[] streamIds);
511
512
513
514
515
516
517 static native void quiche_stream_iter_free(long iterAddr);
518
519
520
521
522
523
524 static native Object @Nullable [] quiche_conn_path_stats(long connAddr, long streamIdx);
525
526
527
528
529
530
531 static native int quiche_conn_dgram_max_writable_len(long connAddr);
532
533
534
535
536
537
538
539 static native int quiche_conn_dgram_recv_front_len(long connAddr);
540
541
542
543
544
545
546 static native int quiche_conn_dgram_recv(long connAddr, long buf, int size);
547
548
549
550
551
552
553 static native int quiche_conn_dgram_send(long connAddr, long buf, int size);
554
555
556
557
558
559
560 static native int quiche_conn_set_session(long connAddr, byte[] sessionBytes);
561
562
563
564
565
566
567 static native int quiche_conn_max_send_udp_payload_size(long connAddr);
568
569 static native int quiche_conn_scids_left(long connAddr);
570
571 static native long quiche_conn_new_scid(
572 long connAddr, long scidAddr, int scidLen, byte[] resetToken, boolean retire_if_needed, long seq);
573
574 static native byte @Nullable [] quiche_conn_retired_scid_next(long connAddr);
575
576 static native long quiche_conn_path_event_next(long connAddr);
577 static native int quiche_path_event_type(long pathEvent);
578 static native void quiche_path_event_free(long pathEvent);
579 static native Object[] quiche_path_event_new(long pathEvent);
580 static native Object[] quiche_path_event_validated(long pathEvent);
581 static native Object[] quiche_path_event_failed_validation(long pathEvent);
582 static native Object[] quiche_path_event_closed(long pathEvent);
583 static native Object[] quiche_path_event_reused_source_connection_id(long pathEvent);
584 static native Object[] quiche_path_event_peer_migrated(long pathEvent);
585
586
587
588
589
590 static native long quiche_config_new(int version);
591
592
593
594
595
596
597 static native void quiche_config_grease(long configAddr, boolean value);
598
599
600
601
602
603
604 static native void quiche_config_set_max_idle_timeout(long configAddr, long value);
605
606
607
608
609
610
611 static native void quiche_config_set_max_recv_udp_payload_size(long configAddr, long value);
612
613
614
615
616
617
618 static native void quiche_config_set_max_send_udp_payload_size(long configAddr, long value);
619
620
621
622
623
624
625 static native void quiche_config_set_initial_max_data(long configAddr, long value);
626
627
628
629
630
631
632 static native void quiche_config_set_initial_max_stream_data_bidi_local(long configAddr, long value);
633
634
635
636
637
638
639 static native void quiche_config_set_initial_max_stream_data_bidi_remote(long configAddr, long value);
640
641
642
643
644
645
646 static native void quiche_config_set_initial_max_stream_data_uni(long configAddr, long value);
647
648
649
650
651
652
653 static native void quiche_config_set_initial_max_streams_bidi(long configAddr, long value);
654
655
656
657
658
659
660 static native void quiche_config_set_initial_max_streams_uni(long configAddr, long value);
661
662
663
664
665
666
667 static native void quiche_config_set_ack_delay_exponent(long configAddr, long value);
668
669
670
671
672
673
674 static native void quiche_config_set_max_ack_delay(long configAddr, long value);
675
676
677
678
679
680
681 static native void quiche_config_set_disable_active_migration(long configAddr, boolean value);
682
683
684
685
686
687
688 static native void quiche_config_set_cc_algorithm(long configAddr, int algo);
689
690
691
692
693
694
695
696 static native void quiche_config_set_initial_congestion_window_packets(long configAddr, int numPackets);
697
698
699
700
701
702
703 static native void quiche_config_enable_hystart(long configAddr, boolean value);
704
705
706
707
708
709
710 static native void quiche_config_enable_dgram(long configAddr, boolean enable,
711 int recv_queue_len, int send_queue_len);
712
713
714 static native void quiche_config_set_active_connection_id_limit(long configAddr, long value);
715
716
717 static native void quiche_config_set_stateless_reset_token(long configAddr, byte[] token);
718
719
720
721
722
723
724 static native void quiche_config_free(long configAddr);
725
726
727
728
729
730 private static native void quiche_enable_debug_logging(QuicheLogger logger);
731
732 private static native long buffer_memory_address(ByteBuffer buffer);
733
734 static native int sockaddr_cmp(long addr, long addr2);
735
736
737
738
739
740
741
742
743 static long readerMemoryAddress(ByteBuf buf) {
744 return memoryAddress(buf, buf.readerIndex(), buf.readableBytes());
745 }
746
747
748
749
750
751
752
753
754 static long writerMemoryAddress(ByteBuf buf) {
755 return memoryAddress(buf, buf.writerIndex(), buf.writableBytes());
756 }
757
758
759
760
761
762
763
764
765
766
767 static long memoryAddress(ByteBuf buf, int offset, int len) {
768 assert buf.isDirect();
769 if (buf.hasMemoryAddress()) {
770 return buf.memoryAddress() + offset;
771 }
772 return memoryAddressWithPosition(buf.internalNioBuffer(offset, len));
773 }
774
775
776
777
778
779
780
781
782
783 static long memoryAddressWithPosition(ByteBuffer buf) {
784 assert buf.isDirect();
785 return buffer_memory_address(buf) + buf.position();
786 }
787
788 @SuppressWarnings("deprecation")
789 static ByteBuf allocateNativeOrder(int capacity) {
790
791 ByteBuf buffer = Unpooled.directBuffer(capacity);
792
793
794
795 return PlatformDependent.BIG_ENDIAN_NATIVE_ORDER ? buffer : buffer.order(ByteOrder.LITTLE_ENDIAN);
796 }
797
798 static boolean shouldClose(int res) {
799 return res == Quiche.QUICHE_ERR_CRYPTO_FAIL || res == Quiche.QUICHE_ERR_TLS_FAIL;
800 }
801
802
803
804
805
806
807
808
809
810 static boolean isSameAddress(ByteBuffer memory, ByteBuffer memory2, int addressOffset) {
811 long address1 = Quiche.memoryAddressWithPosition(memory) + addressOffset;
812 long address2 = Quiche.memoryAddressWithPosition(memory2) + addressOffset;
813 return SockaddrIn.cmp(address1, address2) == 0;
814 }
815
816 static void setPrimitiveValue(ByteBuffer memory, int offset, int valueType, long value) {
817 switch (valueType) {
818 case 1:
819 memory.put(offset, (byte) value);
820 break;
821 case 2:
822 memory.putShort(offset, (short) value);
823 break;
824 case 4:
825 memory.putInt(offset, (int) value);
826 break;
827 case 8:
828 memory.putLong(offset, value);
829 break;
830 default:
831 throw new IllegalStateException();
832 }
833 }
834
835 static long getPrimitiveValue(ByteBuffer memory, int offset, int valueType) {
836 switch (valueType) {
837 case 1:
838 return memory.get(offset);
839 case 2:
840 return memory.getShort(offset);
841 case 4:
842 return memory.getInt(offset);
843 case 8:
844 return memory.getLong(offset);
845 default:
846 throw new IllegalStateException();
847 }
848 }
849
850
851 static {
852 ERROR_MAPPINGS.put(QUICHE_ERR_DONE,
853 new QuicTransportErrorHolder(QuicTransportError.NO_ERROR, "QUICHE_ERR_DONE"));
854 ERROR_MAPPINGS.put(QUICHE_ERR_INVALID_FRAME,
855 new QuicTransportErrorHolder(QuicTransportError.FRAME_ENCODING_ERROR, "QUICHE_ERR_INVALID_FRAME"));
856 ERROR_MAPPINGS.put(QUICHE_ERR_INVALID_STREAM_STATE,
857 new QuicTransportErrorHolder(QuicTransportError.STREAM_STATE_ERROR, "QUICHE_ERR_INVALID_STREAM_STATE"));
858 ERROR_MAPPINGS.put(QUICHE_ERR_INVALID_TRANSPORT_PARAM,
859 new QuicTransportErrorHolder(QuicTransportError.TRANSPORT_PARAMETER_ERROR,
860 "QUICHE_ERR_INVALID_TRANSPORT_PARAM"));
861 ERROR_MAPPINGS.put(QUICHE_ERR_FLOW_CONTROL,
862 new QuicTransportErrorHolder(QuicTransportError.FLOW_CONTROL_ERROR, "QUICHE_ERR_FLOW_CONTROL"));
863 ERROR_MAPPINGS.put(QUICHE_ERR_STREAM_LIMIT,
864 new QuicTransportErrorHolder(QuicTransportError.STREAM_LIMIT_ERROR, "QUICHE_ERR_STREAM_LIMIT"));
865 ERROR_MAPPINGS.put(QUICHE_ERR_ID_LIMIT,
866 new QuicTransportErrorHolder(QuicTransportError.CONNECTION_ID_LIMIT_ERROR, "QUICHE_ERR_ID_LIMIT"));
867 ERROR_MAPPINGS.put(QUICHE_ERR_FINAL_SIZE,
868 new QuicTransportErrorHolder(QuicTransportError.FINAL_SIZE_ERROR, "QUICHE_ERR_FINAL_SIZE"));
869 ERROR_MAPPINGS.put(QUICHE_ERR_CRYPTO_BUFFER_EXCEEDED,
870 new QuicTransportErrorHolder(QuicTransportError.CRYPTO_BUFFER_EXCEEDED,
871 "QUICHE_ERR_CRYPTO_BUFFER_EXCEEDED"));
872 ERROR_MAPPINGS.put(QUICHE_ERR_KEY_UPDATE,
873 new QuicTransportErrorHolder(QuicTransportError.KEY_UPDATE_ERROR, "QUICHE_ERR_KEY_UPDATE"));
874
875
876 ERROR_MAPPINGS.put(QUICHE_ERR_TLS_FAIL,
877 new QuicTransportErrorHolder(QuicTransportError.valueOf(0x0100), "QUICHE_ERR_TLS_FAIL"));
878 ERROR_MAPPINGS.put(QUICHE_ERR_CRYPTO_FAIL,
879 new QuicTransportErrorHolder(QuicTransportError.valueOf(0x0100), "QUICHE_ERR_CRYPTO_FAIL"));
880
881 ERROR_MAPPINGS.put(QUICHE_ERR_BUFFER_TOO_SHORT,
882 new QuicTransportErrorHolder(QuicTransportError.PROTOCOL_VIOLATION, "QUICHE_ERR_BUFFER_TOO_SHORT"));
883 ERROR_MAPPINGS.put(QUICHE_ERR_UNKNOWN_VERSION,
884 new QuicTransportErrorHolder(QuicTransportError.PROTOCOL_VIOLATION, "QUICHE_ERR_UNKNOWN_VERSION"));
885 ERROR_MAPPINGS.put(QUICHE_ERR_INVALID_PACKET,
886 new QuicTransportErrorHolder(QuicTransportError.PROTOCOL_VIOLATION, "QUICHE_ERR_INVALID_PACKET"));
887 ERROR_MAPPINGS.put(QUICHE_ERR_INVALID_STATE,
888 new QuicTransportErrorHolder(QuicTransportError.PROTOCOL_VIOLATION, "QUICHE_ERR_INVALID_STATE"));
889 ERROR_MAPPINGS.put(QUICHE_ERR_CONGESTION_CONTROL,
890 new QuicTransportErrorHolder(QuicTransportError.PROTOCOL_VIOLATION, "QUICHE_ERR_CONGESTION_CONTROL"));
891 ERROR_MAPPINGS.put(QUICHE_ERR_STREAM_STOPPED,
892 new QuicTransportErrorHolder(QuicTransportError.PROTOCOL_VIOLATION, "QUICHE_ERR_STREAM_STOPPED"));
893 ERROR_MAPPINGS.put(QUICHE_ERR_OUT_OF_IDENTIFIERS,
894 new QuicTransportErrorHolder(QuicTransportError.PROTOCOL_VIOLATION, "QUICHE_ERR_OUT_OF_IDENTIFIERS"));
895 }
896
897 static Exception convertToException(int result) {
898 QuicTransportErrorHolder holder = ERROR_MAPPINGS.get(result);
899 if (holder == null) {
900
901 return new QuicException(QuicheError.valueOf(result).message());
902 }
903 Exception exception = new QuicException(holder.error + ": " + holder.quicheErrorName, holder.error);
904 if (result == QUICHE_ERR_TLS_FAIL) {
905 String lastSslError = BoringSSL.ERR_last_error();
906 final SSLHandshakeException sslExc = new SSLHandshakeException(lastSslError);
907 sslExc.initCause(exception);
908 return sslExc;
909 }
910 if (result == QUICHE_ERR_CRYPTO_FAIL) {
911 return new SSLException(exception);
912 }
913 return exception;
914 }
915
916 private static final class QuicTransportErrorHolder {
917 private final QuicTransportError error;
918 private final String quicheErrorName;
919
920 QuicTransportErrorHolder(QuicTransportError error, String quicheErrorName) {
921 this.error = error;
922 this.quicheErrorName = quicheErrorName;
923 }
924 }
925
926 private Quiche() { }
927 }