Mercurial > hg > nginx
comparison src/event/ngx_event_quic_transport.c @ 8370:262396242352 quic
Reworked macros for parsing/assembling packet types.
Previously, macros checking a packet type with the long header also checked
whether this is a long header. Now it requires a separate preceding check.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Thu, 30 Apr 2020 12:38:38 +0300 |
parents | 336d527ca031 |
children | 7ea34e13937f |
comparison
equal
deleted
inserted
replaced
8369:bddf704d62c1 | 8370:262396242352 |
---|---|
64 static u_char *ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len, | 64 static u_char *ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len, |
65 u_char **out); | 65 u_char **out); |
66 static u_char *ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len, | 66 static u_char *ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len, |
67 u_char *dst); | 67 u_char *dst); |
68 | 68 |
69 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt, | |
70 ngx_uint_t frame_type); | |
69 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack); | 71 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack); |
70 static size_t ngx_quic_create_crypto(u_char *p, | 72 static size_t ngx_quic_create_crypto(u_char *p, |
71 ngx_quic_crypto_frame_t *crypto); | 73 ngx_quic_crypto_frame_t *crypto); |
72 static size_t ngx_quic_create_hs_done(u_char *p); | 74 static size_t ngx_quic_create_hs_done(u_char *p); |
73 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf); | 75 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf); |
526 ssize_t | 528 ssize_t |
527 ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end, | 529 ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end, |
528 ngx_quic_frame_t *f) | 530 ngx_quic_frame_t *f) |
529 { | 531 { |
530 u_char *p; | 532 u_char *p; |
531 uint8_t flags; | |
532 uint64_t varint; | 533 uint64_t varint; |
533 ngx_uint_t i; | 534 ngx_uint_t i; |
534 | 535 |
535 flags = pkt->flags; | |
536 p = start; | 536 p = start; |
537 | 537 |
538 p = ngx_quic_parse_int(p, end, &varint); | 538 p = ngx_quic_parse_int(p, end, &varint); |
539 if (p == NULL) { | 539 if (p == NULL) { |
540 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | 540 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, |
542 return NGX_ERROR; | 542 return NGX_ERROR; |
543 } | 543 } |
544 | 544 |
545 f->type = varint; | 545 f->type = varint; |
546 | 546 |
547 if (ngx_quic_frame_allowed(pkt, f->type) != NGX_OK) { | |
548 return NGX_DECLINED; | |
549 } | |
550 | |
547 switch (f->type) { | 551 switch (f->type) { |
548 | 552 |
549 case NGX_QUIC_FT_CRYPTO: | 553 case NGX_QUIC_FT_CRYPTO: |
550 | |
551 if (ngx_quic_pkt_zrtt(flags)) { | |
552 goto not_allowed; | |
553 } | |
554 | 554 |
555 p = ngx_quic_parse_int(p, end, &f->u.crypto.offset); | 555 p = ngx_quic_parse_int(p, end, &f->u.crypto.offset); |
556 if (p == NULL) { | 556 if (p == NULL) { |
557 goto error; | 557 goto error; |
558 } | 558 } |
578 #endif | 578 #endif |
579 break; | 579 break; |
580 | 580 |
581 case NGX_QUIC_FT_PADDING: | 581 case NGX_QUIC_FT_PADDING: |
582 | 582 |
583 /* allowed in any packet type */ | |
584 | |
585 while (p < end && *p == NGX_QUIC_FT_PADDING) { | 583 while (p < end && *p == NGX_QUIC_FT_PADDING) { |
586 p++; | 584 p++; |
587 } | 585 } |
588 | 586 |
589 break; | 587 break; |
590 | 588 |
591 case NGX_QUIC_FT_ACK: | 589 case NGX_QUIC_FT_ACK: |
592 case NGX_QUIC_FT_ACK_ECN: | 590 case NGX_QUIC_FT_ACK_ECN: |
593 | |
594 if (ngx_quic_pkt_zrtt(flags)) { | |
595 goto not_allowed; | |
596 } | |
597 | 591 |
598 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.largest)) | 592 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.largest)) |
599 && (p = ngx_quic_parse_int(p, end, &f->u.ack.delay)) | 593 && (p = ngx_quic_parse_int(p, end, &f->u.ack.delay)) |
600 && (p = ngx_quic_parse_int(p, end, &f->u.ack.range_count)) | 594 && (p = ngx_quic_parse_int(p, end, &f->u.ack.range_count)) |
601 && (p = ngx_quic_parse_int(p, end, &f->u.ack.first_range)))) | 595 && (p = ngx_quic_parse_int(p, end, &f->u.ack.first_range)))) |
642 } | 636 } |
643 | 637 |
644 break; | 638 break; |
645 | 639 |
646 case NGX_QUIC_FT_PING: | 640 case NGX_QUIC_FT_PING: |
647 | |
648 /* allowed in any packet type */ | |
649 | |
650 break; | 641 break; |
651 | 642 |
652 case NGX_QUIC_FT_NEW_CONNECTION_ID: | 643 case NGX_QUIC_FT_NEW_CONNECTION_ID: |
653 | |
654 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
655 goto not_allowed; | |
656 } | |
657 | 644 |
658 p = ngx_quic_parse_int(p, end, &f->u.ncid.seqnum); | 645 p = ngx_quic_parse_int(p, end, &f->u.ncid.seqnum); |
659 if (p == NULL) { | 646 if (p == NULL) { |
660 goto error; | 647 goto error; |
661 } | 648 } |
684 "quic frame in: NCID seq:%ui retire:%ui len:%ui", | 671 "quic frame in: NCID seq:%ui retire:%ui len:%ui", |
685 f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len); | 672 f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len); |
686 break; | 673 break; |
687 | 674 |
688 case NGX_QUIC_FT_CONNECTION_CLOSE2: | 675 case NGX_QUIC_FT_CONNECTION_CLOSE2: |
689 | |
690 if (!ngx_quic_short_pkt(flags)) { | |
691 goto not_allowed; | |
692 } | |
693 | |
694 /* fall through */ | 676 /* fall through */ |
695 | 677 |
696 case NGX_QUIC_FT_CONNECTION_CLOSE: | 678 case NGX_QUIC_FT_CONNECTION_CLOSE: |
697 | |
698 if (ngx_quic_pkt_zrtt(flags)) { | |
699 goto not_allowed; | |
700 } | |
701 | 679 |
702 p = ngx_quic_parse_int(p, end, &f->u.close.error_code); | 680 p = ngx_quic_parse_int(p, end, &f->u.close.error_code); |
703 if (p == NULL) { | 681 if (p == NULL) { |
704 goto error; | 682 goto error; |
705 } | 683 } |
749 case NGX_QUIC_FT_STREAM4: | 727 case NGX_QUIC_FT_STREAM4: |
750 case NGX_QUIC_FT_STREAM5: | 728 case NGX_QUIC_FT_STREAM5: |
751 case NGX_QUIC_FT_STREAM6: | 729 case NGX_QUIC_FT_STREAM6: |
752 case NGX_QUIC_FT_STREAM7: | 730 case NGX_QUIC_FT_STREAM7: |
753 | 731 |
754 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
755 goto not_allowed; | |
756 } | |
757 | |
758 f->u.stream.type = f->type; | 732 f->u.stream.type = f->type; |
759 | 733 |
760 f->u.stream.off = ngx_quic_stream_bit_off(f->type); | 734 f->u.stream.off = ngx_quic_stream_bit_off(f->type); |
761 f->u.stream.len = ngx_quic_stream_bit_len(f->type); | 735 f->u.stream.len = ngx_quic_stream_bit_len(f->type); |
762 f->u.stream.fin = ngx_quic_stream_bit_fin(f->type); | 736 f->u.stream.fin = ngx_quic_stream_bit_fin(f->type); |
805 #endif | 779 #endif |
806 break; | 780 break; |
807 | 781 |
808 case NGX_QUIC_FT_MAX_DATA: | 782 case NGX_QUIC_FT_MAX_DATA: |
809 | 783 |
810 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
811 goto not_allowed; | |
812 } | |
813 | |
814 p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data); | 784 p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data); |
815 if (p == NULL) { | 785 if (p == NULL) { |
816 goto error; | 786 goto error; |
817 } | 787 } |
818 | 788 |
820 "quic frame in: MAX_DATA max_data:%ui", | 790 "quic frame in: MAX_DATA max_data:%ui", |
821 f->u.max_data.max_data); | 791 f->u.max_data.max_data); |
822 break; | 792 break; |
823 | 793 |
824 case NGX_QUIC_FT_RESET_STREAM: | 794 case NGX_QUIC_FT_RESET_STREAM: |
825 | |
826 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
827 goto not_allowed; | |
828 } | |
829 | 795 |
830 if (!((p = ngx_quic_parse_int(p, end, &f->u.reset_stream.id)) | 796 if (!((p = ngx_quic_parse_int(p, end, &f->u.reset_stream.id)) |
831 && (p = ngx_quic_parse_int(p, end, &f->u.reset_stream.error_code)) | 797 && (p = ngx_quic_parse_int(p, end, &f->u.reset_stream.error_code)) |
832 && (p = ngx_quic_parse_int(p, end, | 798 && (p = ngx_quic_parse_int(p, end, |
833 &f->u.reset_stream.final_size)))) | 799 &f->u.reset_stream.final_size)))) |
842 f->u.reset_stream.final_size); | 808 f->u.reset_stream.final_size); |
843 break; | 809 break; |
844 | 810 |
845 case NGX_QUIC_FT_STOP_SENDING: | 811 case NGX_QUIC_FT_STOP_SENDING: |
846 | 812 |
847 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
848 goto not_allowed; | |
849 } | |
850 | |
851 p = ngx_quic_parse_int(p, end, &f->u.stop_sending.id); | 813 p = ngx_quic_parse_int(p, end, &f->u.stop_sending.id); |
852 if (p == NULL) { | 814 if (p == NULL) { |
853 goto error; | 815 goto error; |
854 } | 816 } |
855 | 817 |
864 | 826 |
865 break; | 827 break; |
866 | 828 |
867 case NGX_QUIC_FT_STREAMS_BLOCKED: | 829 case NGX_QUIC_FT_STREAMS_BLOCKED: |
868 case NGX_QUIC_FT_STREAMS_BLOCKED2: | 830 case NGX_QUIC_FT_STREAMS_BLOCKED2: |
869 | |
870 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
871 goto not_allowed; | |
872 } | |
873 | 831 |
874 p = ngx_quic_parse_int(p, end, &f->u.streams_blocked.limit); | 832 p = ngx_quic_parse_int(p, end, &f->u.streams_blocked.limit); |
875 if (p == NULL) { | 833 if (p == NULL) { |
876 goto error; | 834 goto error; |
877 } | 835 } |
884 f->u.streams_blocked.limit, | 842 f->u.streams_blocked.limit, |
885 f->u.streams_blocked.bidi); | 843 f->u.streams_blocked.bidi); |
886 | 844 |
887 break; | 845 break; |
888 | 846 |
889 case NGX_QUIC_FT_HANDSHAKE_DONE: | |
890 /* only sent by server, not by client */ | |
891 goto not_allowed; | |
892 | |
893 case NGX_QUIC_FT_NEW_TOKEN: | 847 case NGX_QUIC_FT_NEW_TOKEN: |
894 | |
895 if (!ngx_quic_short_pkt(flags)) { | |
896 goto not_allowed; | |
897 } | |
898 | |
899 /* TODO: implement */ | 848 /* TODO: implement */ |
900 | 849 |
901 ngx_log_error(NGX_LOG_ALERT, pkt->log, 0, | 850 ngx_log_error(NGX_LOG_ALERT, pkt->log, 0, |
902 "quic unimplemented frame type 0x%xi in packet", f->type); | 851 "quic unimplemented frame type 0x%xi in packet", f->type); |
903 | 852 |
904 break; | 853 break; |
905 | 854 |
906 case NGX_QUIC_FT_MAX_STREAMS: | 855 case NGX_QUIC_FT_MAX_STREAMS: |
907 case NGX_QUIC_FT_MAX_STREAMS2: | 856 case NGX_QUIC_FT_MAX_STREAMS2: |
908 | |
909 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
910 goto not_allowed; | |
911 } | |
912 | 857 |
913 p = ngx_quic_parse_int(p, end, &f->u.max_streams.limit); | 858 p = ngx_quic_parse_int(p, end, &f->u.max_streams.limit); |
914 if (p == NULL) { | 859 if (p == NULL) { |
915 goto error; | 860 goto error; |
916 } | 861 } |
923 f->u.max_streams.bidi); | 868 f->u.max_streams.bidi); |
924 break; | 869 break; |
925 | 870 |
926 case NGX_QUIC_FT_MAX_STREAM_DATA: | 871 case NGX_QUIC_FT_MAX_STREAM_DATA: |
927 | 872 |
928 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
929 goto not_allowed; | |
930 } | |
931 | |
932 p = ngx_quic_parse_int(p, end, &f->u.max_stream_data.id); | 873 p = ngx_quic_parse_int(p, end, &f->u.max_stream_data.id); |
933 if (p == NULL) { | 874 if (p == NULL) { |
934 goto error; | 875 goto error; |
935 } | 876 } |
936 | 877 |
945 f->u.max_stream_data.limit); | 886 f->u.max_stream_data.limit); |
946 break; | 887 break; |
947 | 888 |
948 case NGX_QUIC_FT_DATA_BLOCKED: | 889 case NGX_QUIC_FT_DATA_BLOCKED: |
949 | 890 |
950 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
951 goto not_allowed; | |
952 } | |
953 | |
954 p = ngx_quic_parse_int(p, end, &f->u.data_blocked.limit); | 891 p = ngx_quic_parse_int(p, end, &f->u.data_blocked.limit); |
955 if (p == NULL) { | 892 if (p == NULL) { |
956 goto error; | 893 goto error; |
957 } | 894 } |
958 | 895 |
960 "quic frame in: DATA_BLOCKED limit:%ui", | 897 "quic frame in: DATA_BLOCKED limit:%ui", |
961 f->u.data_blocked.limit); | 898 f->u.data_blocked.limit); |
962 break; | 899 break; |
963 | 900 |
964 case NGX_QUIC_FT_STREAM_DATA_BLOCKED: | 901 case NGX_QUIC_FT_STREAM_DATA_BLOCKED: |
965 | |
966 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
967 goto not_allowed; | |
968 } | |
969 | 902 |
970 p = ngx_quic_parse_int(p, end, &f->u.stream_data_blocked.id); | 903 p = ngx_quic_parse_int(p, end, &f->u.stream_data_blocked.id); |
971 if (p == NULL) { | 904 if (p == NULL) { |
972 goto error; | 905 goto error; |
973 } | 906 } |
984 f->u.stream_data_blocked.limit); | 917 f->u.stream_data_blocked.limit); |
985 break; | 918 break; |
986 | 919 |
987 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: | 920 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: |
988 | 921 |
989 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
990 goto not_allowed; | |
991 } | |
992 | |
993 p = ngx_quic_parse_int(p, end, &f->u.retire_cid.sequence_number); | 922 p = ngx_quic_parse_int(p, end, &f->u.retire_cid.sequence_number); |
994 if (p == NULL) { | 923 if (p == NULL) { |
995 goto error; | 924 goto error; |
996 } | 925 } |
997 | 926 |
1001 f->u.retire_cid.sequence_number); | 930 f->u.retire_cid.sequence_number); |
1002 break; | 931 break; |
1003 | 932 |
1004 case NGX_QUIC_FT_PATH_CHALLENGE: | 933 case NGX_QUIC_FT_PATH_CHALLENGE: |
1005 | 934 |
1006 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
1007 goto not_allowed; | |
1008 } | |
1009 | |
1010 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_challenge.data); | 935 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_challenge.data); |
1011 if (p == NULL) { | 936 if (p == NULL) { |
1012 goto error; | 937 goto error; |
1013 } | 938 } |
1014 | 939 |
1021 #endif | 946 #endif |
1022 break; | 947 break; |
1023 | 948 |
1024 case NGX_QUIC_FT_PATH_RESPONSE: | 949 case NGX_QUIC_FT_PATH_RESPONSE: |
1025 | 950 |
1026 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) { | |
1027 goto not_allowed; | |
1028 } | |
1029 | |
1030 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_response.data); | 951 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_response.data); |
1031 if (p == NULL) { | 952 if (p == NULL) { |
1032 goto error; | 953 goto error; |
1033 } | 954 } |
1034 | 955 |
1047 return NGX_ERROR; | 968 return NGX_ERROR; |
1048 } | 969 } |
1049 | 970 |
1050 return p - start; | 971 return p - start; |
1051 | 972 |
1052 not_allowed: | 973 error: |
974 | |
975 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
976 "quic failed to parse frame type 0x%xi", f->type); | |
977 | |
978 return NGX_ERROR; | |
979 } | |
980 | |
981 | |
982 static ngx_int_t | |
983 ngx_quic_frame_allowed(ngx_quic_header_t *pkt, ngx_uint_t frame_type) | |
984 { | |
985 uint8_t ptype; | |
986 | |
987 /* frame permissions per packet: 4 bits: IH01: 12.4, Table 3 */ | |
988 static uint8_t ngx_quic_frame_masks[] = { | |
989 /* PADDING */ 0xF, | |
990 /* PING */ 0xF, | |
991 /* ACK */ 0xD, | |
992 /* ACK_ECN */ 0xD, | |
993 /* RESET_STREAM */ 0x3, | |
994 /* STOP_SENDING */ 0x3, | |
995 /* CRYPTO */ 0xD, | |
996 /* NEW_TOKEN */ 0x1, | |
997 /* STREAM0 */ 0x3, | |
998 /* STREAM1 */ 0x3, | |
999 /* STREAM2 */ 0x3, | |
1000 /* STREAM3 */ 0x3, | |
1001 /* STREAM4 */ 0x3, | |
1002 /* STREAM5 */ 0x3, | |
1003 /* STREAM6 */ 0x3, | |
1004 /* STREAM7 */ 0x3, | |
1005 /* MAX_DATA */ 0x3, | |
1006 /* MAX_STREAM_DATA */ 0x3, | |
1007 /* MAX_STREAMS */ 0x3, | |
1008 /* MAX_STREAMS2 */ 0x3, | |
1009 /* DATA_BLOCKED */ 0x3, | |
1010 /* STREAM_DATA_BLOCKED */ 0x3, | |
1011 /* STREAMS_BLOCKED */ 0x3, | |
1012 /* STREAMS_BLOCKED2 */ 0x3, | |
1013 /* NEW_CONNECTION_ID */ 0x3, | |
1014 /* RETIRE_CONNECTION_ID */ 0x3, | |
1015 /* PATH_CHALLENGE */ 0x3, | |
1016 /* PATH_RESPONSE */ 0x3, | |
1017 /* CONNECTION_CLOSE */ 0xD, | |
1018 /* CONNECTION_CLOSE2 */ 0x1, | |
1019 /* HANDSHAKE_DONE */ 0x0, /* only sent by server */ | |
1020 }; | |
1021 | |
1022 if (ngx_quic_long_pkt(pkt->flags)) { | |
1023 | |
1024 if (ngx_quic_pkt_in(pkt->flags)) { | |
1025 ptype = 8; /* initial */ | |
1026 | |
1027 } else if (ngx_quic_pkt_hs(pkt->flags)) { | |
1028 ptype = 4; /* handshake */ | |
1029 | |
1030 } else { | |
1031 ptype = 2; /* zero-rtt */ | |
1032 } | |
1033 | |
1034 } else { | |
1035 ptype = 1; /* application data */ | |
1036 } | |
1037 | |
1038 if (ptype & ngx_quic_frame_masks[frame_type]) { | |
1039 return NGX_OK; | |
1040 } | |
1053 | 1041 |
1054 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | 1042 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, |
1055 "quic frame type 0x%xi is not " | 1043 "quic frame type 0x%xi is not " |
1056 "allowed in packet with flags 0x%xi", | 1044 "allowed in packet with flags 0x%xi", |
1057 f->type, pkt->flags); | 1045 frame_type, pkt->flags); |
1058 | 1046 |
1059 return NGX_DECLINED; | 1047 return NGX_DECLINED; |
1060 | |
1061 error: | |
1062 | |
1063 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, | |
1064 "quic failed to parse frame type 0x%xi", f->type); | |
1065 | |
1066 return NGX_ERROR; | |
1067 } | 1048 } |
1068 | 1049 |
1069 | 1050 |
1070 ssize_t | 1051 ssize_t |
1071 ngx_quic_parse_ack_range(ngx_quic_header_t *pkt, u_char *start, u_char *end, | 1052 ngx_quic_parse_ack_range(ngx_quic_header_t *pkt, u_char *start, u_char *end, |