From 7b4c06575fd3eb9c7ac33cf4601881438d8e6342 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 27 Oct 2016 23:33:50 -0700 Subject: [PATCH] modules: Add DNS module with Node.js compatible lookup(). --- modules/Makefile.am | 4 ++ modules/dns/dns.cc | 52 +++++++++++++++++++++++ modules/dns/dns.h | 27 ++++++++++++ modules/dns/lookup.cc | 95 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 modules/dns/dns.cc create mode 100644 modules/dns/dns.h create mode 100644 modules/dns/lookup.cc diff --git a/modules/Makefile.am b/modules/Makefile.am index 2bc7229f3..8b49ec5cc 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -36,6 +36,10 @@ conf_module_LTLIBRARIES = \ conf/conf_serverinfo.la \ conf/conf_listen.la +dns_moduledir=@moduledir@ +dns_module_LTLIBRARIES = dns/dns.la +dns_dns_la_SOURCES = dns/dns.cc \ + dns/lookup.cc moduledir=@moduledir@ future_la_SOURCES = future.cc diff --git a/modules/dns/dns.cc b/modules/dns/dns.cc new file mode 100644 index 000000000..dff689d21 --- /dev/null +++ b/modules/dns/dns.cc @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "dns.h" + +namespace ircd { +namespace js { + +struct dns +:trap +{ + using trap::trap; +} +dns{"dns"}; + +} // namespace js +} // namespace ircd + +ip::tcp::resolver tcp_resolver +{ + *ircd::ios +}; + +ircd::mapi::fini dtors{[] +{ + tcp_resolver.cancel(); +}}; + +ircd::mapi::header IRCD_MODULE +{ + "Client interface to the Domain Name Service", + ircd::mapi::NO_FLAGS, + &dtors +}; diff --git a/modules/dns/dns.h b/modules/dns/dns.h new file mode 100644 index 000000000..91aaff8d3 --- /dev/null +++ b/modules/dns/dns.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +namespace ip = boost::asio::ip; + +extern ip::tcp::resolver tcp_resolver; // dns.cc diff --git a/modules/dns/lookup.cc b/modules/dns/lookup.cc new file mode 100644 index 000000000..42422566b --- /dev/null +++ b/modules/dns/lookup.cc @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "dns.h" + +namespace ircd { +namespace js { + +extern trap dns; + +struct lookup +:trap::function +{ + trap &future{trap::find("future")}; + + value handle_result(const boost::system::error_code &, ip::tcp::resolver::iterator &); + value on_call(object::handle obj, value::handle, const args &args) override; + using trap::function::function; +} +static lookup +{ + dns, "lookup" +}; + + +} // namespace js +} // namespace ircd + +// system-level hostname resolution +// +// args[0]: hostname - string +// args[1]: [options] - object or integer; integer = 4 or 6 +// args[2]: [callback] - function; undefined = yield +// +// https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback +// +ircd::js::value +ircd::js::lookup::on_call(object::handle obj, + value::handle that, + const args &args) +{ + const string hostname{args[0]}; + const object options{args.has(1)? args[1] : value{}}; //TODO: Node.js options + const value callback{args.has(2)? args[2] : value{}}; + const ip::tcp::resolver::query query + { + std::string(hostname), + std::string{} + }; + + auto &task(task::get()); + contract result(ctor(future, vector{{callback}})); + tcp_resolver.async_resolve(query, [this, result] + (const boost::system::error_code &ec, ip::tcp::resolver::iterator it) + mutable + { + result(std::bind(&lookup::handle_result, this, std::ref(ec), std::ref(it))); + }); + + return result; +} + +ircd::js::value +ircd::js::lookup::handle_result(const boost::system::error_code &ec, + ip::tcp::resolver::iterator &it) +{ + static const ip::tcp::resolver::iterator end; + + if(ec) + throw jserror("%s", ec.message().c_str()); + + vector addrs; + for(; it != end; ++it) + addrs.append(string(it->endpoint().address().to_string())); + + return object(addrs); +}