Browse Source

context xptr working

boB Rudis 10 months ago
parent
commit
6e4d255bfc
No known key found for this signature in database

+ 2
- 1
DESCRIPTION View File

@@ -23,7 +23,8 @@ Depends:
23 23
 Imports:
24 24
     httr,
25 25
     jsonlite,
26
-    Rcpp
26
+    Rcpp,
27
+    magrittr
27 28
 Roxygen: list(markdown = TRUE)
28 29
 RoxygenNote: 6.1.1
29 30
 LinkingTo: 

+ 5
- 0
NAMESPACE View File

@@ -1,7 +1,12 @@
1 1
 # Generated by roxygen2: do not edit by hand
2 2
 
3
+S3method(print,gctx)
4
+export("%>%")
5
+export(gdns_get_address)
6
+export(gdns_resolver)
3 7
 export(get_address)
4 8
 import(httr)
5 9
 importFrom(Rcpp,sourceCpp)
6 10
 importFrom(jsonlite,fromJSON)
11
+importFrom(magrittr,"%>%")
7 12
 useDynLib(clandnstine, .registration = TRUE)

+ 43
- 0
R/RcppExports.R View File

@@ -14,3 +14,46 @@ get_address <- function(host, resolver = "9.9.9.9") {
14 14
     .Call(`_clandnstine_get_address`, host, resolver)
15 15
 }
16 16
 
17
+#' Test whether an object is an external pointer
18
+#'
19
+#' @param x object to test
20
+check_is_xptr <- function(s) {
21
+    invisible(.Call(`_clandnstine_check_is_xptr`, s))
22
+}
23
+
24
+#' Test whether an external pointer is null
25
+#'
26
+#' @param x object to test
27
+is_null_xptr_ <- function(s) {
28
+    .Call(`_clandnstine_is_null_xptr_`, s)
29
+}
30
+
31
+#' Create a gdns DNS over TLS context and populate it with a resolver
32
+#' for use in resolution functions
33
+#'
34
+#' @param resolver length 1 <chr> of a valid DNS over TLS resolver;
35
+#'        Defaults to Quad9 (`9.9.9.9`).
36
+#' @export
37
+#' @examples
38
+#' x <- gdns_resolver()
39
+gdns_resolver <- function(resolver = "9.9.9.9") {
40
+    .Call(`_clandnstine_gdns_resolver`, resolver)
41
+}
42
+
43
+#' Resolve a host to an addrss
44
+#'
45
+#' @param gctx gdns resolver context created with [gdns_resolver()]
46
+#' @param host to lookup
47
+#' @export
48
+#' @examples
49
+#' x <- gdns_resolver()
50
+#' gdns_get_address(x, "yahoo.com")
51
+#' x %>% gdns_get_address("yahoo.com")
52
+gdns_get_address <- function(gctx, host) {
53
+    .Call(`_clandnstine_gdns_get_address`, gctx, host)
54
+}
55
+
56
+int_get_resolvers <- function(gctx) {
57
+    .Call(`_clandnstine_int_get_resolvers`, gctx)
58
+}
59
+

+ 13
- 0
R/print-context.R View File

@@ -0,0 +1,13 @@
1
+#' Printer for gdns contexts
2
+#'
3
+#' @param x gdns context object
4
+#' @param ... unused
5
+#' @keywords internal
6
+#' @export
7
+print.gctx <- function(x, ...) {
8
+  if (is_null_xptr_(x)) {
9
+    cat("<gdns resolver context (INVALID)>\n")
10
+  } else {
11
+    cat("<gdns resolver context; resolvers: ", int_get_resolvers(x) ,">\n", sep="")
12
+  }
13
+}

+ 11
- 0
R/utils-pipe.R View File

@@ -0,0 +1,11 @@
1
+#' Pipe operator
2
+#'
3
+#' See \code{magrittr::\link[magrittr]{\%>\%}} for details.
4
+#'
5
+#' @name %>%
6
+#' @rdname pipe
7
+#' @keywords internal
8
+#' @export
9
+#' @importFrom magrittr %>%
10
+#' @usage lhs \%>\% rhs
11
+NULL

+ 14
- 0
man/check_is_xptr.Rd View File

@@ -0,0 +1,14 @@
1
+% Generated by roxygen2: do not edit by hand
2
+% Please edit documentation in R/RcppExports.R
3
+\name{check_is_xptr}
4
+\alias{check_is_xptr}
5
+\title{Test whether an object is an external pointer}
6
+\usage{
7
+check_is_xptr(s)
8
+}
9
+\arguments{
10
+\item{x}{object to test}
11
+}
12
+\description{
13
+Test whether an object is an external pointer
14
+}

+ 5
- 1
man/clandnstine.Rd View File

@@ -4,8 +4,12 @@
4 4
 \name{clandnstine}
5 5
 \alias{clandnstine}
6 6
 \alias{clandnstine-package}
7
-\title{...}
7
+\title{Perform 'DNS' over 'TLS' Queries}
8 8
 \description{
9
+Something something 'DNS. Something something 'TLS'.
10
+Something something 'getdns API/library'.
11
+}
12
+\details{
9 13
 \itemize{
10 14
 \item URL: \url{https://gitlab.com/hrbrmstr/clandnstine}
11 15
 \item BugReports: \url{https://gitlab.com/hrbrmstr/clandnstine/issues}

+ 21
- 0
man/gdns_get_address.Rd View File

@@ -0,0 +1,21 @@
1
+% Generated by roxygen2: do not edit by hand
2
+% Please edit documentation in R/RcppExports.R
3
+\name{gdns_get_address}
4
+\alias{gdns_get_address}
5
+\title{Resolve a host to an addrss}
6
+\usage{
7
+gdns_get_address(gctx, host)
8
+}
9
+\arguments{
10
+\item{gctx}{gdns resolver context created with \code{\link[=gdns_resolver]{gdns_resolver()}}}
11
+
12
+\item{host}{to lookup}
13
+}
14
+\description{
15
+Resolve a host to an addrss
16
+}
17
+\examples{
18
+x <- gdns_resolver()
19
+gdns_get_address(x, "yahoo.com")
20
+x \%>\% gdns_get_address("yahoo.com")
21
+}

+ 20
- 0
man/gdns_resolver.Rd View File

@@ -0,0 +1,20 @@
1
+% Generated by roxygen2: do not edit by hand
2
+% Please edit documentation in R/RcppExports.R
3
+\name{gdns_resolver}
4
+\alias{gdns_resolver}
5
+\title{Create a gdns DNS over TLS context and populate it with a resolver
6
+for use in resolution functions}
7
+\usage{
8
+gdns_resolver(resolver = "9.9.9.9")
9
+}
10
+\arguments{
11
+\item{resolver}{length 1 <chr> of a valid DNS over TLS resolver;
12
+Defaults to Quad9 (\code{9.9.9.9}).}
13
+}
14
+\description{
15
+Create a gdns DNS over TLS context and populate it with a resolver
16
+for use in resolution functions
17
+}
18
+\examples{
19
+x <- gdns_resolver()
20
+}

+ 14
- 0
man/is_null_xptr_.Rd View File

@@ -0,0 +1,14 @@
1
+% Generated by roxygen2: do not edit by hand
2
+% Please edit documentation in R/RcppExports.R
3
+\name{is_null_xptr_}
4
+\alias{is_null_xptr_}
5
+\title{Test whether an external pointer is null}
6
+\usage{
7
+is_null_xptr_(s)
8
+}
9
+\arguments{
10
+\item{x}{object to test}
11
+}
12
+\description{
13
+Test whether an external pointer is null
14
+}

+ 12
- 0
man/pipe.Rd View File

@@ -0,0 +1,12 @@
1
+% Generated by roxygen2: do not edit by hand
2
+% Please edit documentation in R/utils-pipe.R
3
+\name{\%>\%}
4
+\alias{\%>\%}
5
+\title{Pipe operator}
6
+\usage{
7
+lhs \%>\% rhs
8
+}
9
+\description{
10
+See \code{magrittr::\link[magrittr]{\%>\%}} for details.
11
+}
12
+\keyword{internal}

+ 17
- 0
man/print.gctx.Rd View File

@@ -0,0 +1,17 @@
1
+% Generated by roxygen2: do not edit by hand
2
+% Please edit documentation in R/print-context.R
3
+\name{print.gctx}
4
+\alias{print.gctx}
5
+\title{Printer for gdns contexts}
6
+\usage{
7
+\method{print}{gctx}(x, ...)
8
+}
9
+\arguments{
10
+\item{x}{gdns context object}
11
+
12
+\item{...}{unused}
13
+}
14
+\description{
15
+Printer for gdns contexts
16
+}
17
+\keyword{internal}

+ 60
- 0
src/RcppExports.cpp View File

@@ -17,9 +17,69 @@ BEGIN_RCPP
17 17
     return rcpp_result_gen;
18 18
 END_RCPP
19 19
 }
20
+// check_is_xptr
21
+void check_is_xptr(SEXP s);
22
+RcppExport SEXP _clandnstine_check_is_xptr(SEXP sSEXP) {
23
+BEGIN_RCPP
24
+    Rcpp::RNGScope rcpp_rngScope_gen;
25
+    Rcpp::traits::input_parameter< SEXP >::type s(sSEXP);
26
+    check_is_xptr(s);
27
+    return R_NilValue;
28
+END_RCPP
29
+}
30
+// is_null_xptr_
31
+SEXP is_null_xptr_(SEXP s);
32
+RcppExport SEXP _clandnstine_is_null_xptr_(SEXP sSEXP) {
33
+BEGIN_RCPP
34
+    Rcpp::RObject rcpp_result_gen;
35
+    Rcpp::RNGScope rcpp_rngScope_gen;
36
+    Rcpp::traits::input_parameter< SEXP >::type s(sSEXP);
37
+    rcpp_result_gen = Rcpp::wrap(is_null_xptr_(s));
38
+    return rcpp_result_gen;
39
+END_RCPP
40
+}
41
+// gdns_resolver
42
+SEXP gdns_resolver(std::string resolver);
43
+RcppExport SEXP _clandnstine_gdns_resolver(SEXP resolverSEXP) {
44
+BEGIN_RCPP
45
+    Rcpp::RObject rcpp_result_gen;
46
+    Rcpp::RNGScope rcpp_rngScope_gen;
47
+    Rcpp::traits::input_parameter< std::string >::type resolver(resolverSEXP);
48
+    rcpp_result_gen = Rcpp::wrap(gdns_resolver(resolver));
49
+    return rcpp_result_gen;
50
+END_RCPP
51
+}
52
+// gdns_get_address
53
+CharacterVector gdns_get_address(SEXP gctx, std::string host);
54
+RcppExport SEXP _clandnstine_gdns_get_address(SEXP gctxSEXP, SEXP hostSEXP) {
55
+BEGIN_RCPP
56
+    Rcpp::RObject rcpp_result_gen;
57
+    Rcpp::RNGScope rcpp_rngScope_gen;
58
+    Rcpp::traits::input_parameter< SEXP >::type gctx(gctxSEXP);
59
+    Rcpp::traits::input_parameter< std::string >::type host(hostSEXP);
60
+    rcpp_result_gen = Rcpp::wrap(gdns_get_address(gctx, host));
61
+    return rcpp_result_gen;
62
+END_RCPP
63
+}
64
+// int_get_resolvers
65
+CharacterVector int_get_resolvers(SEXP gctx);
66
+RcppExport SEXP _clandnstine_int_get_resolvers(SEXP gctxSEXP) {
67
+BEGIN_RCPP
68
+    Rcpp::RObject rcpp_result_gen;
69
+    Rcpp::RNGScope rcpp_rngScope_gen;
70
+    Rcpp::traits::input_parameter< SEXP >::type gctx(gctxSEXP);
71
+    rcpp_result_gen = Rcpp::wrap(int_get_resolvers(gctx));
72
+    return rcpp_result_gen;
73
+END_RCPP
74
+}
20 75
 
21 76
 static const R_CallMethodDef CallEntries[] = {
22 77
     {"_clandnstine_get_address", (DL_FUNC) &_clandnstine_get_address, 2},
78
+    {"_clandnstine_check_is_xptr", (DL_FUNC) &_clandnstine_check_is_xptr, 1},
79
+    {"_clandnstine_is_null_xptr_", (DL_FUNC) &_clandnstine_is_null_xptr_, 1},
80
+    {"_clandnstine_gdns_resolver", (DL_FUNC) &_clandnstine_gdns_resolver, 1},
81
+    {"_clandnstine_gdns_get_address", (DL_FUNC) &_clandnstine_gdns_get_address, 2},
82
+    {"_clandnstine_int_get_resolvers", (DL_FUNC) &_clandnstine_int_get_resolvers, 1},
23 83
     {NULL, NULL, 0}
24 84
 };
25 85
 

+ 1
- 1
src/clandnstine-main.cpp View File

@@ -59,7 +59,7 @@ CharacterVector get_address(std::string host, std::string resolver = "9.9.9.9")
59 59
       r = getdns_list_get_dict(addrs, i, &cur_addr);
60 60
       r = getdns_dict_get_bindata(cur_addr, "address_data", &address);
61 61
 
62
-      if (address->size == 4 || address->size == 16) { // this is unlikely
62
+      if (address->size == 4 || address->size == 16) { // this is unlikely to be bad
63 63
         char *addr_str = getdns_display_ip_address(address);
64 64
         out.push_back(addr_str);
65 65
         if (addr_str) free(addr_str);

+ 192
- 0
src/resolver.cpp View File

@@ -0,0 +1,192 @@
1
+#include <Rcpp.h>
2
+#include <getdns/getdns.h>
3
+#include <getdns/getdns_extra.h>
4
+#include <arpa/inet.h>
5
+using namespace Rcpp;
6
+
7
+//' Test whether an object is an external pointer
8
+//'
9
+//' @param x object to test
10
+// [[Rcpp::export]]
11
+void check_is_xptr(SEXP s) {
12
+  if (TYPEOF(s) != EXTPTRSXP) {
13
+    Rf_error("expected an externalptr");
14
+  }
15
+}
16
+
17
+//' Test whether an external pointer is null
18
+//'
19
+//' @param x object to test
20
+// [[Rcpp::export]]
21
+SEXP is_null_xptr_(SEXP s) {
22
+  check_is_xptr(s);
23
+  return Rf_ScalarLogical(R_ExternalPtrAddr(s) == NULL);
24
+}
25
+
26
+static void gctx_finalizer(SEXP ptr) {
27
+  if(!R_ExternalPtrAddr(ptr)) return;
28
+  getdns_context *ctxt = (getdns_context *)R_ExternalPtrAddr(ptr);
29
+  if (ptr) getdns_context_destroy(ctxt);
30
+  R_ClearExternalPtr(ptr); /* not really needed */
31
+}
32
+
33
+//' Create a gdns DNS over TLS context and populate it with a resolver
34
+//' for use in resolution functions
35
+//'
36
+//' @param resolver length 1 <chr> of a valid DNS over TLS resolver;
37
+//'        Defaults to Quad9 (`9.9.9.9`).
38
+//' @export
39
+//' @examples
40
+//' x <- gdns_resolver()
41
+// [[Rcpp::export]]
42
+SEXP gdns_resolver(std::string resolver = "9.9.9.9") {
43
+
44
+  bool ok = false;
45
+  SEXP ptr;
46
+  getdns_return_t r;
47
+  getdns_context *ctxt = NULL;
48
+
49
+  getdns_dict *resolver_dict = getdns_dict_create();
50
+  r = getdns_str2dict(resolver.c_str(), &resolver_dict);
51
+
52
+  getdns_list *resolver_list = getdns_list_create();
53
+  r = getdns_list_set_dict(resolver_list, 0, resolver_dict);
54
+
55
+  getdns_transport_list_t tls_transport[] = { GETDNS_TRANSPORT_TLS };
56
+
57
+  if ((r = getdns_context_create(&ctxt, 1))) {
58
+  } else if ((r = getdns_context_set_dns_transport_list(ctxt, 1, tls_transport))) {
59
+  } else if ((r = getdns_context_set_upstream_recursive_servers(ctxt, resolver_list))) {
60
+  } else if ((r = getdns_context_set_resolution_type(ctxt, GETDNS_RESOLUTION_STUB))) {
61
+  } else {
62
+    ok = true;
63
+  }
64
+
65
+  if (ok) {
66
+    ptr = R_MakeExternalPtr(ctxt, Rf_install("gctx"), R_NilValue);
67
+    R_RegisterCFinalizerEx(ptr, gctx_finalizer, TRUE);
68
+    Rf_setAttrib(ptr, Rf_install("class"), Rf_mkString("gctx"));
69
+    return(ptr);
70
+  } else {
71
+    return(R_NilValue);
72
+  }
73
+
74
+}
75
+
76
+//' Resolve a host to an addrss
77
+//'
78
+//' @param gctx gdns resolver context created with [gdns_resolver()]
79
+//' @param host to lookup
80
+//' @export
81
+//' @examples
82
+//' x <- gdns_resolver()
83
+//' gdns_get_address(x, "yahoo.com")
84
+//' x %>% gdns_get_address("yahoo.com")
85
+// [[Rcpp::export]]
86
+CharacterVector gdns_get_address(SEXP gctx, std::string host) {
87
+
88
+  uint32_t err;
89
+  size_t sz;
90
+  getdns_return_t r;
91
+  getdns_dict *resp = NULL;
92
+  getdns_list *addrs;
93
+  std::vector< std::string > out;
94
+  bool ok = false;
95
+
96
+  getdns_context *ctxt = (getdns_context *)R_ExternalPtrAddr(gctx);
97
+
98
+  if (gctx == NULL) return(CharacterVector());
99
+
100
+  if ((r = getdns_address_sync(ctxt, host.c_str(), NULL, &resp))) {
101
+  } else if ((r = getdns_dict_get_int(resp, "status", &err))) {
102
+  } else if (err != GETDNS_RESPSTATUS_GOOD) {
103
+  } else if ((r = getdns_dict_get_list(resp, "just_address_answers", &addrs))) {
104
+  } else if (r != GETDNS_RETURN_GOOD) {
105
+  } else if ((r = getdns_list_get_length(addrs, &sz))) {
106
+  } else {
107
+    ok = true;
108
+  }
109
+
110
+  if (ok) {
111
+
112
+    out.reserve(sz);
113
+
114
+    for (size_t i = 0; i < sz; ++i) {
115
+
116
+      getdns_dict *cur_addr;
117
+      getdns_bindata *address;
118
+
119
+      r = getdns_list_get_dict(addrs, i, &cur_addr);
120
+      r = getdns_dict_get_bindata(cur_addr, "address_data", &address);
121
+
122
+      if (address->size == 4 || address->size == 16) { // this is unlikely to be bad
123
+        char *addr_str = getdns_display_ip_address(address);
124
+        out.push_back(addr_str);
125
+        if (addr_str) free(addr_str);
126
+      }
127
+
128
+    }
129
+
130
+    out.shrink_to_fit();
131
+
132
+  }
133
+
134
+  if (resp) getdns_dict_destroy(resp);
135
+
136
+  if (ok) return(wrap(out)); else return(CharacterVector());
137
+
138
+}
139
+
140
+// [[Rcpp::export]]
141
+CharacterVector int_get_resolvers(SEXP gctx) {
142
+
143
+  bool ok = false;
144
+  size_t sz;
145
+  getdns_list *addrs;
146
+  std::vector< std::string > out;
147
+
148
+  getdns_context *ctxt = (getdns_context *)R_ExternalPtrAddr(gctx);
149
+  if (gctx == NULL) return(CharacterVector());
150
+
151
+  getdns_return_t r;
152
+
153
+  if ((r = getdns_context_get_upstream_recursive_servers(ctxt, &addrs))) {
154
+  } else if (r != GETDNS_RETURN_GOOD) {
155
+  } else if ((r = getdns_list_get_length(addrs, &sz))) {
156
+  } else {
157
+    ok = true;
158
+  }
159
+
160
+  if (ok) {
161
+
162
+    out.reserve(sz);
163
+
164
+    for (size_t i = 0; i < sz; ++i) {
165
+
166
+      getdns_dict *cur_addr;
167
+      getdns_bindata *address;
168
+
169
+      r = getdns_list_get_dict(addrs, i, &cur_addr);
170
+      r = getdns_dict_get_bindata(cur_addr, "address_data", &address);
171
+
172
+      if (address->size == 4 || address->size == 16) { // this is unlikely to be bad
173
+        char *addr_str = getdns_display_ip_address(address);
174
+        out.push_back(addr_str);
175
+        if (addr_str) free(addr_str);
176
+      }
177
+
178
+    }
179
+
180
+    out.shrink_to_fit();
181
+
182
+  }
183
+
184
+  if (addrs) getdns_list_destroy(addrs);
185
+
186
+  if (ok) return(wrap(out)); else return(CharacterVector());
187
+
188
+}
189
+
190
+
191
+
192
+

+ 3
- 2
tests/testthat/test-clandnstine.R View File

@@ -1,6 +1,7 @@
1
-context("minimal package functionality")
1
+context("basic wrapper works")
2 2
 test_that("we can do something", {
3 3
 
4
-  #expect_that(some_function(), is_a("data.frame"))
4
+  x <- get_address("example.com")
5
+  expect_true(all(c("2606:2800:220:1:248:1893:25c8:1946", "93.184.216.34") %in% x))
5 6
 
6 7
 })

Loading…
Cancel
Save