Merge branch 'main' into patch-1

This commit is contained in:
Chris Blom 2022-10-05 11:40:49 +02:00 committed by GitHub
commit b4c851b39e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 25621 additions and 92 deletions

42
.github/workflows/cmake.yml vendored Normal file
View File

@ -0,0 +1,42 @@
name: CMake
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install xmllint
run: sudo apt-get install libpcaudio-dev
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}

View File

@ -2,26 +2,27 @@ cmake_minimum_required(VERSION 3.1)
project(googerteller VERSION 1.0 project(googerteller VERSION 1.0
DESCRIPTION "Audible feedback on Google communications" DESCRIPTION "Audible feedback on Google communications"
LANGUAGES CXX) LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard to use") set(CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard to use")
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON) set(CMAKE_CXX_EXTENSIONS ON)
#add_library(support STATIC ext/powerblog/h2o-pp.cc add_custom_target(Work ALL DEPENDS configs.hh)
# ext/powerblog/ext/simplesocket/swrappers.cc
# ext/powerblog/ext/simplesocket/comboaddress.cc
# ext/powerblog/ext/simplesocket/sclasses.cc
# ext/fmt-7.1.3/src/format.cc)
add_executable(teller teller.cc ext/lpm.c)
#target_include_directories(support PUBLIC ext/powerblog/ext/simplesocket ext/powerblog/ext ext/fmt-7.1.3/include/)
#target_link_libraries(support PUBLIC -lh2o-evloop -lssl -lcrypto Threads::Threads)
add_executable(teller teller.cc )
target_link_libraries(teller -lpcaudio -lpthread) target_link_libraries(teller -lpcaudio -lpthread)
#enable_testing() add_executable(testrunner testrunner.cc ext/lpm.c )
#add_test(testname testrunner) target_link_libraries(testrunner -lpcaudio)
enable_testing()
add_test(testname testrunner)
add_custom_command(
OUTPUT configs.hh
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/make-built-in-config.sh ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS teller.conf trackers.conf
)

View File

@ -5,17 +5,42 @@ Audible feedback on just how much your browsing feeds into Google.
By bert@hubertnet.nl / https://berthub.eu/ By bert@hubertnet.nl / https://berthub.eu/
Makes a little bit of noise any time your computer sends a packet to a Makes a little bit of noise any time your computer sends a packet to a
Google service, which excludes Google Cloud users. tracker or a Google service, which excludes Google Cloud users.
Demo video [in this tweet](https://twitter.com/bert_hu_bert/status/1561466204602220544) Demo video [in this tweet](https://twitter.com/bert_hu_bert/status/1561466204602220544)
[Blog post with more videos](https://berthub.eu/articles/posts/tracker-beeper/)
## Installing on OSX:
If need be, install Homebrew via https://brew.sh/ as this will allow you to
compile new software. To do so, copy paste the instruction under 'Install
Homebrew' into the terminal app ([Apple
help](https://support.apple.com/guide/terminal/open-or-quit-terminal-apd5265185d-f365-44cb-8b09-71a064a42125/mac)). This might take quite a while.
It will also ask for your password.
Then run:
```
brew tap robertjakub/teller
brew install --HEAD googerteller
```
To then start the noise, enter:
```
sudo tcpdump -nql | teller
```
And it should work. For the last command, it may also again ask you to enter your
password.
## How to compile ## How to compile
This will currently only work on Unix derived systems (like Linux, OSX and
FreeBSD).
You need a C++ compiler like `gcc-c++` and CMake for compiling the binary. You need a C++ compiler like `gcc-c++` and CMake for compiling the binary.
You also need to install `libpcaudio` (`libpcaudio-dev` on Debian/Ubuntu, `pcaudiolib-devel` on Fedora/Red Hat, `pcaudiolib` on Arch/Manjaro). You also need to install `libpcaudio` (`libpcaudio-dev` on Debian/Ubuntu, `pcaudiolib-devel` on Fedora/Red Hat, `pcaudiolib` on Arch/Manjaro).
For OSX [this is a bit more work](https://github.com/espeak-ng/pcaudiolib#mac-os)
Then run: Then do:
``` ```
cmake . cmake .
@ -23,44 +48,30 @@ make
``` ```
## How to run ## How to run
Google is so large its IPv4 and IPv6 footprint can't be handled by tcpdump, Start as:
or at least not efficiently. Therefore we need to define an ip(6)tables
`ipset`. This will first exclude Google Cloud, and then include all the
other Google IP addresses.
Install iptables 'ipset', and run (as root) the `ipset-setup.sh` script, or
execute:
``` ```
ipset create google-services hash:net sudo tcpdump -nql | ./teller
for a in $(cat goog-cloud-prefixes.txt)
do
echo $a
ipset add google-services $a nomatch
done
for a in $(cat goog-prefixes.txt)
do
ipset add google-services $a
done
ipset create google-services6 hash:net family inet6
for a in $(cat goog-cloud-prefixes6.txt)
do
ipset add google-services6 $a nomatch
done
for a in $(cat goog-prefixes6.txt)
do
ipset add google-services6 $a
done
iptables -I OUTPUT -m set --match-set google-services dst -j NFLOG --nflog-group 20 --nflog-threshold 1
ip6tables -I OUTPUT -m set --match-set google-services6 dst -j NFLOG --nflog-group 20 --nflog-threshold 1
``` ```
Then start as: And cry.
```
sudo tcpdump -i nflog:20 -ln | ./teller ## Configuration
``` Tracker data is read from `tracker.conf` which you should only edit if
you've learned about more IP addresses for relevant trackers.
In `teller.conf` you can edit for each tracker where the noise should end up
(left or right channel), and what the frequency should be.
## Data source
The list of Google services IP addresses can be found on [this Google
support page](https://support.google.com/a/answer/10026322?hl=en).
Note that this splits out Google services and Google cloud user IP
addresses. However, it appears the Google services set includes the cloud IP
addresses, so you must check both sets before determining something is in
fact a Google service and not a Google customer.
# To run on a single process on Linux
Or, to track a single process, fe `firefox`, start it and run: Or, to track a single process, fe `firefox`, start it and run:
@ -72,11 +83,10 @@ sudo bpftrace netsendmsg.bt |
And cry. And cry.
## Data source ## Dependencies
The list of Google services IP addresses can be found on [this Google This software gratefully builds on:
support page](https://support.google.com/a/answer/10026322?hl=en).
Note that this splits out Google services and Google cloud user IP * [doctest](https://github.com/doctest/doctest) testing framework
addresses. However, it appears the Google services set includes the cloud IP * [lpm](https://github.com/rmind/liblpm) Longest Prefix Match library
addresses, so you must check both sets before determining something is in * [Portable C Audio Library 1.2](https://github.com/espeak-ng/pcaudiolib) - which you need to install yourself
fact a Google service and not a Google customer. * tcpdump of course

6580
ext/doctest.h Normal file

File diff suppressed because it is too large Load Diff

420
ext/lpm.c Normal file
View File

@ -0,0 +1,420 @@
/*
* Copyright (c) 2016 Mindaugas Rasiukevicius <rmind at noxt eu>
* All rights reserved.
*
* Use is subject to license terms, as specified in the LICENSE file.
*/
/*
* Longest Prefix Match (LPM) library supporting IPv4 and IPv6.
*
* Algorithm:
*
* Each prefix gets its own hash map and all added prefixes are saved
* in a bitmap. On a lookup, we perform a linear scan of hash maps,
* iterating through the added prefixes only. Usually, there are only
* a few unique prefixes used and such simple algorithm is very efficient.
* With many IPv6 prefixes, the linear scan might become a bottleneck.
*/
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <assert.h>
#include "lpm.h"
#define LPM_MAX_PREFIX (128)
#define LPM_MAX_WORDS (LPM_MAX_PREFIX >> 5)
#define LPM_TO_WORDS(x) ((x) >> 2)
#define LPM_HASH_STEP (8)
#define LPM_LEN_IDX(len) ((len) >> 4)
#ifdef DEBUG
#define ASSERT assert
#else
#define ASSERT(x)
#endif
typedef struct lpm_ent {
struct lpm_ent *next;
void * val;
unsigned len;
uint8_t key[];
} lpm_ent_t;
typedef struct {
unsigned hashsize;
unsigned nitems;
lpm_ent_t ** bucket;
} lpm_hmap_t;
struct lpm {
uint32_t bitmask[LPM_MAX_WORDS];
void * defvals[2];
lpm_hmap_t prefix[LPM_MAX_PREFIX + 1];
};
static const uint32_t zero_address[LPM_MAX_WORDS];
lpm_t *
lpm_create(void)
{
lpm_t *lpm;
if ((lpm = calloc(1, sizeof(lpm_t))) == NULL) {
return NULL;
}
return lpm;
}
void
lpm_clear(lpm_t *lpm, lpm_dtor_t dtor, void *arg)
{
for (unsigned n = 0; n <= LPM_MAX_PREFIX; n++) {
lpm_hmap_t *hmap = &lpm->prefix[n];
if (!hmap->hashsize) {
ASSERT(!hmap->bucket);
continue;
}
for (unsigned i = 0; i < hmap->hashsize; i++) {
lpm_ent_t *entry = hmap->bucket[i];
while (entry) {
lpm_ent_t *next = entry->next;
if (dtor) {
dtor(arg, entry->key,
entry->len, entry->val);
}
free(entry);
entry = next;
}
}
free(hmap->bucket);
hmap->bucket = NULL;
hmap->hashsize = 0;
hmap->nitems = 0;
}
if (dtor) {
dtor(arg, zero_address, 4, lpm->defvals[0]);
dtor(arg, zero_address, 16, lpm->defvals[1]);
}
memset(lpm->bitmask, 0, sizeof(lpm->bitmask));
memset(lpm->defvals, 0, sizeof(lpm->defvals));
}
void
lpm_destroy(lpm_t *lpm)
{
lpm_clear(lpm, NULL, NULL);
free(lpm);
}
/*
* fnv1a_hash: Fowler-Noll-Vo hash function (FNV-1a variant).
*/
static uint32_t
fnv1a_hash(const void *buf, size_t len)
{
uint32_t hash = 2166136261UL;
const uint8_t *p = buf;
while (len--) {
hash ^= *p++;
hash *= 16777619U;
}
return hash;
}
static bool
hashmap_rehash(lpm_hmap_t *hmap, unsigned size)
{
lpm_ent_t **bucket;
unsigned hashsize;
for (hashsize = 1; hashsize < size; hashsize <<= 1) {
continue;
}
if ((bucket = calloc(1, hashsize * sizeof(lpm_ent_t *))) == NULL) {
return false;
}
for (unsigned n = 0; n < hmap->hashsize; n++) {
lpm_ent_t *list = hmap->bucket[n];
while (list) {
lpm_ent_t *entry = list;
uint32_t hash = fnv1a_hash(entry->key, entry->len);
const unsigned i = hash & (hashsize - 1);
list = entry->next;
entry->next = bucket[i];
bucket[i] = entry;
}
}
hmap->hashsize = hashsize;
free(hmap->bucket); // may be NULL
hmap->bucket = bucket;
return true;
}
static lpm_ent_t *
hashmap_insert(lpm_hmap_t *hmap, const void *key, size_t len)
{
const unsigned target = hmap->nitems + LPM_HASH_STEP;
const size_t entlen = offsetof(lpm_ent_t, key[len]);
uint32_t hash, i;
lpm_ent_t *entry;
if (hmap->hashsize < target && !hashmap_rehash(hmap, target)) {
return NULL;
}
hash = fnv1a_hash(key, len);
i = hash & (hmap->hashsize - 1);
entry = hmap->bucket[i];
while (entry) {
if (entry->len == len && memcmp(entry->key, key, len) == 0) {
return entry;
}
entry = entry->next;
}
if ((entry = malloc(entlen)) != NULL) {
memcpy(entry->key, key, len);
entry->next = hmap->bucket[i];
entry->len = len;
hmap->bucket[i] = entry;
hmap->nitems++;
}
return entry;
}
static lpm_ent_t *
hashmap_lookup(lpm_hmap_t *hmap, const void *key, size_t len)
{
const uint32_t hash = fnv1a_hash(key, len);
const unsigned i = hash & (hmap->hashsize - 1);
lpm_ent_t *entry;
if (hmap->hashsize == 0) {
return NULL;
}
entry = hmap->bucket[i];
while (entry) {
if (entry->len == len && memcmp(entry->key, key, len) == 0) {
return entry;
}
entry = entry->next;
}
return NULL;
}
static int
hashmap_remove(lpm_hmap_t *hmap, const void *key, size_t len)
{
const uint32_t hash = fnv1a_hash(key, len);
const unsigned i = hash & (hmap->hashsize - 1);
lpm_ent_t *prev = NULL, *entry;
if (hmap->hashsize == 0) {
return -1;
}
entry = hmap->bucket[i];
while (entry) {
if (entry->len == len && memcmp(entry->key, key, len) == 0) {
if (prev) {
prev->next = entry->next;
} else {
hmap->bucket[i] = entry->next;
}
free(entry);
return 0;
}
prev = entry;
entry = entry->next;
}
return -1;
}
/*
* compute_prefix: given the address and prefix length, compute and
* return the address prefix.
*/
static inline void
compute_prefix(const unsigned nwords, const uint32_t *addr,
unsigned preflen, uint32_t *prefix)
{
uint32_t addr2[4];
if ((uintptr_t)addr & 3) {
/* Unaligned address: just copy for now. */
memcpy(addr2, addr, nwords * 4);
addr = addr2;
}
for (unsigned i = 0; i < nwords; i++) {
if (preflen == 0) {
prefix[i] = 0;
continue;
}
if (preflen < 32) {
uint32_t mask = htonl(0xffffffff << (32 - preflen));
prefix[i] = addr[i] & mask;
preflen = 0;
} else {
prefix[i] = addr[i];
preflen -= 32;
}
}
}
/*
* lpm_insert: insert the CIDR into the LPM table.
*
* => Returns zero on success and -1 on failure.
*/
int
lpm_insert(lpm_t *lpm, const void *addr,
size_t len, unsigned preflen, void *val)
{
const unsigned nwords = LPM_TO_WORDS(len);
uint32_t prefix[nwords];
lpm_ent_t *entry;
ASSERT(len == 4 || len == 16);
if (preflen == 0) {
/* 0-length prefix is a special case. */
lpm->defvals[LPM_LEN_IDX(len)] = val;
return 0;
}
compute_prefix(nwords, addr, preflen, prefix);
entry = hashmap_insert(&lpm->prefix[preflen], prefix, len);
if (entry) {
const unsigned n = --preflen >> 5;
lpm->bitmask[n] |= 0x80000000U >> (preflen & 31);
entry->val = val;
return 0;
}
return -1;
}
/*
* lpm_remove: remove the specified prefix.
*/
int
lpm_remove(lpm_t *lpm, const void *addr, size_t len, unsigned preflen)
{
const unsigned nwords = LPM_TO_WORDS(len);
uint32_t prefix[nwords];
ASSERT(len == 4 || len == 16);
if (preflen == 0) {
lpm->defvals[LPM_LEN_IDX(len)] = NULL;
return 0;
}
compute_prefix(nwords, addr, preflen, prefix);
return hashmap_remove(&lpm->prefix[preflen], prefix, len);
}
/*
* lpm_lookup: find the longest matching prefix given the IP address.
*
* => Returns the associated value on success or NULL on failure.
*/
void *
lpm_lookup(lpm_t *lpm, const void *addr, size_t len)
{
const unsigned nwords = LPM_TO_WORDS(len);
unsigned i, n = nwords;
uint32_t prefix[nwords];
while (n--) {
uint32_t bitmask = lpm->bitmask[n];
while ((i = ffs(bitmask)) != 0) {
const unsigned preflen = (32 * n) + (32 - --i);
lpm_hmap_t *hmap = &lpm->prefix[preflen];
lpm_ent_t *entry;
compute_prefix(nwords, addr, preflen, prefix);
entry = hashmap_lookup(hmap, prefix, len);
if (entry) {
return entry->val;
}
bitmask &= ~(1U << i);
}
}
return lpm->defvals[LPM_LEN_IDX(len)];
}
/*
* lpm_lookup_prefix: return the value associated with a prefix
*
* => Returns the associated value on success or NULL on failure.
*/
void *
lpm_lookup_prefix(lpm_t *lpm, const void *addr, size_t len, unsigned preflen)
{
const unsigned nwords = LPM_TO_WORDS(len);
uint32_t prefix[nwords];
lpm_ent_t *entry;
ASSERT(len == 4 || len == 16);
if (preflen == 0) {
return lpm->defvals[LPM_LEN_IDX(len)];
}
compute_prefix(nwords, addr, preflen, prefix);
entry = hashmap_lookup(&lpm->prefix[preflen], prefix, len);
if (entry) {
return entry->val;
}
return NULL;
}
/*
* lpm_strtobin: convert CIDR string to the binary IP address and mask.
*
* => The address will be in the network byte order.
* => Returns 0 on success or -1 on failure.
*/
int
lpm_strtobin(const char *cidr, void *addr, size_t *len, unsigned *preflen)
{
char *p, buf[INET6_ADDRSTRLEN];
strncpy(buf, cidr, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';
if ((p = strchr(buf, '/')) != NULL) {
const ptrdiff_t off = p - buf;
*preflen = atoi(&buf[off + 1]);
buf[off] = '\0';
} else {
*preflen = LPM_MAX_PREFIX;
}
if (inet_pton(AF_INET6, buf, addr) == 1) {
*len = 16;
return 0;
}
if (inet_pton(AF_INET, buf, addr) == 1) {
if (*preflen == LPM_MAX_PREFIX) {
*preflen = 32;
}
*len = 4;
return 0;
}
return -1;
}

28
ext/lpm.h Normal file
View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016 Mindaugas Rasiukevicius <rmind at noxt eu>
* All rights reserved.
*
* Use is subject to license terms, as specified in the LICENSE file.
*/
#ifndef _LPM_H_
#define _LPM_H_
__BEGIN_DECLS
typedef struct lpm lpm_t;
typedef void (*lpm_dtor_t)(void *, const void *, size_t, void *);
lpm_t * lpm_create(void);
void lpm_destroy(lpm_t *);
void lpm_clear(lpm_t *, lpm_dtor_t, void *);
int lpm_insert(lpm_t *, const void *, size_t, unsigned, void *);
int lpm_remove(lpm_t *, const void *, size_t, unsigned);
void * lpm_lookup(lpm_t *, const void *, size_t);
void * lpm_lookup_prefix(lpm_t *, const void *, size_t, unsigned);
int lpm_strtobin(const char *, void *, size_t *, unsigned *);
__END_DECLS
#endif

17169
ext/toml.hpp Normal file

File diff suppressed because it is too large Load Diff

38
lpmwrapper.hh Normal file
View File

@ -0,0 +1,38 @@
extern "C" {
#include "ext/lpm.h"
}
class LPMWrapper
{
public:
LPMWrapper()
{
d_lpm = lpm_create();
}
~LPMWrapper()
{
lpm_destroy(d_lpm);
}
void insert(const std::string& str, void* val=(void*)1)
{
char addr[16];
size_t len=sizeof(addr);
unsigned preflen=0;
lpm_strtobin(str.c_str(), addr, &len, &preflen);
if(lpm_insert(d_lpm, addr, len, preflen, val) < 0)
throw std::runtime_error("Error inserting prefix");
}
void* lookup(const char*str)
{
char addr[16];
size_t len=sizeof(addr);
unsigned preflen=0;
lpm_strtobin(str, addr, &len, &preflen);
return lpm_lookup(d_lpm, addr, len);
}
private:
lpm_t* d_lpm;
};

12
make-built-in-config.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
cd $1
(
echo \#pragma once
echo 'constexpr char tellertoml[]=R"('
cat teller.conf
echo ')";'
echo 'constexpr char trackerstoml[]=R"('
cat trackers.conf
echo ')";'
) > configs.hh

161
teller.cc
View File

@ -5,26 +5,37 @@
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <pcaudiolib/audio.h> #include <pcaudiolib/audio.h>
#include "ext/toml.hpp"
#include "lpmwrapper.hh"
#include "configs.hh"
using namespace std; using namespace std;
int main()
{
audio_object* ao;
struct TrackerConf
{
double freq{400};
double balance{0.5}; // 0 is left, 1 is right
std::atomic<int64_t> counter{0};
};
void playerThread(const TrackerConf* tcptr)
{
auto& counter = tcptr->counter;
audio_object* ao;
ao=create_audio_device_object(0, "teller", ""); ao=create_audio_device_object(0, "teller", "");
if(!ao) { if(!ao) {
cerr<<"Unable to open audio file "<<endl; cerr<<"Unable to open audio file "<<endl;
return 0; return;
} }
int res = audio_object_open(ao, AUDIO_OBJECT_FORMAT_S16LE, 44100, 1); int res = audio_object_open(ao, AUDIO_OBJECT_FORMAT_S16LE, 44100, 2);
if(res < 0) { if(res < 0) {
cerr<<"Error opening audio: "<<audio_object_strerror(ao, res)<<endl; cerr<<"Error opening audio: "<<audio_object_strerror(ao, res)<<endl;
return;
} }
std::atomic<int64_t> counter = 0;
auto player = [&]() {
vector<int16_t> data; vector<int16_t> data;
int ourcounter=0; int ourcounter=0;
data.reserve(44100); data.reserve(44100);
@ -32,8 +43,12 @@ int main()
data.clear(); data.clear();
if(ourcounter < counter) { if(ourcounter < counter) {
for(int n=0; n < 250; ++n) { for(int n=0; n < 250; ++n) {
int16_t val = 20000 * sin((n/44100.0) * 500 * 2 * M_PI); int16_t val = 20000 * sin((n/44100.0) * tcptr->freq * 2 * M_PI);
data.push_back(val); int16_t lval = tcptr->balance * val;
int16_t rval = (1.0-tcptr->balance) * val;
data.push_back(lval);
data.push_back(rval);
} }
ourcounter++; ourcounter++;
if(counter - ourcounter > 1000) if(counter - ourcounter > 1000)
@ -42,20 +57,138 @@ int main()
else { else {
for(int n=0; n < 150; ++n) { for(int n=0; n < 150; ++n) {
data.push_back(0); data.push_back(0);
data.push_back(0);
} }
} }
audio_object_write(ao, &data[0], data.size() * sizeof(decltype(data)::value_type)); audio_object_write(ao, &data[0], data.size() * sizeof(decltype(data)::value_type));
// audio_object_flush(ao); // audio_object_flush(ao);
} }
}; }
std::thread athread(player);
int main(int argc, char** argv)
{
toml::table conftbl, trackertbl;
try
{
trackertbl = toml::parse_file("trackers.conf");
conftbl = toml::parse_file("teller.conf");
}
catch (const toml::parse_error& err)
{
std::cerr << "Could not read configuration files, using built-in defaults" <<endl;
trackertbl = toml::parse(trackerstoml);
conftbl = toml::parse(tellertoml);
}
map<string, TrackerConf> trackerdb;
auto tellerarr = conftbl.as_table();
for(const auto& t : *tellerarr) {
auto& entry = trackerdb[(string)t.first];
entry.balance = conftbl[t.first]["balance"].value_or(0.5);
entry.freq = conftbl[t.first]["freq"].value_or(500);
cout <<"Want to play sound for tracker "<<t.first<<", balance= "<<entry.balance<<" frequency = "<<entry.freq<<endl;
}
LPMWrapper trackspos, tracksneg;
auto tarr = trackertbl.as_table();
for(const auto& t : *tarr) {
cout<<"Defining tracker "<<t.first<<endl;
if(trackerdb.count((string)t.first)==0) {
cout<<"Skipping tracker "<<t.first<<", user doesn't want it"<<endl;
continue;
}
auto trackerptr = &trackerdb[(string)t.first];
auto track = trackertbl[t.first]["positive"].as_array();
if(track) {
track->for_each([&trackspos, &trackerptr](auto&& el) {
if constexpr (toml::is_string<decltype(el)>) {
trackspos.insert(*el, (void*)trackerptr);
}
});
}
else {
cout<<"Not array?"<<endl;
}
track = trackertbl[t.first]["negative"].as_array();
if(track) {
track->for_each([&tracksneg, &trackerptr](auto&& el) {
if constexpr (toml::is_string<decltype(el)>) {
tracksneg.insert(*el, (void*)trackerptr);
}
});
}
else {
cout<<"Negative "<<t.first<<" not array?"<<endl;
}
}
for(const auto& t : trackerdb) {
std::thread athread(playerThread, &t.second);
athread.detach();
}
string line; string line;
while(getline(cin, line)) { while(getline(cin, line)) {
counter++;
/*
22:42:25.323984 IP 13.81.0.219.29601 > 10.0.0.3.32902: tcp 1186
22:42:25.323997 IP 10.0.0.3.32902 > 13.81.0.219.29601: tcp 0
22:42:25.327216 b0:95:75:c3:68:92 > ff:ff:ff:ff:ff:ff, RRCP-0x25 query
16:53:11.082416 IP6 2603:8000:ae00:d301:5636:9bff:fe27:6af6.59394 > 2001:41f0:782d:1::2.29603: tcp 0
*/
if(line.find(" IP6 ") != string::npos) {
auto pos = line.find('>');
if(pos == string::npos)
continue;
auto pos2 = line.find('.', pos);
if(pos2 == string::npos) continue;
line.resize(pos2);
string ip = line.substr(pos+2, pos2 - pos - 2);
if(tracksneg.lookup(&line.at(pos+2))) {
cout<<ip<<" negative match"<<endl;
}
else if(auto fptr = trackspos.lookup(&line.at(pos+2))) {
cout<<ip<<" match!"<<endl;
((TrackerConf*)fptr)->counter++;
}
}
else {
auto pos = line.find('>');
if(pos == string::npos)
continue;
auto pos2 = line.find('.', pos);
if(pos2 == string::npos) continue;
pos2 = line.find('.', pos2+1);
if(pos2 == string::npos) continue;
pos2 = line.find('.', pos2+1);
if(pos2 == string::npos) continue;
pos2 = line.find_first_of(".:", pos2+1);
if(pos2 == string::npos) continue;
line.resize(pos2);
string ip=line.substr(pos+2, pos2 - pos - 2);
// cout<<&line.at(pos+2)<<endl;
if(tracksneg.lookup(&line.at(pos+2))) {
cout<<ip<<" negative match"<<endl;
}
else if(auto fptr = trackspos.lookup(&line.at(pos+2))) {
cout<<ip<<" match!"<<endl;
((TrackerConf*)fptr)->counter++;
}
}
} }
counter = -1;
athread.join();
sleep(1); sleep(1);
} }

11
teller.conf Normal file
View File

@ -0,0 +1,11 @@
[google]
balance=0
[facebook]
balance=1
freq=1000
[unassorted]
balance=0.5
freq=1500

45
testrunner.cc Normal file
View File

@ -0,0 +1,45 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "ext/doctest.h"
#include "lpmwrapper.hh"
using namespace std;
TEST_CASE("basic test") {
LPMWrapper t;
void* ptr = (void*)1;
t.insert("127.0.0.1/32", ptr);
CHECK(t.lookup("127.0.0.1") == ptr);
CHECK(t.lookup("127.0.0.2") == 0);
}
TEST_CASE("IPv6 test") {
LPMWrapper t;
void* ptr = (void*)1;
t.insert("::1", ptr);
CHECK(t.lookup("::1") == ptr);
CHECK(t.lookup("::2") == 0);
}
TEST_CASE("Mixed test") {
LPMWrapper t;
void* ptr = (void*)1;
t.insert("::1", ptr);
ptr = (void*)2;
t.insert("192.168.0.0/16", ptr);
CHECK(t.lookup("::1") == (void*)1);
CHECK(t.lookup("192.168.1.1") == (void*)2);
CHECK(t.lookup("192.168.255.255") == (void*)2);
CHECK(t.lookup("10.0.0.1") == 0);
CHECK(t.lookup("172.16.2.3") == 0);
CHECK(t.lookup("1.0.0.0") == 0);
}

1040
trackers.conf Normal file

File diff suppressed because it is too large Load Diff