@@ -794,119 +794,28 @@ bool ToASCII(const std::string& input, std::string* output) {
794
794
}
795
795
#endif
796
796
797
+ #define NS_IN6ADDRSZ 16
798
+
797
799
void URLHost::ParseIPv6Host (const char * input, size_t length) {
798
800
CHECK_EQ (type_, HostType::H_FAILED);
799
- unsigned size = arraysize (value_.ipv6 );
800
- for (unsigned n = 0 ; n < size; n++)
801
- value_.ipv6 [n] = 0 ;
802
- uint16_t * piece_pointer = &value_.ipv6 [0 ];
803
- uint16_t * const buffer_end = piece_pointer + size;
804
- uint16_t * compress_pointer = nullptr ;
805
- const char * pointer = input;
806
- const char * end = pointer + length;
807
- unsigned value, len, numbers_seen;
808
- char ch = pointer < end ? pointer[0 ] : kEOL ;
809
- if (ch == ' :' ) {
810
- if (length < 2 || pointer[1 ] != ' :' )
811
- return ;
812
- pointer += 2 ;
813
- ch = pointer < end ? pointer[0 ] : kEOL ;
814
- piece_pointer++;
815
- compress_pointer = piece_pointer;
816
- }
817
- while (ch != kEOL ) {
818
- if (piece_pointer >= buffer_end)
819
- return ;
820
- if (ch == ' :' ) {
821
- if (compress_pointer != nullptr )
822
- return ;
823
- pointer++;
824
- ch = pointer < end ? pointer[0 ] : kEOL ;
825
- piece_pointer++;
826
- compress_pointer = piece_pointer;
827
- continue ;
828
- }
829
- value = 0 ;
830
- len = 0 ;
831
- while (len < 4 && IsASCIIHexDigit (ch)) {
832
- value = value * 0x10 + hex2bin (ch);
833
- pointer++;
834
- ch = pointer < end ? pointer[0 ] : kEOL ;
835
- len++;
836
- }
837
- switch (ch) {
838
- case ' .' :
839
- if (len == 0 )
840
- return ;
841
- pointer -= len;
842
- ch = pointer < end ? pointer[0 ] : kEOL ;
843
- if (piece_pointer > buffer_end - 2 )
844
- return ;
845
- numbers_seen = 0 ;
846
- while (ch != kEOL ) {
847
- value = 0xffffffff ;
848
- if (numbers_seen > 0 ) {
849
- if (ch == ' .' && numbers_seen < 4 ) {
850
- pointer++;
851
- ch = pointer < end ? pointer[0 ] : kEOL ;
852
- } else {
853
- return ;
854
- }
855
- }
856
- if (!IsASCIIDigit (ch))
857
- return ;
858
- while (IsASCIIDigit (ch)) {
859
- unsigned number = ch - ' 0' ;
860
- if (value == 0xffffffff ) {
861
- value = number;
862
- } else if (value == 0 ) {
863
- return ;
864
- } else {
865
- value = value * 10 + number;
866
- }
867
- if (value > 255 )
868
- return ;
869
- pointer++;
870
- ch = pointer < end ? pointer[0 ] : kEOL ;
871
- }
872
- *piece_pointer = *piece_pointer * 0x100 + value;
873
- numbers_seen++;
874
- if (numbers_seen == 2 || numbers_seen == 4 )
875
- piece_pointer++;
876
- }
877
- if (numbers_seen != 4 )
878
- return ;
879
- continue ;
880
- case ' :' :
881
- pointer++;
882
- ch = pointer < end ? pointer[0 ] : kEOL ;
883
- if (ch == kEOL )
884
- return ;
885
- break ;
886
- case kEOL :
887
- break ;
888
- default :
889
- return ;
890
- }
891
- *piece_pointer = value;
892
- piece_pointer++;
893
- }
894
801
895
- if (compress_pointer != nullptr ) {
896
- int64_t swaps = piece_pointer - compress_pointer;
897
- piece_pointer = buffer_end - 1 ;
898
- while (piece_pointer != &value_.ipv6 [0 ] && swaps > 0 ) {
899
- uint16_t temp = *piece_pointer;
900
- uint16_t * swap_piece = compress_pointer + swaps - 1 ;
901
- *piece_pointer = *swap_piece;
902
- *swap_piece = temp;
903
- piece_pointer--;
904
- swaps--;
905
- }
906
- } else if (compress_pointer == nullptr &&
907
- piece_pointer != buffer_end) {
802
+ unsigned char buf[sizeof (struct in6_addr )];
803
+ MaybeStackBuffer<char > ipv6 (length + 1 );
804
+ *(*ipv6 + length) = 0 ;
805
+ memset (buf, 0 , sizeof (buf));
806
+ memcpy (*ipv6, input, sizeof (const char ) * length);
807
+
808
+ int ret = uv_inet_pton (AF_INET6, *ipv6, buf);
809
+
810
+ if (ret != 0 ) {
908
811
return ;
909
812
}
813
+
814
+ // Ref: https://sourceware.org/git/?p=glibc.git;a=blob;f=resolv/inet_ntop.c;h=c4d38c0f951013e51a4fc6eaa8a9b82e146abe5a;hb=HEAD#l119
815
+ for (int i = 0 ; i < NS_IN6ADDRSZ; i += 2 ) {
816
+ value_.ipv6 [i >> 1 ] = (buf[i] << 8 ) | buf[i + 1 ];
817
+ }
818
+
910
819
type_ = HostType::H_IPV6;
911
820
}
912
821
0 commit comments