boB Rudis
5 years ago
16 changed files with 433 additions and 5 deletions
@ -1,7 +1,12 @@ |
|||||
# Generated by roxygen2: do not edit by hand |
# Generated by roxygen2: do not edit by hand |
||||
|
|
||||
|
S3method(print,gctx) |
||||
|
export("%>%") |
||||
|
export(gdns_get_address) |
||||
|
export(gdns_resolver) |
||||
export(get_address) |
export(get_address) |
||||
import(httr) |
import(httr) |
||||
importFrom(Rcpp,sourceCpp) |
importFrom(Rcpp,sourceCpp) |
||||
importFrom(jsonlite,fromJSON) |
importFrom(jsonlite,fromJSON) |
||||
|
importFrom(magrittr,"%>%") |
||||
useDynLib(clandnstine, .registration = TRUE) |
useDynLib(clandnstine, .registration = TRUE) |
||||
|
@ -0,0 +1,13 @@ |
|||||
|
#' Printer for gdns contexts |
||||
|
#' |
||||
|
#' @param x gdns context object |
||||
|
#' @param ... unused |
||||
|
#' @keywords internal |
||||
|
#' @export |
||||
|
print.gctx <- function(x, ...) { |
||||
|
if (is_null_xptr_(x)) { |
||||
|
cat("<gdns resolver context (INVALID)>\n") |
||||
|
} else { |
||||
|
cat("<gdns resolver context; resolvers: ", int_get_resolvers(x) ,">\n", sep="") |
||||
|
} |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
#' Pipe operator |
||||
|
#' |
||||
|
#' See \code{magrittr::\link[magrittr]{\%>\%}} for details. |
||||
|
#' |
||||
|
#' @name %>% |
||||
|
#' @rdname pipe |
||||
|
#' @keywords internal |
||||
|
#' @export |
||||
|
#' @importFrom magrittr %>% |
||||
|
#' @usage lhs \%>\% rhs |
||||
|
NULL |
@ -0,0 +1,14 @@ |
|||||
|
% Generated by roxygen2: do not edit by hand |
||||
|
% Please edit documentation in R/RcppExports.R |
||||
|
\name{check_is_xptr} |
||||
|
\alias{check_is_xptr} |
||||
|
\title{Test whether an object is an external pointer} |
||||
|
\usage{ |
||||
|
check_is_xptr(s) |
||||
|
} |
||||
|
\arguments{ |
||||
|
\item{x}{object to test} |
||||
|
} |
||||
|
\description{ |
||||
|
Test whether an object is an external pointer |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
% Generated by roxygen2: do not edit by hand |
||||
|
% Please edit documentation in R/RcppExports.R |
||||
|
\name{gdns_get_address} |
||||
|
\alias{gdns_get_address} |
||||
|
\title{Resolve a host to an addrss} |
||||
|
\usage{ |
||||
|
gdns_get_address(gctx, host) |
||||
|
} |
||||
|
\arguments{ |
||||
|
\item{gctx}{gdns resolver context created with \code{\link[=gdns_resolver]{gdns_resolver()}}} |
||||
|
|
||||
|
\item{host}{to lookup} |
||||
|
} |
||||
|
\description{ |
||||
|
Resolve a host to an addrss |
||||
|
} |
||||
|
\examples{ |
||||
|
x <- gdns_resolver() |
||||
|
gdns_get_address(x, "yahoo.com") |
||||
|
x \%>\% gdns_get_address("yahoo.com") |
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
% Generated by roxygen2: do not edit by hand |
||||
|
% Please edit documentation in R/RcppExports.R |
||||
|
\name{gdns_resolver} |
||||
|
\alias{gdns_resolver} |
||||
|
\title{Create a gdns DNS over TLS context and populate it with a resolver |
||||
|
for use in resolution functions} |
||||
|
\usage{ |
||||
|
gdns_resolver(resolver = "9.9.9.9") |
||||
|
} |
||||
|
\arguments{ |
||||
|
\item{resolver}{length 1 <chr> of a valid DNS over TLS resolver; |
||||
|
Defaults to Quad9 (\code{9.9.9.9}).} |
||||
|
} |
||||
|
\description{ |
||||
|
Create a gdns DNS over TLS context and populate it with a resolver |
||||
|
for use in resolution functions |
||||
|
} |
||||
|
\examples{ |
||||
|
x <- gdns_resolver() |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
% Generated by roxygen2: do not edit by hand |
||||
|
% Please edit documentation in R/RcppExports.R |
||||
|
\name{is_null_xptr_} |
||||
|
\alias{is_null_xptr_} |
||||
|
\title{Test whether an external pointer is null} |
||||
|
\usage{ |
||||
|
is_null_xptr_(s) |
||||
|
} |
||||
|
\arguments{ |
||||
|
\item{x}{object to test} |
||||
|
} |
||||
|
\description{ |
||||
|
Test whether an external pointer is null |
||||
|
} |
@ -0,0 +1,12 @@ |
|||||
|
% Generated by roxygen2: do not edit by hand |
||||
|
% Please edit documentation in R/utils-pipe.R |
||||
|
\name{\%>\%} |
||||
|
\alias{\%>\%} |
||||
|
\title{Pipe operator} |
||||
|
\usage{ |
||||
|
lhs \%>\% rhs |
||||
|
} |
||||
|
\description{ |
||||
|
See \code{magrittr::\link[magrittr]{\%>\%}} for details. |
||||
|
} |
||||
|
\keyword{internal} |
@ -0,0 +1,17 @@ |
|||||
|
% Generated by roxygen2: do not edit by hand |
||||
|
% Please edit documentation in R/print-context.R |
||||
|
\name{print.gctx} |
||||
|
\alias{print.gctx} |
||||
|
\title{Printer for gdns contexts} |
||||
|
\usage{ |
||||
|
\method{print}{gctx}(x, ...) |
||||
|
} |
||||
|
\arguments{ |
||||
|
\item{x}{gdns context object} |
||||
|
|
||||
|
\item{...}{unused} |
||||
|
} |
||||
|
\description{ |
||||
|
Printer for gdns contexts |
||||
|
} |
||||
|
\keyword{internal} |
@ -0,0 +1,192 @@ |
|||||
|
#include <Rcpp.h> |
||||
|
#include <getdns/getdns.h> |
||||
|
#include <getdns/getdns_extra.h> |
||||
|
#include <arpa/inet.h> |
||||
|
using namespace Rcpp; |
||||
|
|
||||
|
//' Test whether an object is an external pointer
|
||||
|
//'
|
||||
|
//' @param x object to test
|
||||
|
// [[Rcpp::export]]
|
||||
|
void check_is_xptr(SEXP s) { |
||||
|
if (TYPEOF(s) != EXTPTRSXP) { |
||||
|
Rf_error("expected an externalptr"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//' Test whether an external pointer is null
|
||||
|
//'
|
||||
|
//' @param x object to test
|
||||
|
// [[Rcpp::export]]
|
||||
|
SEXP is_null_xptr_(SEXP s) { |
||||
|
check_is_xptr(s); |
||||
|
return Rf_ScalarLogical(R_ExternalPtrAddr(s) == NULL); |
||||
|
} |
||||
|
|
||||
|
static void gctx_finalizer(SEXP ptr) { |
||||
|
if(!R_ExternalPtrAddr(ptr)) return; |
||||
|
getdns_context *ctxt = (getdns_context *)R_ExternalPtrAddr(ptr); |
||||
|
if (ptr) getdns_context_destroy(ctxt); |
||||
|
R_ClearExternalPtr(ptr); /* not really needed */ |
||||
|
} |
||||
|
|
||||
|
//' Create a gdns DNS over TLS context and populate it with a resolver
|
||||
|
//' for use in resolution functions
|
||||
|
//'
|
||||
|
//' @param resolver length 1 <chr> of a valid DNS over TLS resolver;
|
||||
|
//' Defaults to Quad9 (`9.9.9.9`).
|
||||
|
//' @export
|
||||
|
//' @examples
|
||||
|
//' x <- gdns_resolver()
|
||||
|
// [[Rcpp::export]]
|
||||
|
SEXP gdns_resolver(std::string resolver = "9.9.9.9") { |
||||
|
|
||||
|
bool ok = false; |
||||
|
SEXP ptr; |
||||
|
getdns_return_t r; |
||||
|
getdns_context *ctxt = NULL; |
||||
|
|
||||
|
getdns_dict *resolver_dict = getdns_dict_create(); |
||||
|
r = getdns_str2dict(resolver.c_str(), &resolver_dict); |
||||
|
|
||||
|
getdns_list *resolver_list = getdns_list_create(); |
||||
|
r = getdns_list_set_dict(resolver_list, 0, resolver_dict); |
||||
|
|
||||
|
getdns_transport_list_t tls_transport[] = { GETDNS_TRANSPORT_TLS }; |
||||
|
|
||||
|
if ((r = getdns_context_create(&ctxt, 1))) { |
||||
|
} else if ((r = getdns_context_set_dns_transport_list(ctxt, 1, tls_transport))) { |
||||
|
} else if ((r = getdns_context_set_upstream_recursive_servers(ctxt, resolver_list))) { |
||||
|
} else if ((r = getdns_context_set_resolution_type(ctxt, GETDNS_RESOLUTION_STUB))) { |
||||
|
} else { |
||||
|
ok = true; |
||||
|
} |
||||
|
|
||||
|
if (ok) { |
||||
|
ptr = R_MakeExternalPtr(ctxt, Rf_install("gctx"), R_NilValue); |
||||
|
R_RegisterCFinalizerEx(ptr, gctx_finalizer, TRUE); |
||||
|
Rf_setAttrib(ptr, Rf_install("class"), Rf_mkString("gctx")); |
||||
|
return(ptr); |
||||
|
} else { |
||||
|
return(R_NilValue); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
//' Resolve a host to an addrss
|
||||
|
//'
|
||||
|
//' @param gctx gdns resolver context created with [gdns_resolver()]
|
||||
|
//' @param host to lookup
|
||||
|
//' @export
|
||||
|
//' @examples
|
||||
|
//' x <- gdns_resolver()
|
||||
|
//' gdns_get_address(x, "yahoo.com")
|
||||
|
//' x %>% gdns_get_address("yahoo.com")
|
||||
|
// [[Rcpp::export]]
|
||||
|
CharacterVector gdns_get_address(SEXP gctx, std::string host) { |
||||
|
|
||||
|
uint32_t err; |
||||
|
size_t sz; |
||||
|
getdns_return_t r; |
||||
|
getdns_dict *resp = NULL; |
||||
|
getdns_list *addrs; |
||||
|
std::vector< std::string > out; |
||||
|
bool ok = false; |
||||
|
|
||||
|
getdns_context *ctxt = (getdns_context *)R_ExternalPtrAddr(gctx); |
||||
|
|
||||
|
if (gctx == NULL) return(CharacterVector()); |
||||
|
|
||||
|
if ((r = getdns_address_sync(ctxt, host.c_str(), NULL, &resp))) { |
||||
|
} else if ((r = getdns_dict_get_int(resp, "status", &err))) { |
||||
|
} else if (err != GETDNS_RESPSTATUS_GOOD) { |
||||
|
} else if ((r = getdns_dict_get_list(resp, "just_address_answers", &addrs))) { |
||||
|
} else if (r != GETDNS_RETURN_GOOD) { |
||||
|
} else if ((r = getdns_list_get_length(addrs, &sz))) { |
||||
|
} else { |
||||
|
ok = true; |
||||
|
} |
||||
|
|
||||
|
if (ok) { |
||||
|
|
||||
|
out.reserve(sz); |
||||
|
|
||||
|
for (size_t i = 0; i < sz; ++i) { |
||||
|
|
||||
|
getdns_dict *cur_addr; |
||||
|
getdns_bindata *address; |
||||
|
|
||||
|
r = getdns_list_get_dict(addrs, i, &cur_addr); |
||||
|
r = getdns_dict_get_bindata(cur_addr, "address_data", &address); |
||||
|
|
||||
|
if (address->size == 4 || address->size == 16) { // this is unlikely to be bad
|
||||
|
char *addr_str = getdns_display_ip_address(address); |
||||
|
out.push_back(addr_str); |
||||
|
if (addr_str) free(addr_str); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
out.shrink_to_fit(); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
if (resp) getdns_dict_destroy(resp); |
||||
|
|
||||
|
if (ok) return(wrap(out)); else return(CharacterVector()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// [[Rcpp::export]]
|
||||
|
CharacterVector int_get_resolvers(SEXP gctx) { |
||||
|
|
||||
|
bool ok = false; |
||||
|
size_t sz; |
||||
|
getdns_list *addrs; |
||||
|
std::vector< std::string > out; |
||||
|
|
||||
|
getdns_context *ctxt = (getdns_context *)R_ExternalPtrAddr(gctx); |
||||
|
if (gctx == NULL) return(CharacterVector()); |
||||
|
|
||||
|
getdns_return_t r; |
||||
|
|
||||
|
if ((r = getdns_context_get_upstream_recursive_servers(ctxt, &addrs))) { |
||||
|
} else if (r != GETDNS_RETURN_GOOD) { |
||||
|
} else if ((r = getdns_list_get_length(addrs, &sz))) { |
||||
|
} else { |
||||
|
ok = true; |
||||
|
} |
||||
|
|
||||
|
if (ok) { |
||||
|
|
||||
|
out.reserve(sz); |
||||
|
|
||||
|
for (size_t i = 0; i < sz; ++i) { |
||||
|
|
||||
|
getdns_dict *cur_addr; |
||||
|
getdns_bindata *address; |
||||
|
|
||||
|
r = getdns_list_get_dict(addrs, i, &cur_addr); |
||||
|
r = getdns_dict_get_bindata(cur_addr, "address_data", &address); |
||||
|
|
||||
|
if (address->size == 4 || address->size == 16) { // this is unlikely to be bad
|
||||
|
char *addr_str = getdns_display_ip_address(address); |
||||
|
out.push_back(addr_str); |
||||
|
if (addr_str) free(addr_str); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
out.shrink_to_fit(); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
if (addrs) getdns_list_destroy(addrs); |
||||
|
|
||||
|
if (ok) return(wrap(out)); else return(CharacterVector()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -1,6 +1,7 @@ |
|||||
context("minimal package functionality") |
context("basic wrapper works") |
||||
test_that("we can do something", { |
test_that("we can do something", { |
||||
|
|
||||
#expect_that(some_function(), is_a("data.frame")) |
x <- get_address("example.com") |
||||
|
expect_true(all(c("2606:2800:220:1:248:1893:25c8:1946", "93.184.216.34") %in% x)) |
||||
|
|
||||
}) |
}) |
||||
|
Loading…
Reference in new issue