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