diff --git a/.vscode/settings.json b/.vscode/settings.json index bb8d301e5..89a35aa52 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,6 +63,7 @@ "future": "cpp", "map": "cpp", "vector": "cpp", - "new": "cpp" + "new": "cpp", + "shared_mutex": "cpp" } } \ No newline at end of file diff --git a/contrib/wizard/lokinet-wizard.sh b/contrib/wizard/lokinet-wizard.sh deleted file mode 100755 index 80e798081..000000000 --- a/contrib/wizard/lokinet-wizard.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -root=$(dirname $(realpath -L $0)) - -if [ ! -d v ] ; then - echo "setting up wizard for the first time..." - python3 -m venv v && v/bin/pip install -r "$root/requirements.txt" &> /dev/null || echo "failed" -fi -v/bin/python "$root/lokinet.py" $@ \ No newline at end of file diff --git a/contrib/wizard/lokinet.py b/contrib/wizard/lokinet.py deleted file mode 100644 index 097029a1d..000000000 --- a/contrib/wizard/lokinet.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -from configparser import ConfigParser as Config -import netifaces -import ipaddress -import os - -def yield_public_addresses(): - for ifname in netifaces.interfaces(): - addrs = netifaces.ifaddresses(ifname) - if netifaces.AF_INET in addrs: - for addr in addrs[netifaces.AF_INET]: - ip = addr['addr'] - if not ipaddress.ip_address(ip).is_private: - yield ifname, ip - -def genconf(rootdir): - conf = Config() - conf['router'] = { - 'threads': '2', - 'net-threads': '1', - 'contact-file': os.path.join(rootdir, 'self.signed'), - 'transport-privkey': os.path.join(rootdir, 'transport.key'), - 'identity-privkey': os.path.join(rootdir, 'identity.key') - } - conf['netdb'] = { - 'dir': os.path.join(rootdir, 'netdb') - } - conf['bind'] = {} - found = False - for ifname, ip in yield_public_addresses(): - conf['bind'][ifname] = '1090' - print("using public address {}".format(ip)) - break - else: - print("This machine has no public network addresses") - return conf - -def main(args): - fname = 'daemon.ini' - if len(args) == 1: - fname = args[0] - conf = genconf(os.path.realpath('.')) - if conf: - with open(fname, 'w') as f: - conf.write(f) - print("wrote config to {}".format(fname)) -if __name__ == '__main__': - import sys - main(sys.argv[1:]) - diff --git a/contrib/wizard/requirements.txt b/contrib/wizard/requirements.txt deleted file mode 100644 index 67127e632..000000000 --- a/contrib/wizard/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -netifaces==0.10.7 \ No newline at end of file diff --git a/daemon.ini b/daemon.ini index b08452887..7a7de548f 100644 --- a/daemon.ini +++ b/daemon.ini @@ -1,12 +1,3 @@ -[router] -threads = 2 -net-threads = 1 -contact-file = /home/jeff/git/llarp/self.signed -transport-privkey = /home/jeff/git/llarp/transport.key -identity-privkey = /home/jeff/git/llarp/identity.key - [netdb] -dir = /home/jeff/git/llarp/netdb - +dir=netdb [bind] - diff --git a/daemon/dns.cpp b/daemon/dns.cpp index a95c93f7e..30306af54 100644 --- a/daemon/dns.cpp +++ b/daemon/dns.cpp @@ -3,12 +3,12 @@ #include /* fprintf, printf */ #include +#include #include #include "dnsd.hpp" #include "ev.hpp" +#include "llarp/net.hpp" #include "logger.hpp" -#include "net.hpp" -#include #include // for multithreaded version #include @@ -18,7 +18,7 @@ #endif struct llarp_main *ctx = 0; -bool done = false; +bool done = false; void handle_signal(int sig) @@ -38,14 +38,15 @@ hookChecker(std::string name) #define SERVER "8.8.8.8" #define PORT 53 -struct dns_relay_config { +struct dns_relay_config +{ std::string upstream_host; uint16_t upstream_port; }; void dns_iter_config(llarp_config_iterator *itr, const char *section, - const char *key, const char *val) + const char *key, const char *val) { dns_relay_config *config = (dns_relay_config *)itr->user; if(!strcmp(section, "dns")) @@ -53,12 +54,14 @@ dns_iter_config(llarp_config_iterator *itr, const char *section, if(!strcmp(key, "upstream-server")) { config->upstream_host = strdup(val); - llarp::LogDebug("Config file setting dns server to ", config->upstream_host); + llarp::LogDebug("Config file setting dns server to ", + config->upstream_host); } if(!strcmp(key, "upstream-port")) { config->upstream_port = atoi(val); - llarp::LogDebug("Config file setting dns server port to ", config->upstream_port); + llarp::LogDebug("Config file setting dns server port to ", + config->upstream_port); } } } @@ -68,15 +71,15 @@ main(int argc, char *argv[]) { int code = 1; llarp::LogInfo("Starting up server"); - + const char *conffname = handleBaseCmdLineArgs(argc, argv); dns_relay_config dnsr_config; dnsr_config.upstream_host = "8.8.8.8"; dnsr_config.upstream_port = 53; llarp_config *config_reader; llarp_new_config(&config_reader); - //ctx = llarp_main_init(conffname, multiThreaded); - + // ctx = llarp_main_init(conffname, multiThreaded); + if(llarp_load_config(config_reader, conffname)) { llarp_free_config(&config_reader); @@ -102,7 +105,9 @@ main(int argc, char *argv[]) // configure main netloop struct dnsd_context dnsd; - if(!llarp_dnsd_init(&dnsd, netloop, "*", 1053, (const char *)dnsr_config.upstream_host.c_str(), dnsr_config.upstream_port)) + if(!llarp_dnsd_init(&dnsd, netloop, "*", 1053, + (const char *)dnsr_config.upstream_host.c_str(), + dnsr_config.upstream_port)) { // llarp::LogError("failed to initialize dns subsystem"); llarp::LogError("Couldnt init dns daemon"); diff --git a/daemon/main.cpp b/daemon/main.cpp index ce50d6a7e..b424ab0ff 100644 --- a/daemon/main.cpp +++ b/daemon/main.cpp @@ -22,52 +22,9 @@ main(int argc, char *argv[]) multiThreaded = false; } const char *conffname = handleBaseCmdLineArgs(argc, argv); - /* - const char *conffname = "daemon.ini"; - int c; - while(1) - { - static struct option long_options[] = { - {"config", required_argument, 0, 'c'}, - {"logLevel", required_argument, 0, 'o'}, - {0, 0, 0, 0}}; - int option_index = 0; - c = getopt_long(argc, argv, "c:o:", long_options, &option_index); - if(c == -1) - break; - switch(c) - { - case 0: - break; - case 'c': - conffname = optarg; - break; - case 'o': - if(strncmp(optarg, "debug", MIN(strlen(optarg), (unsigned long)5)) == 0) - { - cSetLogLevel(eLogDebug); - } - else if(strncmp(optarg, "info", MIN(strlen(optarg), (unsigned long)4)) - == 0) - { - cSetLogLevel(eLogInfo); - } - else if(strncmp(optarg, "warn", MIN(strlen(optarg), (unsigned long)4)) - == 0) - { - cSetLogLevel(eLogWarn); - } - else if(strncmp(optarg, "error", MIN(strlen(optarg), (unsigned long)5)) - == 0) - { - cSetLogLevel(eLogError); - } - break; - default: - abort(); - } - } - */ + + if(!llarp_ensure_config(conffname)) + return 1; ctx = llarp_main_init(conffname, multiThreaded); int code = 1; diff --git a/daemon/rcutil.cpp b/daemon/rcutil.cpp index a22d65a70..faaf0530b 100644 --- a/daemon/rcutil.cpp +++ b/daemon/rcutil.cpp @@ -10,7 +10,7 @@ #include "buffer.hpp" #include "crypto.hpp" #include "fs.hpp" -#include "net.hpp" +#include "llarp/net.hpp" #include "router.hpp" struct llarp_main *ctx = 0; diff --git a/include/llarp/config.h b/include/llarp/config.h index 4186e3deb..703c657cc 100644 --- a/include/llarp/config.h +++ b/include/llarp/config.h @@ -38,4 +38,10 @@ void llarp_config_iter(struct llarp_config *conf, struct llarp_config_iterator *iter); +/// ensure configuration exists +/// populate with defaults if it does not exist +/// return if this succeeded +bool +llarp_ensure_config(const char *fname); + #endif diff --git a/include/llarp/iwp/server.hpp b/include/llarp/iwp/server.hpp index 46e7a2206..3682db11d 100644 --- a/include/llarp/iwp/server.hpp +++ b/include/llarp/iwp/server.hpp @@ -38,7 +38,7 @@ struct llarp_link const char *m_name; typedef std::unordered_map< llarp::Addr, llarp_link_session *, - llarp::addrhash > + llarp::Addr::Hash > LinkMap_t; LinkMap_t m_sessions; @@ -52,7 +52,7 @@ struct llarp_link std::atomic< bool > pumpingLogic; typedef std::unordered_map< llarp::Addr, llarp_link_session *, - llarp::addrhash > + llarp::Addr::Hash > PendingSessionMap_t; PendingSessionMap_t m_PendingSessions; mtx_t m_PendingSessions_Mutex; diff --git a/include/llarp/iwp/session.hpp b/include/llarp/iwp/session.hpp index 56245a878..a548d689f 100644 --- a/include/llarp/iwp/session.hpp +++ b/include/llarp/iwp/session.hpp @@ -6,10 +6,10 @@ #include "llarp/buffer.h" #include "llarp/crypto.hpp" #include "llarp/crypto_async.h" +#include "llarp/net.hpp" #include "llarp/router_contact.h" #include "llarp/time.h" #include "llarp/types.h" -#include "net.hpp" struct llarp_udp_io; struct llarp_async_iwp; diff --git a/llarp/net.hpp b/include/llarp/net.hpp similarity index 91% rename from llarp/net.hpp rename to include/llarp/net.hpp index fd8c6c95c..c763cead7 100644 --- a/llarp/net.hpp +++ b/include/llarp/net.hpp @@ -2,6 +2,7 @@ #define LLARP_NET_HPP #include #include +#include #include #include "mem.hpp" @@ -221,21 +222,32 @@ namespace llarp return (byte1 == 10 || (byte1 == 192 && byte2 == 168) || (byte1 == 172 && (byte2 & 0xf0) == 16)); } - }; - struct addrhash - { - std::size_t - operator()(Addr const& a) const noexcept + bool + isLoopback() { - if(a.af() == AF_INET) + return (ntohl(addr4()->s_addr)) >> 24 == 127; + } + + struct Hash + { + std::size_t + operator()(Addr const& a) const noexcept { - return a.port() + a.addr4()->s_addr; + if(a.af() == AF_INET) + { + return a.port() + a.addr4()->s_addr; + } + uint8_t empty[16] = {0}; + return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port(); } - uint8_t empty[16] = {0}; - return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port(); - } + }; }; + + /// get first network interface with public address + bool + GetBestNetIF(std::string& ifname, int af = AF_INET); + } // namespace llarp #endif diff --git a/llarp/config.cpp b/llarp/config.cpp index 277dc3615..0c5c3c03d 100644 --- a/llarp/config.cpp +++ b/llarp/config.cpp @@ -1,6 +1,9 @@ #include "config.hpp" #include +#include +#include "fs.hpp" #include "ini.hpp" +#include "logger.hpp" #include "mem.hpp" namespace llarp @@ -78,3 +81,35 @@ llarp_config_iter(struct llarp_config *conf, struct llarp_config_iterator *iter) iter->visit(iter, section.first.c_str(), item.first.c_str(), item.second.c_str()); } + +bool +llarp_ensure_config(const char *fname) +{ + std::error_code ec; + if(fs::exists(fname, ec)) + return true; + if(ec) + { + llarp::LogError(ec); + return false; + } + + std::ofstream f(fname); + if(!f.is_open()) + { + llarp::LogError("failed to open ", fname, " for writing"); + return false; + } + + f << "[netdb]" << std::endl; + f << "dir=netdb" << std::endl; + f << "[bind]" << std::endl; + + std::string ifname; + + if(llarp::GetBestNetIF(ifname, AF_INET)) + f << ifname << "=1090" << std::endl; + + llarp::LogInfo("Generated new config ", fname); + return true; +} \ No newline at end of file diff --git a/llarp/dnsc.cpp b/llarp/dnsc.cpp index b34d74d8a..bad453583 100644 --- a/llarp/dnsc.cpp +++ b/llarp/dnsc.cpp @@ -15,8 +15,8 @@ #include #include +#include "llarp/net.hpp" // for llarp::Addr #include "logger.hpp" -#include "net.hpp" // for llarp::Addr // FIXME: make configurable #define SERVER "8.8.8.8" @@ -115,7 +115,7 @@ raw_resolve_host(const char *url) dnsQuery.request[11] = 0x00; */ - //char *word; + // char *word; unsigned int i; llarp::LogDebug("Asking DNS server ", SERVER, " about ", url); // dnsQuery.reqType = 0x01; @@ -148,19 +148,19 @@ raw_resolve_host(const char *url) int rcode; socklen_t size; int ip = 0; - //int length; + // int length; unsigned char buffer[DNC_BUF_SIZE]; // unsigned char tempBuf[3]; - uint16_t QDCOUNT; // No. of items in Question Section - uint16_t ANCOUNT; // No. of items in Answer Section - uint16_t NSCOUNT; // No. of items in Authority Section - uint16_t ARCOUNT; // No. of items in Additional Section - //uint16_t QCLASS; // Specifies the class of the query - uint16_t ATYPE; // Specifies the meaning of the data in the RDATA field - //uint16_t ACLASS; // Specifies the class of the data in the RDATA field - //uint32_t TTL; // The number of seconds the results can be cached - //uint16_t RDLENGTH; // The length of the RDATA field - //uint16_t MSGID; + uint16_t QDCOUNT; // No. of items in Question Section + uint16_t ANCOUNT; // No. of items in Answer Section + uint16_t NSCOUNT; // No. of items in Authority Section + uint16_t ARCOUNT; // No. of items in Additional Section + // uint16_t QCLASS; // Specifies the class of the query + uint16_t ATYPE; // Specifies the meaning of the data in the RDATA field + // uint16_t ACLASS; // Specifies the class of the data in the RDATA field + // uint32_t TTL; // The number of seconds the results can be cached + // uint16_t RDLENGTH; // The length of the RDATA field + // uint16_t MSGID; int sockfd; @@ -307,8 +307,8 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp, // llarp::LogInfo("got a response, udp user is ", udp->user); unsigned char *castBuf = (unsigned char *)buf; - //auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf); - dns_msg_header *hdr = decode_hdr((const char *)castBuf); + // auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf); + dns_msg_header *hdr = decode_hdr((const char *)castBuf); llarp::LogDebug("Header got client responses for id: ", hdr->id); diff --git a/llarp/dnsd.cpp b/llarp/dnsd.cpp index 93e0c0fde..fa19b3e3b 100644 --- a/llarp/dnsd.cpp +++ b/llarp/dnsd.cpp @@ -2,8 +2,8 @@ #include #include #include "ev.hpp" +#include "llarp/net.hpp" #include "logger.hpp" -#include "net.hpp" dns_tracker dns_udp_tracker; diff --git a/llarp/ev_epoll.hpp b/llarp/ev_epoll.hpp index 1c623476f..0ddfea1a5 100644 --- a/llarp/ev_epoll.hpp +++ b/llarp/ev_epoll.hpp @@ -7,8 +7,8 @@ #include #include #include "ev.hpp" +#include "llarp/net.hpp" #include "logger.hpp" -#include "net.hpp" namespace llarp { diff --git a/llarp/iwp/server.cpp b/llarp/iwp/server.cpp index 1e00ce10c..7e5c10354 100644 --- a/llarp/iwp/server.cpp +++ b/llarp/iwp/server.cpp @@ -225,8 +225,8 @@ llarp_link::RemoveSession(llarp_link_session* s) UnmapAddr(s->addr); s->done(); m_sessions.erase(itr); - delete s; } + delete s; } uint8_t* diff --git a/llarp/iwp/session.cpp b/llarp/iwp/session.cpp index fb5d9531f..3cc4b933e 100644 --- a/llarp/iwp/session.cpp +++ b/llarp/iwp/session.cpp @@ -216,7 +216,6 @@ handle_generated_session_start(iwp_async_session_start *start) if(llarp_ev_udp_sendto(link->udp, link->addr, start->buf, start->sz) == -1) llarp::LogError("sendto failed"); link->EnterState(llarp_link_session::State::eSessionStartSent); - link->serv->remove_intro_from(link->addr); link->working = false; } @@ -247,8 +246,6 @@ handle_verify_introack(iwp_async_introack *introack) { // invalid signature llarp::LogError("introack verify failed from ", link->addr); - link->serv->remove_intro_from(link->addr); - link->serv->RemoveSession(link); return; } // cancel resend @@ -380,10 +377,8 @@ llarp_link_session::on_intro_ack(const void *buf, size_t sz) { // too big? llarp::LogError("introack too big"); - serv->RemoveSession(this); return; } - serv->put_intro_from(this); // copy buffer so we own it memcpy(workbuf, buf, sz); // set intro ack parameters diff --git a/llarp/net.cpp b/llarp/net.cpp index 285e182b4..56673e379 100644 --- a/llarp/net.cpp +++ b/llarp/net.cpp @@ -1,4 +1,4 @@ -#include "net.hpp" +#include "llarp/net.hpp" #include "str.hpp" #ifdef ANDROID #include "android/ifaddrs.h" @@ -63,21 +63,21 @@ llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr) if(llarp::StrEq(i->ifa_name, ifname) && i->ifa_addr->sa_family == af) { // can't do this here - //llarp::Addr a(*i->ifa_addr); - //if(!a.isPrivate()) + // llarp::Addr a(*i->ifa_addr); + // if(!a.isPrivate()) //{ - // llarp::LogInfo(__FILE__, "found ", ifname, " af: ", af); - memcpy(addr, i->ifa_addr, sl); - if(af == AF_INET6) - { - // set scope id - sockaddr_in6* ip6addr = (sockaddr_in6*)addr; - ip6addr->sin6_scope_id = if_nametoindex(ifname); - ip6addr->sin6_flowinfo = 0; - } - found = true; - break; + // llarp::LogInfo(__FILE__, "found ", ifname, " af: ", af); + memcpy(addr, i->ifa_addr, sl); + if(af == AF_INET6) + { + // set scope id + sockaddr_in6* ip6addr = (sockaddr_in6*)addr; + ip6addr->sin6_scope_id = if_nametoindex(ifname); + ip6addr->sin6_flowinfo = 0; } + found = true; + break; + } //} } i = i->ifa_next; @@ -86,3 +86,37 @@ llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr) freeifaddrs(ifa); return found; } + +namespace llarp +{ + bool + GetBestNetIF(std::string& ifname, int af) + { + ifaddrs* ifa = nullptr; + bool found = false; + + if(getifaddrs(&ifa) == -1) + return false; + ifaddrs* i = ifa; + while(i) + { + if(i->ifa_addr) + { + if(i->ifa_addr->sa_family == af) + { + llarp::Addr a(*i->ifa_addr); + if(!(a.isPrivate() || a.isLoopback())) + { + ifname = i->ifa_name; + found = true; + break; + } + } + } + i = i->ifa_next; + } + if(ifa) + freeifaddrs(ifa); + return found; + } +} // namespace llarp \ No newline at end of file diff --git a/llarp/router.cpp b/llarp/router.cpp index 57d6881cc..7c5b0f0b8 100644 --- a/llarp/router.cpp +++ b/llarp/router.cpp @@ -9,8 +9,8 @@ #include "buffer.hpp" #include "encode.hpp" +#include "llarp/net.hpp" #include "logger.hpp" -#include "net.hpp" #include "str.hpp" #include diff --git a/llarp/service.cpp b/llarp/service.cpp index e732ab9db..b6151a8af 100644 --- a/llarp/service.cpp +++ b/llarp/service.cpp @@ -1,5 +1,6 @@ #include #include "buffer.hpp" +#include "fs.hpp" #include "ini.hpp" #include "router.hpp" @@ -157,14 +158,32 @@ namespace llarp Identity::BEncode(llarp_buffer_t* buf) const { /// TODO: implement me - return false; + if(!bencode_start_dict(buf)) + return false; + if(!BEncodeWriteDictEntry("e", enckey, buf)) + return false; + if(!BEncodeWriteDictEntry("s", signkey, buf)) + return false; + if(!BEncodeWriteDictInt("v", version, buf)) + return false; + if(!BEncodeWriteDictEntry("x", vanity, buf)) + return false; + return bencode_end(buf); } bool Identity::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) { - /// TODO: implement me - return false; + bool read = false; + if(!BEncodeMaybeReadDictEntry("e", enckey, read, key, buf)) + return false; + if(!BEncodeMaybeReadDictEntry("s", signkey, read, key, buf)) + return false; + if(!BEncodeMaybeReadDictInt("v", version, read, key, buf)) + return false; + if(!BEncodeMaybeReadDictEntry("x", vanity, read, key, buf)) + return false; + return read; } void @@ -180,8 +199,42 @@ namespace llarp bool Identity::EnsureKeys(const std::string& fname, llarp_crypto* c) { - // TODO: implement me - return false; + byte_t tmp[256]; + auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); + std::error_code ec; + // check for file + if(!fs::exists(fname, ec)) + { + if(ec) + { + llarp::LogError(ec); + return false; + } + // regen and encode + RegenerateKeys(c); + if(!BEncode(&buf)) + return false; + // rewind + buf.sz = buf.cur - buf.base; + buf.cur = buf.base; + // write + std::ofstream f; + f.open(fname, std::ios::binary); + if(!f.is_open()) + return false; + f.write((char*)buf.cur, buf.sz); + } + // read file + std::ifstream inf(fname, std::ios::binary); + inf.seekg(0, std::ios::end); + size_t sz = inf.tellg(); + inf.seekg(0, std::ios::beg); + + if(sz > sizeof(tmp)) + return false; + // decode + inf.read((char*)buf.base, sz); + return BDecode(&buf); } bool @@ -221,7 +274,6 @@ namespace llarp bool Config::Load(const std::string& fname) { - // TODO: implement me ini::Parser parser(fname); for(const auto& sec : parser.top().ordered_sections) { diff --git a/llarp/threadpool.cpp b/llarp/threadpool.cpp index 3abba5210..556fce4a7 100644 --- a/llarp/threadpool.cpp +++ b/llarp/threadpool.cpp @@ -40,8 +40,8 @@ namespace llarp lock, [this] { return this->stop || !this->jobs.empty(); }); if(this->stop && this->jobs.empty()) return; - job = this->jobs.front(); - this->jobs.pop_front(); + job = this->jobs.top().job; + this->jobs.pop(); } // do work job->work(job->user); @@ -81,7 +81,7 @@ namespace llarp if(stop) return; - jobs.push_back(new llarp_thread_job(job.user, job.work)); + jobs.emplace(ids++, new llarp_thread_job(job.user, job.work)); } condition.notify_one(); } diff --git a/llarp/threadpool.hpp b/llarp/threadpool.hpp index c0f8e09b3..f637abb6b 100644 --- a/llarp/threadpool.hpp +++ b/llarp/threadpool.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -27,8 +27,24 @@ namespace llarp void Stop(); std::vector< std::thread > threads; - std::deque< llarp_thread_job* > jobs; + struct Job_t + { + uint32_t id; + llarp_thread_job* job; + Job_t(uint32_t jobid, llarp_thread_job* j) : id(jobid), job(j) + { + } + + bool + operator<(const Job_t& j) const + { + return id < j.id; + } + }; + + std::priority_queue< Job_t > jobs; + uint32_t ids = 0; mtx_t queue_mutex; std::condition_variable condition; std::condition_variable done; diff --git a/llarp/timer.cpp b/llarp/timer.cpp index b3072b39d..ce7cfcd7d 100644 --- a/llarp/timer.cpp +++ b/llarp/timer.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "logger.hpp" @@ -44,10 +45,10 @@ namespace llarp static_cast< timer* >(user)->exec(); } - void - send_job(llarp_threadpool* pool) + bool + operator<(const timer& other) const { - llarp_threadpool_queue_job(pool, {this, timer::call}); + return (started + timeout) < (other.started + other.timeout); } }; }; // namespace llarp @@ -176,14 +177,29 @@ llarp_timer_cancel_job(struct llarp_timer_context* t, uint32_t id) t->cancel(id); } +typedef std::priority_queue< llarp::timer* > timers_t; + +static void +call_timers(void* user) +{ + timers_t* t = static_cast< timers_t* >(user); + while(t->size()) + { + t->top()->exec(); + t->pop(); + } + delete t; +} + void llarp_timer_tick_all(struct llarp_timer_context* t, struct llarp_threadpool* pool) { if(!t->run()) return; - auto now = llarp_time_now_ms(); - auto itr = t->timers.begin(); + auto now = llarp_time_now_ms(); + auto itr = t->timers.begin(); + timers_t* calling = new timers_t(); while(itr != t->timers.end()) { if(now - itr->second->started >= itr->second->timeout @@ -193,7 +209,7 @@ llarp_timer_tick_all(struct llarp_timer_context* t, { // timer hit itr->second->called_at = now; - itr->second->send_job(pool); + calling->push(itr->second); ++itr; } else if(itr->second->done) @@ -209,6 +225,10 @@ llarp_timer_tick_all(struct llarp_timer_context* t, else // timer not hit yet ++itr; } + if(calling->size()) + llarp_threadpool_queue_job(pool, {calling, &call_timers}); + else + delete calling; } void