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