// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #include extern ircd::mapi::header IRCD_MODULE; namespace ircd::net::dns { struct tag; using answers = vector_view; using answers_callback = std::function; constexpr const size_t MAX_COUNT {64}; } namespace ircd::net::dns::cache { struct waiter; bool operator==(const waiter &, const waiter &); bool operator!=(const waiter &, const waiter &); bool call_waiter(const string_view &, const string_view &, const json::array &, waiter &); size_t call_waiters(const string_view &, const string_view &, const json::array &); void handle(const m::event &, m::vm::eval &); bool put(const string_view &type, const string_view &state_key, const records &rrs); bool put(const string_view &type, const string_view &state_key, const uint &code, const string_view &msg); void fini(); void init(); extern conf::item min_ttl IRCD_MODULE_EXPORT_DATA; extern conf::item error_ttl IRCD_MODULE_EXPORT_DATA; extern conf::item nxdomain_ttl IRCD_MODULE_EXPORT_DATA; extern const m::room::id::buf room_id; extern m::hookfn hook; extern std::list waiting; extern ctx::mutex mutex; extern ctx::dock dock; } struct ircd::net::dns::cache::waiter { dns::callback callback; dns::opts opts; uint16_t port; string_view key; char keybuf[rfc1035::NAME_BUFSIZE*2]; waiter(const hostport &hp, const dns::opts &opts, dns::callback &&callback); waiter(waiter &&) = delete; waiter(const waiter &) = delete; waiter &operator=(waiter &&) = delete; waiter &operator=(const waiter &) = delete; }; // // s_dns_resolver.cc // namespace ircd::net::dns { // Resolver instance struct resolver extern *resolver_instance; uint16_t resolver_call(const hostport &, const opts &); void resolver_init(answers_callback); void resolver_fini(); } struct ircd::net::dns::resolver { using header = rfc1035::header; static conf::item servers; static conf::item timeout; static conf::item send_rate; static conf::item send_burst; static conf::item retry_max; answers_callback callback; std::vector server; // The list of active servers size_t server_next{0}; // Round-robin state to hit servers ctx::dock dock, done; ctx::mutex mutex; std::map tags; // The active requests steady_point send_last; // Time of last send std::deque sendq; // Queue of frames for rate-limiting ip::udp::socket ns; // A pollable activity object // util void add_server(const ipport &); void add_server(const string_view &); void set_servers(const string_view &list); void set_servers(); // removal (must have lock) void unqueue(tag &); void remove(tag &); decltype(tags)::iterator remove(tag &, const decltype(tags)::iterator &); void error_one(tag &, const std::exception_ptr &, const bool &remove = true); void error_one(tag &, const std::system_error &, const bool &remove = true); void error_all(const std::error_code &, const bool &remove = true); void cancel_all(const bool &remove = true); // reception bool handle_error(const header &, tag &); void handle_reply(const header &, const const_buffer &body, tag &); void handle_reply(const ipport &, const header &, const const_buffer &body); void handle(const ipport &, const mutable_buffer &); void recv_worker(); ctx::context recv_context; // submission void send_query(const ip::udp::endpoint &, tag &); void queue_query(tag &); void send_query(tag &); void submit(tag &); // timeout bool check_timeout(const uint16_t &id, tag &, const steady_point &expired); void check_timeouts(const milliseconds &timeout); void timeout_worker(); ctx::context timeout_context; // sendq void flush(const uint16_t &); void sendq_work(); void sendq_clear(); void sendq_worker(); ctx::context sendq_context; template tag &set_tag(A&&...); const_buffer make_query(const mutable_buffer &buf, tag &); uint16_t operator()(const hostport &, const opts &); resolver(answers_callback); ~resolver() noexcept; }; struct ircd::net::dns::tag { uint16_t id {0}; hostport hp; dns::opts opts; // note: invalid after query sent const_buffer question; steady_point last {steady_point::min()}; uint8_t tries {0}; uint rcode {0}; ipport server; char hostbuf[rfc1035::NAME_BUFSIZE]; char qbuf[512]; tag(const hostport &hp, const dns::opts &opts) :hp{hp} ,opts{opts} { this->hp.host = { hostbuf, copy(hostbuf, hp.host) }; this->hp.service = {}; } tag(tag &&) = delete; tag(const tag &) = delete; tag &operator=(tag &&) = delete; tag &operator=(const tag &) = delete; };