Browse Source

working basic services

master
boB Rudis 4 years ago
parent
commit
d11622c511
No known key found for this signature in database GPG Key ID: 1D7529BE14E2BBA9
  1. 15
      DESCRIPTION
  2. 5
      NAMESPACE
  3. 10
      R/RcppExports.R
  4. 13
      R/bonjour-package.R
  5. 12
      R/discover.R
  6. 13
      R/query.R
  7. 11
      README.Rmd
  8. 112
      README.md
  9. 15
      man/bnjr_discover.Rd
  10. 17
      man/bnjr_query.Rd
  11. 12
      man/bonjour.Rd
  12. 3
      src/Makevars
  13. 22
      src/RcppExports.cpp
  14. 266
      src/bonjour-main.cpp
  15. 17
      src/mdns.h

15
DESCRIPTION

@ -1,6 +1,6 @@
Package: bonjour
Type: Package
Title: bonjour title goes here otherwise CRAN checks fail
Title: Discover and Query Multicast DNS (mDNS)/zeroconf Services
Version: 0.1.0
Date: 2020-04-29
Authors@R: c(
@ -8,7 +8,15 @@ Authors@R: c(
comment = c(ORCID = "0000-0001-5670-2640"))
)
Maintainer: Bob Rudis <bob@rud.is>
Description: A good description goes here otherwise CRAN checks fail.
Description: Multicast DNS (mDNS) provides the ability to perform DNS-like
operations on the local link in the absence of any conventional
Unicast DNS server. Given a type of service
that a client is looking for, and a domain in which the client is
looking for that service, this mechanism allows clients to discover
a list of named instances of that desired service, using standard
DNS queries. This mechanism is referred to as DNS-based Service
Discovery, or DNS-SD. Tools are provided to perform service discovery
and query for specific services over multicast DNS (mDNS).
URL: https://git.rud.is/hrbrmstr/bonjour
BugReports: https://gitlab.com/hrbrmstr/bonjour/issues
Encoding: UTF-8
@ -19,7 +27,8 @@ Suggests:
Depends:
R (>= 3.2.0)
Imports:
Rcpp
Rcpp,
ndjson
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.0
LinkingTo:

5
NAMESPACE

@ -1,6 +1,7 @@
# Generated by roxygen2: do not edit by hand
export(int_bnjr_discover)
export(int_bnjr_query_send)
export(bnjr_discover)
export(bnjr_query)
importFrom(Rcpp,sourceCpp)
importFrom(ndjson,flatten)
useDynLib(bonjour, .registration = TRUE)

10
R/RcppExports.R

@ -1,13 +1,11 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#' @export
int_bnjr_discover <- function() {
.Call(`_bonjour_int_bnjr_discover`)
int_bnjr_discover <- function(scan_time = 10L) {
.Call(`_bonjour_int_bnjr_discover`, scan_time)
}
#' @export
int_bnjr_query_send <- function(svc) {
.Call(`_bonjour_int_bnjr_query_send`, svc)
int_bnjr_query <- function(q, scan_time = 5L) {
.Call(`_bonjour_int_bnjr_query`, q, scan_time)
}

13
R/bonjour-package.R

@ -1,9 +1,20 @@
#' ...
#' Discover and Query Multicast DNS (mDNS)/zeroconf Services
#'
#' #' Multicast DNS (mDNS) provides the ability to perform DNS-like
#' operations on the local link in the absence of any conventional
#' Unicast DNS server. Given a type of service
#' that a client is looking for, and a domain in which the client is
#' looking for that service, this mechanism allows clients to discover
#' a list of named instances of that desired service, using standard
#' DNS queries. This mechanism is referred to as DNS-based Service
#' Discovery, or DNS-SD. Tools are provided to perform service discovery
#' and query for specific services over multicast DNS (mDNS).
#'
#' @md
#' @name bonjour
#' @keywords internal
#' @author Bob Rudis (bob@@rud.is)
#' @importFrom ndjson flatten
## usethis namespace: start
#' @importFrom Rcpp sourceCpp
#' @useDynLib bonjour, .registration = TRUE

12
R/discover.R

@ -0,0 +1,12 @@
#' Browse available services
#'
#' @param scan_time how long to scan for services; default is 10 and
#' should not really be that much lower in most networks.
#' @export
bnjr_discover <- function(scan_time = 10L) {
res <- int_bnjr_discover(scan_time)
res <- unlist(strsplit(res, "\n"))
ndjson::flatten(res, "tbl")
}

13
R/query.R

@ -0,0 +1,13 @@
#' Look for a particular service
#'
#' @param query service to look for
#' @param scan_time how long to scan for services; default is 10 and
#' should not really be that much lower in most networks.
#' @export
bnjr_query <- function(query, scan_time = 10L) {
res <- int_bnjr_query(query, scan_time)
res <- unlist(strsplit(res, "\n"))
ndjson::flatten(res, "tbl")
}

11
README.Rmd

@ -33,12 +33,23 @@ hrbrpkghelpr::install_block()
```{r lib-ex}
library(bonjour)
library(tidyverse)
# current version
packageVersion("bonjour")
```
```{r ex-01, cache = TRUE}
bnjr_discover()
```
```{r ex-02, cache = TRUE}
bnjr_query("_ssh._tcp.local.") %>%
filter(type == "AAAA") %>%
select(addr)
```
## bonjour Metrics
```{r cloc, echo=FALSE}

112
README.md

@ -0,0 +1,112 @@
[![Project Status: Active – The project has reached a stable, usable
state and is being actively
developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[![Signed
by](https://img.shields.io/badge/Keybase-Verified-brightgreen.svg)](https://keybase.io/hrbrmstr)
![Signed commit
%](https://img.shields.io/badge/Signed_Commits-100%25-lightgrey.svg)
[![Linux build
Status](https://travis-ci.org/hrbrmstr/bonjour.svg?branch=master)](https://travis-ci.org/hrbrmstr/bonjour)
![Minimal R
Version](https://img.shields.io/badge/R%3E%3D-3.2.0-blue.svg)
![License](https://img.shields.io/badge/License-MIT-blue.svg)
# bonjour
Discover and Query Multicast DNS (mDNS)/zeroconf Services
## Description
Multicast DNS (mDNS) provides the ability to perform DNS-like operations
on the local link in the absence of any conventional Unicast DNS server.
Given a type of service that a client is looking for, and a domain in
which the client is looking for that service, this mechanism allows
clients to discover a list of named instances of that desired service,
using standard DNS queries. This mechanism is referred to as DNS-based
Service Discovery, or DNS-SD. Tools are provided to perform service
discovery and query for specific services over multicast DNS (mDNS).
## What’s Inside The Tin
The following functions are implemented:
- `bnjr_discover`: Browse available services
- `bnjr_query`: Look for a particular service
## Installation
``` r
remotes::install_git("https://git.rud.is/hrbrmstr/bonjour.git")
# or
remotes::install_git("https://git.sr.ht/~hrbrmstr/bonjour")
# or
remotes::install_gitlab("hrbrmstr/bonjour")
# or
remotes::install_bitbucket("hrbrmstr/bonjour")
```
NOTE: To use the ‘remotes’ install options you will need to have the
[{remotes} package](https://github.com/r-lib/remotes) installed.
## Usage
``` r
library(bonjour)
library(tidyverse)
# current version
packageVersion("bonjour")
## [1] '0.1.0'
```
``` r
bnjr_discover()
## # A tibble: 49 x 7
## entry_type from length name rclass ttl type
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <chr>
## 1 answer 10.1.10.59:5353 12 _ssh._tcp.local. 1 10 PTR
## 2 answer 10.1.10.59:5353 12 _sftp-ssh._tcp.local. 1 10 PTR
## 3 answer 10.1.10.59:5353 8 _eppc._tcp.local. 1 10 PTR
## 4 answer 10.1.10.59:5353 7 _rfb._tcp.local. 1 10 PTR
## 5 answer 10.1.10.59:5353 7 _smb._tcp.local. 1 10 PTR
## 6 answer 10.1.10.59:5353 17 _net-assistant._udp.local. 1 10 PTR
## 7 answer 10.1.10.59:5353 18 _companion-link._tcp.local. 1 10 PTR
## 8 answer 10.1.10.192:5353 12 _smb._tcp.local. 1 10 PTR
## 9 answer 10.1.10.20:5353 14 _adisk._tcp.local. 1 10 PTR
## 10 answer 10.1.10.20:5353 7 _ssh._tcp.local. 1 10 PTR
## # … with 39 more rows
```
``` r
bnjr_query("_ssh._tcp.local.") %>%
filter(type == "AAAA") %>%
select(addr)
## # A tibble: 9 x 1
## addr
## <chr>
## 1 fe80::1410:647:b4c1:df43
## 2 2603:3005:146a:8000:1459:ebc3:42dc:5ae2
## 3 fe80::1864:a1e2:98b:44d0
## 4 2603:3005:146a:8000:189b:85a2:64f5:598f
## 5 fe80::18f8:a74b:6a0d:9175
## 6 2603:3005:146a:8000:c98:42f7:9943:4b73
## 7 2603:3005:146a:8000:6972:7ff9:9594:5467
## 8 fe80::1041:d138:41f8:efd5
## 9 2603:3005:146a:8000:c95:dcb9:cc3a:d030
```
## bonjour Metrics
| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) |
| :----------- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: |
| C/C++ Header | 1 | 0.11 | 936 | 0.76 | 154 | 0.56 | 87 | 0.48 |
| C++ | 2 | 0.22 | 255 | 0.21 | 97 | 0.35 | 28 | 0.15 |
| R | 5 | 0.56 | 20 | 0.02 | 9 | 0.03 | 34 | 0.19 |
| Rmd | 1 | 0.11 | 13 | 0.01 | 17 | 0.06 | 32 | 0.18 |
## Code of Conduct
Please note that this project is released with a Contributor Code of
Conduct. By participating in this project you agree to abide by its
terms.

15
man/bnjr_discover.Rd

@ -0,0 +1,15 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/discover.R
\name{bnjr_discover}
\alias{bnjr_discover}
\title{Browse available services}
\usage{
bnjr_discover(scan_time = 10L)
}
\arguments{
\item{scan_time}{how long to scan for services; default is 10 and
should not really be that much lower in most networks.}
}
\description{
Browse available services
}

17
man/bnjr_query.Rd

@ -0,0 +1,17 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/query.R
\name{bnjr_query}
\alias{bnjr_query}
\title{Look for a particular service}
\usage{
bnjr_query(query, scan_time = 10L)
}
\arguments{
\item{query}{service to look for}
\item{scan_time}{how long to scan for services; default is 10 and
should not really be that much lower in most networks.}
}
\description{
Look for a particular service
}

12
man/bonjour.Rd

@ -4,9 +4,17 @@
\name{bonjour}
\alias{bonjour}
\alias{bonjour-package}
\title{...}
\title{Discover and Query Multicast DNS (mDNS)/zeroconf Services}
\description{
A good description goes here otherwise CRAN checks fail.
#' Multicast DNS (mDNS) provides the ability to perform DNS-like
operations on the local link in the absence of any conventional
Unicast DNS server. Given a type of service
that a client is looking for, and a domain in which the client is
looking for that service, this mechanism allows clients to discover
a list of named instances of that desired service, using standard
DNS queries. This mechanism is referred to as DNS-based Service
Discovery, or DNS-SD. Tools are provided to perform service discovery
and query for specific services over multicast DNS (mDNS).
}
\seealso{
Useful links:

3
src/Makevars

@ -0,0 +1,3 @@
CXX_STD = CXX11
PKG_CXXFLAGS =
PKG_LIBS =

22
src/RcppExports.cpp

@ -6,30 +6,32 @@
using namespace Rcpp;
// int_bnjr_discover
List int_bnjr_discover();
RcppExport SEXP _bonjour_int_bnjr_discover() {
std::string int_bnjr_discover(int scan_time);
RcppExport SEXP _bonjour_int_bnjr_discover(SEXP scan_timeSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
rcpp_result_gen = Rcpp::wrap(int_bnjr_discover());
Rcpp::traits::input_parameter< int >::type scan_time(scan_timeSEXP);
rcpp_result_gen = Rcpp::wrap(int_bnjr_discover(scan_time));
return rcpp_result_gen;
END_RCPP
}
// int_bnjr_query_send
List int_bnjr_query_send(std::string svc);
RcppExport SEXP _bonjour_int_bnjr_query_send(SEXP svcSEXP) {
// int_bnjr_query
std::string int_bnjr_query(std::string q, int scan_time);
RcppExport SEXP _bonjour_int_bnjr_query(SEXP qSEXP, SEXP scan_timeSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< std::string >::type svc(svcSEXP);
rcpp_result_gen = Rcpp::wrap(int_bnjr_query_send(svc));
Rcpp::traits::input_parameter< std::string >::type q(qSEXP);
Rcpp::traits::input_parameter< int >::type scan_time(scan_timeSEXP);
rcpp_result_gen = Rcpp::wrap(int_bnjr_query(q, scan_time));
return rcpp_result_gen;
END_RCPP
}
static const R_CallMethodDef CallEntries[] = {
{"_bonjour_int_bnjr_discover", (DL_FUNC) &_bonjour_int_bnjr_discover, 0},
{"_bonjour_int_bnjr_query_send", (DL_FUNC) &_bonjour_int_bnjr_query_send, 1},
{"_bonjour_int_bnjr_discover", (DL_FUNC) &_bonjour_int_bnjr_discover, 1},
{"_bonjour_int_bnjr_query", (DL_FUNC) &_bonjour_int_bnjr_query, 2},
{NULL, NULL, 0}
};

266
src/bonjour-main.cpp

@ -1,10 +1,15 @@
#include <Rcpp.h>
#include <stdio.h>
#include <errno.h>
#include "mdns.h"
#include <cstdio>
#include <fstream>
#include <iostream>
using namespace Rcpp;
#include "mdns.h"
#include <stdio.h>
#include <errno.h>
#ifdef _WIN32
# include <iphlpapi.h>
# define sleep(x) Sleep(x * 1000)
@ -17,6 +22,14 @@ static char namebuffer[256];
static char sendbuffer[256];
static mdns_record_txt_t txtbuffer[128];
typedef struct {
const char* service;
const char* hostname;
uint32_t address_ipv4;
uint8_t* address_ipv6;
int port;
} service_record_t;
static mdns_string_t
ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr, size_t addrlen) {
char host[NI_MAXHOST] = {0};
@ -31,9 +44,8 @@ static mdns_string_t
else
len = snprintf(buffer, capacity, "%s", host);
}
if (len >= (int)capacity)
len = (int)capacity - 1;
mdns_string_t str = {buffer, len};
if (len >= (int)capacity) len = (int)capacity - 1;
mdns_string_t str = {buffer, (size_t)len};
return str;
}
@ -53,7 +65,7 @@ static mdns_string_t
}
if (len >= (int)capacity)
len = (int)capacity - 1;
mdns_string_t str = {buffer, len};
mdns_string_t str = {buffer, (size_t)len};
return str;
}
@ -70,53 +82,37 @@ static int query_callback(int sock, const struct sockaddr* from, size_t addrlen,
const void* data, size_t size, size_t offset, size_t length,
void* user_data) {
List *l = static_cast<List *>(user_data);
mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from, addrlen);
std::string fromstr = std::string(fromaddrstr.str, fromaddrstr.length);
const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" :
((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional");
std::string rec = "{ \"from\" : \"" + fromstr +
"\", \"entry_type\": \"" + entrytype + "\"";
if (rtype == MDNS_RECORDTYPE_PTR) {
mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length,
namebuffer, sizeof(namebuffer));
List ptr_l = List::create(
_["from"] = String(fromaddrstr.str),
_["name"] = String(namestr.str),
_["type"] = String("PTR"),
_["entry_type"] = String(entrytype),
_["rclass"] = rclass,
_["ttl"] = ttl,
_["length"] = length
);
rec = rec + ", \"type\": \"PTR\"";
rec = rec + ", \"name\": \"" + std::string(namestr.str, namestr.length) + "\"";
rec = rec + ", \"rclass\": " + std::to_string(rclass) + "";
rec = rec + ", \"ttl\": " + std::to_string(ttl) + "";
rec = rec + ", \"length\": " + std::to_string(length) + "";
l->push_back(ptr_l);
printf("%.*s : %s PTR %.*s rclass 0x%x ttl %u length %d\n",
MDNS_STRING_FORMAT(fromaddrstr), entrytype,
MDNS_STRING_FORMAT(namestr), rclass, ttl, (int)length);
// printf("%.*s : %s PTR %.*s rclass 0x%x ttl %u length %d\n",
// MDNS_STRING_FORMAT(fromaddrstr), entrytype,
// MDNS_STRING_FORMAT(namestr), rclass, ttl, (int)length);
} else if (rtype == MDNS_RECORDTYPE_SRV) {
mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length,
namebuffer, sizeof(namebuffer));
List srv_l = List::create(
_["from"] = String(fromaddrstr.str),
_["type"] = String("SRV"),
_["entry_type"] = String(entrytype),
_["priority"] = srv.priority,
_["weight"] = srv.weight,
_["port"] = srv.port
);
l->push_back(srv_l);
printf("%.*s : %s SRV %.*s priority %d weight %d port %d\n",
MDNS_STRING_FORMAT(fromaddrstr), entrytype,
MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
// printf("%.*s : %s SRV %.*s priority %d weight %d port %d\n",
// MDNS_STRING_FORMAT(fromaddrstr), entrytype,
// MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
} else if (rtype == MDNS_RECORDTYPE_A) {
@ -124,18 +120,12 @@ static int query_callback(int sock, const struct sockaddr* from, size_t addrlen,
mdns_record_parse_a(data, size, offset, length, &addr);
mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr, sizeof(addr));
List a_l = List::create(
_["from"] = String(fromaddrstr.str),
_["type"] = String("A"),
_["entry_type"] = String(entrytype),
_["addr"] = String(addrstr.str)
);
rec = rec + ", \"type\": \"A\"";
rec = rec + ", \"addr\": \"" + std::string(addrstr.str, addrstr.length) + "\"";
l->push_back(a_l);
printf("%.*s : %s A %.*s\n",
MDNS_STRING_FORMAT(fromaddrstr), entrytype,
MDNS_STRING_FORMAT(addrstr));
// printf("%.*s : %s A %.*s\n",
// MDNS_STRING_FORMAT(fromaddrstr), entrytype,
// MDNS_STRING_FORMAT(addrstr));
} else if (rtype == MDNS_RECORDTYPE_AAAA) {
@ -143,121 +133,105 @@ static int query_callback(int sock, const struct sockaddr* from, size_t addrlen,
mdns_record_parse_aaaa(data, size, offset, length, &addr);
mdns_string_t addrstr = ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr, sizeof(addr));
List aaaa_l = List::create(
_["from"] = String(fromaddrstr.str),
_["type"] = String("AAAA"),
_["entry_type"] = String(entrytype),
_["addr"] = String(addrstr.str)
);
l->push_back(aaaa_l);
rec = rec + ", \"type\": \"AAAA\"";
rec = rec + ", \"addr\": \"" + std::string(addrstr.str, addrstr.length) + "\"";
printf("%.*s : %s AAAA %.*s\n",
MDNS_STRING_FORMAT(fromaddrstr), entrytype,
MDNS_STRING_FORMAT(addrstr));
// printf("%.*s : %s AAAA %.*s\n",
// MDNS_STRING_FORMAT(fromaddrstr), entrytype,
// MDNS_STRING_FORMAT(addrstr));
} else if (rtype == MDNS_RECORDTYPE_TXT) {
size_t parsed = mdns_record_parse_txt(data, size, offset, length,
txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t));
for (size_t itxt = 0; itxt < parsed; ++itxt) {
if (txtbuffer[itxt].value.length) {
rec = rec + ", \"type\": \"TXT\"";
printf("%.*s : %s TXT %.*s = %.*s\n",
MDNS_STRING_FORMAT(fromaddrstr), entrytype,
MDNS_STRING_FORMAT(txtbuffer[itxt].key),
MDNS_STRING_FORMAT(txtbuffer[itxt].value));
if (txtbuffer[itxt].value.length) {
List txt_l = List::create(
_["from"] = String(fromaddrstr.str),
_["type"] = String("TXT"),
_["entry_type"] = String(entrytype),
_["key"] = String(txtbuffer[itxt].key.str),
_["value"] = String(txtbuffer[itxt].value.str)
);
rec = rec + ", \"key\": \"" + std::string(txtbuffer[itxt].key.str, txtbuffer[itxt].key.length) + "\"";
rec = rec + ", \"key\": \"" + std::string(txtbuffer[itxt].value.str, txtbuffer[itxt].value.length) + "\"";
l->push_back(txt_l);
// printf("%.*s : %s TXT %.*s = %.*s\n",
// MDNS_STRING_FORMAT(fromaddrstr), entrytype,
// MDNS_STRING_FORMAT(txtbuffer[itxt].key),
// MDNS_STRING_FORMAT(txtbuffer[itxt].value));
} else {
printf("%.*s : %s TXT %.*s\n",
MDNS_STRING_FORMAT(fromaddrstr), entrytype,
MDNS_STRING_FORMAT(txtbuffer[itxt].key));
List txt_l = List::create(
_["from"] = String(fromaddrstr.str),
_["type"] = String("TXT"),
_["entry_type"] = String(entrytype),
_["key"] = String(txtbuffer[itxt].key.str)
);
l->push_back(txt_l);
rec = rec + ", \"key\": \"" + std::string(txtbuffer[itxt].key.str, txtbuffer[itxt].key.length) + "\"";
// printf("%.*s : %s TXT %.*s\n",
// MDNS_STRING_FORMAT(fromaddrstr), entrytype,
// MDNS_STRING_FORMAT(txtbuffer[itxt].key));
}
}
} else {
List generic_l = List::create(
_["from"] = String(fromaddrstr.str),
_["entry_type"] = entrytype,
_["type"] = NA_STRING,
_["rclass"] = rclass,
_["ttl"] = ttl,
_["length"] = length
);
l->push_back(generic_l);
rec = rec + ", \"type\": \"" + std::to_string((long)entrytype) + "";
rec = rec + ", \"rclass\": " + std::to_string(rclass) + "";
rec = rec + ", \"rtype\": " + std::to_string(rtype) + "";
rec = rec + ", \"ttl\": " + std::to_string(ttl) + "";
rec = rec + ", \"length\": " + std::to_string(length) + "";
printf("%.*s : %s type %u rclass 0x%x ttl %u length %d\n",
MDNS_STRING_FORMAT(fromaddrstr), entrytype,
rtype, rclass, ttl, (int)length);
// printf("%.*s : %s type %u rclass 0x%x ttl %u length %d\n",
// MDNS_STRING_FORMAT(fromaddrstr), entrytype,
// rtype, rclass, ttl, (int)length);
}
rec = rec + " }\n";
std::fputs(rec.c_str(), (FILE *)user_data);
return 0;
}
//' @export
// [[Rcpp::export]]
List int_bnjr_discover() {
std::string int_bnjr_discover(int scan_time = 10L) {
#ifdef _WIN32
WORD versionWanted = MAKEWORD(1, 1);
WSADATA wsaData;
if (WSAStartup(versionWanted, &wsaData)) {
printf("Failed to initialize WinSock\n");
return -1;
return();
}
#endif
size_t capacity = 2048;
void* buffer = malloc(capacity);
void* user_data = 0;
size_t records;
List out = List::create();
std::string out;
std::FILE* tmpf = std::tmpfile();
int port = 0;
int sock = mdns_socket_open_ipv4(port);
if (sock < 0) return(out);
if (sock < 0) {
printf("Failed to open socket: %s\n", strerror(errno));
goto quit_int_bnjr_discover;
}
if (mdns_discovery_send(sock)) {
goto failnice;
printf("Failed to send DNS-DS discovery: %s\n", strerror(errno));
goto quit_int_bnjr_discover;
}
for (int i = 0; i < 10; ++i) {
for (int i = 0; i < scan_time; ++i) {
do {
records = mdns_discovery_recv(
sock, buffer, capacity,
query_callback, &out
sock, buffer, capacity, query_callback, tmpf
);
} while (records);
if (records) i = 0;
@ -266,29 +240,39 @@ List int_bnjr_discover() {
}
failnice:
std::rewind(tmpf);
char fbuf[1024];
while (std::fgets(fbuf, sizeof(fbuf), tmpf)) {
out = out + std::string(fbuf, strlen(fbuf));
}
std::fclose(tmpf);
quit_int_bnjr_discover:
free(buffer);
mdns_socket_close(sock);
if (sock >= 0) mdns_socket_close(sock);
#ifdef _WIN32
WSACleanup();
WSACleanup();
#endif
return(out);
return(out);
}
//' @export
// [[Rcpp::export]]
List int_bnjr_query_send(std::string svc) {
std::string int_bnjr_query(std::string q, int scan_time = 5L) {
#ifdef _WIN32
WORD versionWanted = MAKEWORD(1, 1);
WSADATA wsaData;
if (WSAStartup(versionWanted, &wsaData)) {
printf("Failed to initialize WinSock\n");
return -1;
return();
}
#endif
@ -297,36 +281,31 @@ List int_bnjr_query_send(std::string svc) {
void* user_data = 0;
size_t records;
List out = List::create();
std::FILE* tmpf = std::tmpfile();
std::string out;
int port = 0;
int sock = mdns_socket_open_ipv4(port);
if (sock < 0) return(out);
Rcout << "SERVICE: " << svc.c_str() << std::endl;
if (mdns_discovery_send(sock)) {
Rcout << "FAILED" << std::endl;
goto failnice2;
if (sock < 0) {
printf("Failed to open socket: %s\n", strerror(errno));
goto quit_int_bnjr_query_send;
}
if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR,
svc.c_str(), svc.length(),
buffer, capacity)) {
Rcout << "FAILED" << std::endl;
goto failnice2;
q.c_str(), q.length(),
buffer, capacity)) {
printf("Failed to send mDNS query: %s\n", strerror(errno));
goto quit_int_bnjr_query_send;
}
for (int i = 0; i < 10; ++i) {
for (int i = 0; i < scan_time; ++i) {
do {
records = mdns_query_recv(
sock, buffer, capacity, query_callback, &out, 1
sock, buffer, capacity, query_callback, tmpf, 1
);
Rcout << "RECORDS: " << records << std::endl;
} while (records);
if (records) i = 0;
@ -335,15 +314,26 @@ List int_bnjr_query_send(std::string svc) {
}
failnice2:
std::rewind(tmpf);
char fbuf[1024];
while (std::fgets(fbuf, sizeof(fbuf), tmpf)) {
out = out + std::string(fbuf, strlen(fbuf));
}
std::fclose(tmpf);
quit_int_bnjr_query_send:
free(buffer);
mdns_socket_close(sock);
if (sock >= 0) mdns_socket_close(sock);
#ifdef _WIN32
WSACleanup();
WSACleanup();
#endif
return(out);
return(out);
}
}

17
src/mdns.h

@ -12,6 +12,7 @@
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
@ -163,7 +164,7 @@ mdns_discovery_send(int sock);
// given callback for parsing.
static size_t
mdns_discovery_recv(int sock, void* buffer, size_t capacity,
mdns_record_callback_fn callback, void *user_data);
mdns_record_callback_fn callback, void* user_data);
//! Send a unicast DNS-SD answer with a single record to the given address.
static int
@ -731,10 +732,10 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity,
size_t offset = (size_t)((char*)data - (char*)buffer);
records += mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
MDNS_ENTRYTYPE_AUTHORITY, transaction_id, authority_rrs,
MDNS_ENTRYTYPE_AUTHORITY, transaction_id, authority_rrs,
callback, user_data);
records += mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
MDNS_ENTRYTYPE_ADDITIONAL, transaction_id, additional_rrs,
MDNS_ENTRYTYPE_ADDITIONAL, transaction_id, additional_rrs,
callback, user_data);
return records;
@ -917,13 +918,13 @@ mdns_query_recv(int sock, void* buffer, size_t capacity,
size_t records = 0;
size_t offset = MDNS_POINTER_DIFF(data, buffer);
records += mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
MDNS_ENTRYTYPE_ANSWER, transaction_id, answer_rrs,
MDNS_ENTRYTYPE_ANSWER, transaction_id, answer_rrs,
callback, user_data);
records += mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
MDNS_ENTRYTYPE_AUTHORITY, transaction_id, authority_rrs,
MDNS_ENTRYTYPE_AUTHORITY, transaction_id, authority_rrs,
callback, user_data);
records += mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
MDNS_ENTRYTYPE_ADDITIONAL, transaction_id, additional_rrs,
MDNS_ENTRYTYPE_ADDITIONAL, transaction_id, additional_rrs,
callback, user_data);
return records;
}
@ -964,7 +965,7 @@ mdns_query_answer(int sock, const void* address, size_t address_size, void* buff
*udata++ = htons(MDNS_CLASS_IN);
data = udata;
remain = capacity - MDNS_POINTER_DIFF(data, buffer);
//Fill in answers
//PTR record for service
data = mdns_string_make_ref(data, remain, service_offset);
@ -1164,7 +1165,7 @@ mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t len
++parsed;
}
return parsed;
return parsed;
}
#ifdef _WIN32

Loading…
Cancel
Save