diff --git a/ircd/m/id.cc b/ircd/m/id.cc index 950b9d0cb..268dab560 100644 --- a/ircd/m/id.cc +++ b/ircd/m/id.cc @@ -120,26 +120,74 @@ struct ircd::m::id::input ,"prefix" }; - //TODO: XXX----------------- - //TODO: XXX start an ircd::net grammar; move to net:: -/* - rule authority - { - //TODO: https://tools.ietf.org/html/rfc3986#section-3.2 - -('/' >> '/') >> raw[*(char_ - '/')] >> '/' - }; -*/ const rule<> port { ushort_ - ,"port" + ,"port number" + }; + + const rule<> ip4_octet + { + repeat(1,3)[char_("0-9")] + ,"IPv4 octet" + }; + + const rule<> ip4_literal + { + repeat(3)[ip4_octet >> '.'] >> ip4_octet + ,"IPv4 literal" + }; + + const rule<> ip6_char + { + char_("0-9a-fA-F") + ,"IPv6 character" + }; + + const rule<> ip6_h16 + { + repeat(1,4)[ip6_char] + ,"IPv6 hexdigit" + }; + + const rule<> ip6_piece + { + ip6_h16 >> ':' + ,"IPv6 address piece" + }; + + // This is reversed from the BNF in the RFC otherwise it requires + // backtracking during the repeat[]; grammars are adjusted accordingly. + const rule<> ip6_ipiece + { + ':' >> ip6_h16 + ,"IPv6 address piece" + }; + + const rule<> ip6_ls32 + { + (ip6_h16 >> ':' >> ip6_h16) | ip4_literal + }; + + /// https://tools.ietf.org/html/rfc3986 Appendix A + const rule<> ip6_addr[10] + { + { repeat(6)[ip6_piece] >> ip6_ls32 }, + { lit("::") >> repeat(5)[ip6_piece] >> ip6_ls32 }, + { ip6_h16 >> lit("::") >> repeat(4)[ip6_piece] >> ip6_ls32 }, + { ip6_h16 >> repeat(0,1)[ip6_ipiece] >> lit("::") >> repeat(3)[ip6_piece] >> ip6_ls32 }, + { ip6_h16 >> repeat(0,2)[ip6_ipiece] >> lit("::") >> repeat(2)[ip6_piece] >> ip6_ls32 }, + { ip6_h16 >> repeat(0,3)[ip6_ipiece] >> lit("::") >> ip6_piece >> ip6_ls32 }, + { ip6_h16 >> repeat(0,4)[ip6_ipiece] >> lit("::") >> ip6_ls32 }, + { ip6_h16 >> repeat(0,5)[ip6_ipiece] >> lit("::") >> -ip6_h16 }, + { lit("::") >> -ip6_h16 }, }; const rule<> ip6_address { - //TODO: XXX - *char_("0-9a-fA-F:") - ,"ip6 address" + ip6_addr[0] | ip6_addr[1] | ip6_addr[2] | ip6_addr[3] | ip6_addr[4] | ip6_addr[5] | + ip6_addr[6] | ip6_addr[7] | ip6_addr[8] | ip6_addr[9] + ,"IPv6 address" }; const rule<> ip6_literal @@ -148,13 +196,22 @@ struct ircd::m::id::input ,"ip6 literal" }; - const rule<> dns_name + const rule<> hostlabel { - ip6_literal | *(char_ - ':') - ,"dns name" + char_("A-Za-z0-9") >> *(char_("A-Za-z0-9\x2D")) // x2D is '-' }; - //TODO: /XXX----------------- + const rule<> hostname + { + hostlabel % '.', + "hostname" + }; + + const rule<> dns_name + { + ip6_literal | ip4_literal | hostname + ,"DNS name" + }; /// (Appendix 4.1) Server Name /// A homeserver is uniquely identified by its server name. This value @@ -174,7 +231,7 @@ struct ircd::m::id::input /// `[1234:5678::abcd]:5678` (IPv6 literal with explicit port) const rule<> server_name { - dns_name >> -(':' >> port) + dns_name >> -(':' > port) ,"server name" };