mirror of https://github.com/oxen-io/lokinet
initial threadpool isolation code and run make format
This commit is contained in:
parent
30edb26ed9
commit
62f41d3747
|
@ -166,7 +166,9 @@ main(int argc, char *argv[])
|
|||
#ifndef _WIN32
|
||||
if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
|
||||
#else
|
||||
if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) < 0)
|
||||
if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv,
|
||||
sizeof(tv))
|
||||
< 0)
|
||||
#endif
|
||||
{
|
||||
perror("Error");
|
||||
|
|
|
@ -177,7 +177,9 @@ namespace llarp
|
|||
return false;
|
||||
if(strbuf.sz != sz)
|
||||
{
|
||||
llarp::LogErrorTag("AlignedBuffer::BDecode", "bdecode buffer size missmatch ", strbuf.sz, "!=", sz);
|
||||
llarp::LogErrorTag("AlignedBuffer::BDecode",
|
||||
"bdecode buffer size missmatch ", strbuf.sz,
|
||||
"!=", sz);
|
||||
return false;
|
||||
}
|
||||
memcpy(b, strbuf.base, sz);
|
||||
|
|
|
@ -45,8 +45,9 @@ namespace llarp
|
|||
{
|
||||
if(!item.BDecode(buf))
|
||||
{
|
||||
llarp::LogWarnTag("llarp/BEncode.hpp", "failed to decode key ", k, " for entry in dict");
|
||||
|
||||
llarp::LogWarnTag("llarp/BEncode.hpp", "failed to decode key ", k,
|
||||
" for entry in dict");
|
||||
|
||||
return false;
|
||||
}
|
||||
read = true;
|
||||
|
@ -63,7 +64,8 @@ namespace llarp
|
|||
{
|
||||
if(!bencode_read_integer(buf, &i))
|
||||
{
|
||||
llarp::LogWarnTag("llarp/BEncode.hpp", "failed to decode key ", k, " for integer in dict");
|
||||
llarp::LogWarnTag("llarp/BEncode.hpp", "failed to decode key ", k,
|
||||
" for integer in dict");
|
||||
return false;
|
||||
}
|
||||
read = true;
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* ev.h
|
||||
*
|
||||
* event handler (cross platform high performance event system for IO)
|
||||
*/
|
||||
* ev.h
|
||||
*
|
||||
* event handler (cross platform high performance event system for IO)
|
||||
*/
|
||||
|
||||
// forward declare
|
||||
struct llarp_threadpool;
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
// because this shit is not defined for Windows NT reeeee
|
||||
#ifndef _MSC_VER
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
const char*
|
||||
inet_ntop(int af, const void* src, char* dst, size_t size);
|
||||
int
|
||||
inet_pton(int af, const char* src, void* dst);
|
||||
const char*
|
||||
inet_ntop(int af, const void* src, char* dst, size_t size);
|
||||
int
|
||||
inet_pton(int af, const char* src, void* dst);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,10 @@ llarp_init_threadpool(int workers, const char *name);
|
|||
struct llarp_threadpool *
|
||||
llarp_init_same_process_threadpool();
|
||||
|
||||
/// for network isolation
|
||||
struct llarp_threadpool *
|
||||
llarp_init_isolated_net_threadpool(const char *name);
|
||||
|
||||
void
|
||||
llarp_free_threadpool(struct llarp_threadpool **tp);
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff)
|
|||
struct dict_reader reader = {
|
||||
.buffer = nullptr, .user = ai, .on_key = &llarp_ai_decode_key};
|
||||
#else
|
||||
struct dict_reader reader = { nullptr, ai, &llarp_ai_decode_key };
|
||||
struct dict_reader reader = {nullptr, ai, &llarp_ai_decode_key};
|
||||
#endif
|
||||
return bencode_read_dict(buff, &reader);
|
||||
}
|
||||
|
@ -270,8 +270,7 @@ llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff)
|
|||
struct list_reader r = {
|
||||
.buffer = nullptr, .user = l, .on_item = &llarp_ai_list_bdecode_item};
|
||||
#else
|
||||
struct list_reader r = {
|
||||
nullptr, l, &llarp_ai_list_bdecode_item};
|
||||
struct list_reader r = {nullptr, l, &llarp_ai_list_bdecode_item};
|
||||
#endif
|
||||
return bencode_read_list(buff, &r);
|
||||
}
|
||||
|
|
|
@ -200,7 +200,6 @@ namespace llarp
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
llarp::LogInfo("running mainloop");
|
||||
return llarp_ev_loop_run(mainloop, logic);
|
||||
}
|
||||
|
@ -215,7 +214,7 @@ namespace llarp
|
|||
llarp::LogInfo("SIGINT");
|
||||
SigINT();
|
||||
}
|
||||
// TODO(despair): implement hot-reloading config on NT
|
||||
// TODO(despair): implement hot-reloading config on NT
|
||||
#ifndef _WIN32
|
||||
if(sig == SIGHUP)
|
||||
{
|
||||
|
@ -305,194 +304,194 @@ extern "C"
|
|||
struct llarp_main *
|
||||
llarp_main_init(const char *fname, bool multiProcess)
|
||||
{
|
||||
if(!fname)
|
||||
fname = "daemon.ini";
|
||||
char *var = getenv("LLARP_DEBUG");
|
||||
if(var && *var == '1')
|
||||
{
|
||||
cSetLogLevel(eLogDebug);
|
||||
}
|
||||
llarp_main *m = new llarp_main;
|
||||
m->ctx.reset(new llarp::Context());
|
||||
m->ctx->singleThreaded = !multiProcess;
|
||||
if(!m->ctx->LoadConfig(fname))
|
||||
{
|
||||
m->ctx->Close();
|
||||
delete m;
|
||||
return nullptr;
|
||||
}
|
||||
return m;
|
||||
if(!fname)
|
||||
fname = "daemon.ini";
|
||||
char *var = getenv("LLARP_DEBUG");
|
||||
if(var && *var == '1')
|
||||
{
|
||||
cSetLogLevel(eLogDebug);
|
||||
}
|
||||
llarp_main *m = new llarp_main;
|
||||
m->ctx.reset(new llarp::Context());
|
||||
m->ctx->singleThreaded = !multiProcess;
|
||||
if(!m->ctx->LoadConfig(fname))
|
||||
{
|
||||
m->ctx->Close();
|
||||
delete m;
|
||||
return nullptr;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_main_signal(struct llarp_main *ptr, int sig)
|
||||
{
|
||||
ptr->ctx->HandleSignal(sig);
|
||||
ptr->ctx->HandleSignal(sig);
|
||||
}
|
||||
|
||||
int
|
||||
llarp_main_setup(struct llarp_main *ptr)
|
||||
{
|
||||
return ptr->ctx->Setup();
|
||||
return ptr->ctx->Setup();
|
||||
}
|
||||
|
||||
int
|
||||
llarp_main_run(struct llarp_main *ptr)
|
||||
{
|
||||
return ptr->ctx->Run();
|
||||
return ptr->ctx->Run();
|
||||
}
|
||||
|
||||
void
|
||||
llarp_main_abort(struct llarp_main *ptr)
|
||||
{
|
||||
llarp_logic_stop_timer(ptr->ctx->router->logic);
|
||||
llarp_logic_stop_timer(ptr->ctx->router->logic);
|
||||
}
|
||||
|
||||
int
|
||||
llarp_main_loadDatabase(struct llarp_main *ptr)
|
||||
{
|
||||
return ptr->ctx->LoadDatabase();
|
||||
return ptr->ctx->LoadDatabase();
|
||||
}
|
||||
|
||||
int
|
||||
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i)
|
||||
{
|
||||
return ptr->ctx->IterateDatabase(i);
|
||||
return ptr->ctx->IterateDatabase(i);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc)
|
||||
{
|
||||
return ptr->ctx->PutDatabase(rc);
|
||||
return ptr->ctx->PutDatabase(rc);
|
||||
}
|
||||
|
||||
struct llarp_rc *
|
||||
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk)
|
||||
{
|
||||
return ptr->ctx->GetDatabase(pk);
|
||||
return ptr->ctx->GetDatabase(pk);
|
||||
}
|
||||
|
||||
struct llarp_rc *
|
||||
llarp_main_getLocalRC(struct llarp_main *ptr)
|
||||
{
|
||||
//
|
||||
/*
|
||||
llarp_config_iterator iter;
|
||||
iter.user = this;
|
||||
iter.visit = &iter_config;
|
||||
llarp_config_iter(ctx->config, &iter);
|
||||
*/
|
||||
llarp_rc *rc = new llarp_rc;
|
||||
llarp_rc_new(rc);
|
||||
llarp::LogInfo("Loading ", ptr->ctx->conatctFile);
|
||||
if(llarp_rc_read(ptr->ctx->conatctFile, rc))
|
||||
return rc;
|
||||
else
|
||||
return nullptr;
|
||||
//
|
||||
/*
|
||||
llarp_config_iterator iter;
|
||||
iter.user = this;
|
||||
iter.visit = &iter_config;
|
||||
llarp_config_iter(ctx->config, &iter);
|
||||
*/
|
||||
llarp_rc *rc = new llarp_rc;
|
||||
llarp_rc_new(rc);
|
||||
llarp::LogInfo("Loading ", ptr->ctx->conatctFile);
|
||||
if(llarp_rc_read(ptr->ctx->conatctFile, rc))
|
||||
return rc;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_main_checkOnline(void *u, uint64_t orig, uint64_t left)
|
||||
{
|
||||
// llarp::LogInfo("checkOnline - check ", left);
|
||||
if(left)
|
||||
return;
|
||||
struct check_online_request *request =
|
||||
static_cast< struct check_online_request * >(u);
|
||||
// llarp::LogDebug("checkOnline - running");
|
||||
// llarp::LogInfo("checkOnline - DHT nodes ",
|
||||
// request->ptr->ctx->router->dht->impl.nodes->nodes.size());
|
||||
request->online = false;
|
||||
request->nodes = request->ptr->ctx->router->dht->impl.nodes->nodes.size();
|
||||
if(request->ptr->ctx->router->dht->impl.nodes->nodes.size())
|
||||
{
|
||||
// llarp::LogInfo("checkOnline - Going to say we're online");
|
||||
request->online = true;
|
||||
}
|
||||
request->hook(request);
|
||||
// reschedue our self
|
||||
llarp_main_queryDHT(request);
|
||||
// llarp::LogInfo("checkOnline - check ", left);
|
||||
if(left)
|
||||
return;
|
||||
struct check_online_request *request =
|
||||
static_cast< struct check_online_request * >(u);
|
||||
// llarp::LogDebug("checkOnline - running");
|
||||
// llarp::LogInfo("checkOnline - DHT nodes ",
|
||||
// request->ptr->ctx->router->dht->impl.nodes->nodes.size());
|
||||
request->online = false;
|
||||
request->nodes = request->ptr->ctx->router->dht->impl.nodes->nodes.size();
|
||||
if(request->ptr->ctx->router->dht->impl.nodes->nodes.size())
|
||||
{
|
||||
// llarp::LogInfo("checkOnline - Going to say we're online");
|
||||
request->online = true;
|
||||
}
|
||||
request->hook(request);
|
||||
// reschedue our self
|
||||
llarp_main_queryDHT(request);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_main_queryDHT_online(struct check_online_request *request)
|
||||
{
|
||||
// Info("llarp_main_queryDHT_online: ", request->online ? "online" :
|
||||
// "offline");
|
||||
if(request->online && !request->first)
|
||||
{
|
||||
request->first = true;
|
||||
llarp::LogInfo("llarp_main_queryDHT_online - We're online");
|
||||
llarp::LogInfo("llarp_main_queryDHT_online - Querying DHT");
|
||||
llarp_dht_lookup_router(request->ptr->ctx->router->dht, request->job);
|
||||
}
|
||||
// Info("llarp_main_queryDHT_online: ", request->online ? "online" :
|
||||
// "offline");
|
||||
if(request->online && !request->first)
|
||||
{
|
||||
request->first = true;
|
||||
llarp::LogInfo("llarp_main_queryDHT_online - We're online");
|
||||
llarp::LogInfo("llarp_main_queryDHT_online - Querying DHT");
|
||||
llarp_dht_lookup_router(request->ptr->ctx->router->dht, request->job);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
llarp_main_queryDHT(struct check_online_request *request)
|
||||
{
|
||||
// llarp::LogInfo("llarp_main_queryDHT - setting up timer");
|
||||
request->hook = &llarp_main_queryDHT_online;
|
||||
llarp_logic_call_later(request->ptr->ctx->router->logic,
|
||||
{1000, request, &llarp_main_checkOnline});
|
||||
// llarp_dht_lookup_router(ptr->ctx->router->dht, job);
|
||||
// llarp::LogInfo("llarp_main_queryDHT - setting up timer");
|
||||
request->hook = &llarp_main_queryDHT_online;
|
||||
llarp_logic_call_later(request->ptr->ctx->router->logic,
|
||||
{1000, request, &llarp_main_checkOnline});
|
||||
// llarp_dht_lookup_router(ptr->ctx->router->dht, job);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_main_free(struct llarp_main *ptr)
|
||||
{
|
||||
delete ptr;
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
const char *
|
||||
handleBaseCmdLineArgs(int argc, char *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)
|
||||
const char *conffname = "daemon.ini";
|
||||
int c;
|
||||
while(1)
|
||||
{
|
||||
case 0:
|
||||
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;
|
||||
case 'c':
|
||||
conffname = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
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);
|
||||
}
|
||||
{
|
||||
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:
|
||||
break;
|
||||
== 0)
|
||||
{
|
||||
cSetLogLevel(eLogError);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return conffname;
|
||||
return conffname;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,8 +207,8 @@ raw_resolve_host(const char *url)
|
|||
ret = recvfrom(sockfd, (char *)buffer, DNC_BUF_SIZE, 0,
|
||||
(struct sockaddr *)&addr, &size);
|
||||
#else
|
||||
ret = recvfrom(sockfd, buffer, DNC_BUF_SIZE, 0,
|
||||
(struct sockaddr *)&addr, &size);
|
||||
ret = recvfrom(sockfd, buffer, DNC_BUF_SIZE, 0, (struct sockaddr *)&addr,
|
||||
&size);
|
||||
#endif
|
||||
if(ret < 0)
|
||||
{
|
||||
|
|
|
@ -175,7 +175,8 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from,
|
|||
|
||||
if(request->context->intercept)
|
||||
{
|
||||
sockaddr *intercept = request->context->intercept(request->question.name, request->context);
|
||||
sockaddr *intercept =
|
||||
request->context->intercept(request->question.name, request->context);
|
||||
// if(!forward_dns_request(m_qName))
|
||||
if(intercept != nullptr)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,8 @@ struct dnsd_question_request
|
|||
|
||||
// we could have passed in the source sockaddr in case you wanted to
|
||||
// handle the response yourself
|
||||
typedef sockaddr *(*intercept_query_hook)(std::string name, struct dnsd_context *context);
|
||||
typedef sockaddr *(*intercept_query_hook)(std::string name,
|
||||
struct dnsd_context *context);
|
||||
|
||||
struct dnsd_context
|
||||
{
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#ifdef __linux__
|
||||
#include "ev_epoll.hpp"
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || (__APPLE__ && __MACH__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
|
||||
|| (__APPLE__ && __MACH__)
|
||||
#include "ev_kqueue.hpp"
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__NT__)
|
||||
|
@ -18,7 +19,8 @@ llarp_ev_loop_alloc(struct llarp_ev_loop **ev)
|
|||
#ifdef __linux__
|
||||
*ev = new llarp_epoll_loop;
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || (__APPLE__ && __MACH__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
|
||||
|| (__APPLE__ && __MACH__)
|
||||
*ev = new llarp_kqueue_loop;
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__NT__)
|
||||
|
|
|
@ -144,7 +144,7 @@ struct llarp_win32_loop : public llarp_ev_loop
|
|||
int result = 0;
|
||||
int idx = 0;
|
||||
byte_t readbuf[2048];
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
if(ev_id && qdata && iolen)
|
||||
|
@ -199,15 +199,16 @@ struct llarp_win32_loop : public llarp_ev_loop
|
|||
{
|
||||
if(ev_id && qdata && iolen)
|
||||
{
|
||||
llarp::udp_listener* ev = reinterpret_cast< llarp::udp_listener* >(ev_id);
|
||||
if(ev && ev->fd)
|
||||
llarp::udp_listener* ev =
|
||||
reinterpret_cast< llarp::udp_listener* >(ev_id);
|
||||
if(ev && ev->fd)
|
||||
{
|
||||
if(ev->getData(readbuf, sizeof(readbuf), iolen) == -1)
|
||||
{
|
||||
if(ev->getData(readbuf, sizeof(readbuf), iolen) == -1)
|
||||
{
|
||||
llarp::LogInfo("close ev");
|
||||
close_ev(ev);
|
||||
}
|
||||
llarp::LogInfo("close ev");
|
||||
close_ev(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
++idx;
|
||||
} while(::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, 10));
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#endif
|
||||
|
||||
#include "llarp/iwp/frame_state.hpp"
|
||||
#include <algorithm>
|
||||
#include "buffer.hpp"
|
||||
#include "llarp/crypto.hpp"
|
||||
#include "llarp/endian.h"
|
||||
|
@ -11,7 +12,6 @@
|
|||
#include "llarp/logger.hpp"
|
||||
#include "mem.hpp"
|
||||
#include "router.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
llarp_router *
|
||||
frame_state::Router()
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include "logger.hpp"
|
||||
#include "router.hpp"
|
||||
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
LinkIntroMessage::~LinkIntroMessage()
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include "android/ifaddrs.h"
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#include <ifaddrs.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
|
@ -44,8 +44,8 @@ operator<(const in6_addr& a, const in6_addr& b)
|
|||
#ifdef _WIN32
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <strsafe.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
// current strategy: mingw 32-bit builds call an inlined version of the function
|
||||
// microsoft c++ and mingw 64-bit builds call the normal function
|
||||
|
@ -102,12 +102,12 @@ _llarp_nt_heap_free(void* mem)
|
|||
int
|
||||
llarp_nt_sockaddr_pton(const char* src, struct sockaddr* dst)
|
||||
{
|
||||
struct addrinfo hints = {0}, *result = nullptr;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
const int status = getaddrinfo(src, nullptr, &hints, &result);
|
||||
struct addrinfo hints = {0}, *result = nullptr;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
const int status = getaddrinfo(src, nullptr, &hints, &result);
|
||||
if(!status)
|
||||
{
|
||||
memcpy(dst, result->ai_addr, result->ai_addrlen);
|
||||
|
@ -197,7 +197,7 @@ _llarp_nt_getadaptersinfo(struct llarp_nt_ifaddrs_t** ifap)
|
|||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "GetAdaptersInfo() discovered %d interfaces.\n", n);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* contiguous block for adapter list */
|
||||
struct _llarp_nt_ifaddrs_t* ifa =
|
||||
|
@ -216,7 +216,9 @@ _llarp_nt_getadaptersinfo(struct llarp_nt_ifaddrs_t** ifap)
|
|||
|
||||
/* address */
|
||||
ift->_ifa.ifa_addr = (struct sockaddr*)&ift->_addr;
|
||||
assert(1 == llarp_nt_sockaddr_pton(pIPAddr->IpAddress.String,ift->_ifa.ifa_addr));
|
||||
assert(1
|
||||
== llarp_nt_sockaddr_pton(pIPAddr->IpAddress.String,
|
||||
ift->_ifa.ifa_addr));
|
||||
|
||||
/* name */
|
||||
#ifdef DEBUG
|
||||
|
@ -233,7 +235,9 @@ _llarp_nt_getadaptersinfo(struct llarp_nt_ifaddrs_t** ifap)
|
|||
|
||||
/* netmask */
|
||||
ift->_ifa.ifa_netmask = (sockaddr*)&ift->_netmask;
|
||||
assert(1 == llarp_nt_sockaddr_pton(pIPAddr->IpMask.String, ift->_ifa.ifa_netmask));
|
||||
assert(1
|
||||
== llarp_nt_sockaddr_pton(pIPAddr->IpMask.String,
|
||||
ift->_ifa.ifa_netmask));
|
||||
|
||||
/* next */
|
||||
if(k++ < (n - 1))
|
||||
|
@ -353,7 +357,7 @@ _llarp_nt_getadaptersaddresses(struct llarp_nt_ifaddrs_t** ifap)
|
|||
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
|
||||
{
|
||||
int unicastIndex = 0;
|
||||
for(IP_ADAPTER_UNICAST_ADDRESS *unicast = adapter->FirstUnicastAddress;
|
||||
for(IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress;
|
||||
unicast; unicast = unicast->Next, ++unicastIndex)
|
||||
{
|
||||
/* ensure IP adapter */
|
||||
|
@ -693,7 +697,8 @@ llarp_nt_getifaddrs(struct llarp_nt_ifaddrs_t** ifap)
|
|||
{
|
||||
assert(nullptr != ifap);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "llarp_nt_getifaddrs (ifap:%p error:%p)\n", (void*)ifap,(void*)errno);
|
||||
fprintf(stderr, "llarp_nt_getifaddrs (ifap:%p error:%p)\n", (void*)ifap,
|
||||
(void*)errno);
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
return _llarp_nt_getadaptersaddresses(ifap);
|
||||
|
|
|
@ -38,6 +38,10 @@ namespace llarp
|
|||
if(addr.FromString(v))
|
||||
m_PrefetchAddrs.insert(addr);
|
||||
}
|
||||
if(k == "isolate-net")
|
||||
{
|
||||
// TODO: implement me
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <cstring>
|
||||
|
||||
#include <llarp/time.h>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
|
||||
#include "logger.hpp"
|
||||
|
@ -13,6 +14,8 @@
|
|||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
extern "C" void
|
||||
|
@ -23,7 +26,8 @@ namespace llarp
|
|||
{
|
||||
namespace thread
|
||||
{
|
||||
Pool::Pool(size_t workers, const char *name)
|
||||
void
|
||||
Pool::Spawn(size_t workers, const char *name)
|
||||
{
|
||||
stop = false;
|
||||
while(workers--)
|
||||
|
@ -96,6 +100,49 @@ namespace llarp
|
|||
condition.notify_one();
|
||||
}
|
||||
|
||||
static int
|
||||
runIsolated(void *arg)
|
||||
{
|
||||
IsolatedPool *self = static_cast< IsolatedPool * >(arg);
|
||||
auto func = std::bind(&Pool::Spawn, self, self->m_IsolatedWorkers,
|
||||
self->m_IsolatedName);
|
||||
func();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
IsolatedPool::Spawn(int workers, const char *name)
|
||||
{
|
||||
if(m_isolated)
|
||||
return;
|
||||
#ifdef __linux__
|
||||
IsolatedPool *self = this;
|
||||
self->m_IsolatedName = name;
|
||||
self->m_IsolatedWorkers = workers;
|
||||
m_isolated = new std::thread([self] {
|
||||
pid_t isolated;
|
||||
isolated =
|
||||
clone(runIsolated, self->m_childstack + sizeof(self->m_childstack),
|
||||
CLONE_NEWNET | SIGCHLD, self);
|
||||
if(isolated == -1)
|
||||
{
|
||||
llarp::LogError("failed to run isolated threadpool, ",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
llarp::LogInfo("Spawned network isolated process");
|
||||
if(waitpid(isolated, nullptr, 0) == -1)
|
||||
{
|
||||
llarp::LogError("failed to wait for pid ", isolated, ", ",
|
||||
strerror(errno));
|
||||
}
|
||||
});
|
||||
#else
|
||||
llarp::LogError("isolated network not supported on your platform");
|
||||
Pool::Spawn(workers, name);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace thread
|
||||
} // namespace llarp
|
||||
|
||||
|
@ -106,9 +153,13 @@ struct llarp_threadpool
|
|||
std::mutex m_access;
|
||||
std::queue< llarp_thread_job * > jobs;
|
||||
|
||||
llarp_threadpool(int workers, const char *name)
|
||||
: impl(new llarp::thread::Pool(workers, name))
|
||||
llarp_threadpool(int workers, const char *name, bool isolate)
|
||||
{
|
||||
if(isolate)
|
||||
impl = new llarp::thread::IsolatedPool();
|
||||
else
|
||||
impl = new llarp::thread::Pool();
|
||||
impl->Spawn(workers, name);
|
||||
}
|
||||
|
||||
llarp_threadpool() : impl(nullptr)
|
||||
|
@ -120,7 +171,7 @@ struct llarp_threadpool *
|
|||
llarp_init_threadpool(int workers, const char *name)
|
||||
{
|
||||
if(workers > 0)
|
||||
return new llarp_threadpool(workers, name);
|
||||
return new llarp_threadpool(workers, name, false);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -131,6 +182,12 @@ llarp_init_same_process_threadpool()
|
|||
return new llarp_threadpool();
|
||||
}
|
||||
|
||||
struct llarp_threadpool *
|
||||
llarp_init_isolated_net_threadpool(const char *name)
|
||||
{
|
||||
return new llarp_threadpool(1, name, true);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_threadpool_join(struct llarp_threadpool *pool)
|
||||
{
|
||||
|
|
|
@ -17,11 +17,13 @@ namespace llarp
|
|||
typedef std::unique_lock< mtx_t > lock_t;
|
||||
struct Pool
|
||||
{
|
||||
Pool(size_t sz, const char* name);
|
||||
virtual void
|
||||
Spawn(size_t sz, const char* name);
|
||||
|
||||
void
|
||||
QueueJob(const llarp_thread_job& job);
|
||||
|
||||
void
|
||||
virtual void
|
||||
Join();
|
||||
|
||||
void
|
||||
|
@ -51,6 +53,17 @@ namespace llarp
|
|||
bool stop;
|
||||
};
|
||||
|
||||
struct IsolatedPool : public Pool
|
||||
{
|
||||
void
|
||||
Spawn(int workers, const char* name);
|
||||
|
||||
std::thread* m_isolated = nullptr;
|
||||
int m_IsolatedWorkers = 0;
|
||||
const char* m_IsolatedName = nullptr;
|
||||
char m_childstack[(1024 * 1024 * 8)];
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace llarp
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include <llarp/service/tun_endpoint.hpp>
|
|
@ -1,16 +1,16 @@
|
|||
#if defined(__MINGW32__) && !defined(_WIN64)
|
||||
/*
|
||||
* Contains routines missing from WS2_32.DLL until 2006, if yer using
|
||||
* Microsoft C/C++, then this code is irrelevant, as the official
|
||||
/*
|
||||
* Contains routines missing from WS2_32.DLL until 2006, if yer using
|
||||
* Microsoft C/C++, then this code is irrelevant, as the official
|
||||
* Platform SDK already links against these routines in the correct
|
||||
* libraries.
|
||||
*
|
||||
* -despair86 30/07/18
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <llarp/net.h>
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
#include "win32_intrnl.h"
|
||||
|
||||
const char *
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <tdi.h>
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#include <tdi.h>
|
||||
#include "win32_intrnl.h"
|
||||
|
||||
const PWCHAR TcpFileName = L"\\Device\\Tcp";
|
||||
|
@ -31,10 +31,10 @@ typedef NTSTATUS(FAR PASCAL *pNTClose)(HANDLE);
|
|||
#define FSCTL_TCP_BASE FILE_DEVICE_NETWORK
|
||||
|
||||
#define _TCP_CTL_CODE(Function, Method, Access) \
|
||||
CTL_CODE(FSCTL_TCP_BASE, Function, Method, Access)
|
||||
CTL_CODE(FSCTL_TCP_BASE, Function, Method, Access)
|
||||
|
||||
#define IOCTL_TCP_QUERY_INFORMATION_EX \
|
||||
_TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
_TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
typedef struct _InterfaceIndexTable
|
||||
{
|
||||
|
@ -51,10 +51,10 @@ tdiGetMibForIfEntity(HANDLE tcpFile, TDIEntityID *ent,
|
|||
NTSTATUS status = 0;
|
||||
DWORD returnSize;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n", (int)tcpFile,
|
||||
(int)ent->tei_instance);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n",
|
||||
(int)tcpFile, (int)ent->tei_instance);
|
||||
#endif
|
||||
|
||||
req.ID.toi_class = INFO_CLASS_PROTOCOL;
|
||||
req.ID.toi_type = INFO_TYPE_PROVIDER;
|
||||
|
@ -72,21 +72,21 @@ tdiGetMibForIfEntity(HANDLE tcpFile, TDIEntityID *ent,
|
|||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"TdiGetMibForIfEntity() => {\n"
|
||||
" if_index ....................... %lx\n"
|
||||
" if_type ........................ %lx\n"
|
||||
" if_mtu ......................... %ld\n"
|
||||
" if_speed ....................... %lx\n"
|
||||
" if_physaddrlen ................. %ld\n",
|
||||
entry->ent.if_index, entry->ent.if_type, entry->ent.if_mtu,
|
||||
entry->ent.if_speed, entry->ent.if_physaddrlen);
|
||||
"TdiGetMibForIfEntity() => {\n"
|
||||
" if_index ....................... %lx\n"
|
||||
" if_type ........................ %lx\n"
|
||||
" if_mtu ......................... %ld\n"
|
||||
" if_speed ....................... %lx\n"
|
||||
" if_physaddrlen ................. %ld\n",
|
||||
entry->ent.if_index, entry->ent.if_type, entry->ent.if_mtu,
|
||||
entry->ent.if_speed, entry->ent.if_physaddrlen);
|
||||
fprintf(stderr,
|
||||
" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n"
|
||||
" if_descr ....................... %s\n",
|
||||
entry->ent.if_physaddr[0] & 0xff, entry->ent.if_physaddr[1] & 0xff,
|
||||
entry->ent.if_physaddr[2] & 0xff, entry->ent.if_physaddr[3] & 0xff,
|
||||
entry->ent.if_physaddr[4] & 0xff, entry->ent.if_physaddr[5] & 0xff,
|
||||
entry->ent.if_descr);
|
||||
" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n"
|
||||
" if_descr ....................... %s\n",
|
||||
entry->ent.if_physaddr[0] & 0xff, entry->ent.if_physaddr[1] & 0xff,
|
||||
entry->ent.if_physaddr[2] & 0xff, entry->ent.if_physaddr[3] & 0xff,
|
||||
entry->ent.if_physaddr[4] & 0xff, entry->ent.if_physaddr[5] & 0xff,
|
||||
entry->ent.if_descr);
|
||||
fprintf(stderr, "} status %08lx\n", status);
|
||||
|
||||
return 0;
|
||||
|
@ -158,19 +158,12 @@ tdiGetSetOfThings(HANDLE tcpFile, DWORD toiClass, DWORD toiType, DWORD toiId,
|
|||
}
|
||||
|
||||
static NTSTATUS
|
||||
tdiGetEntityIDSet(HANDLE tcpFile, TDIEntityID **entitySet,
|
||||
PDWORD numEntities)
|
||||
tdiGetEntityIDSet(HANDLE tcpFile, TDIEntityID **entitySet, PDWORD numEntities)
|
||||
{
|
||||
NTSTATUS status = tdiGetSetOfThings(tcpFile,
|
||||
INFO_CLASS_GENERIC,
|
||||
INFO_TYPE_PROVIDER,
|
||||
ENTITY_LIST_ID,
|
||||
GENERIC_ENTITY,
|
||||
0,
|
||||
0,
|
||||
sizeof(TDIEntityID),
|
||||
(PVOID *)entitySet,
|
||||
numEntities);
|
||||
NTSTATUS status =
|
||||
tdiGetSetOfThings(tcpFile, INFO_CLASS_GENERIC, INFO_TYPE_PROVIDER,
|
||||
ENTITY_LIST_ID, GENERIC_ENTITY, 0, 0,
|
||||
sizeof(TDIEntityID), (PVOID *)entitySet, numEntities);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -180,13 +173,12 @@ tdiGetIpAddrsForIpEntity(HANDLE tcpFile, TDIEntityID *ent, IPAddrEntry **addrs,
|
|||
{
|
||||
NTSTATUS status;
|
||||
|
||||
fprintf(stderr,"TdiGetIpAddrsForIpEntity(tcpFile 0x%p, entityId 0x%lx)\n", tcpFile,
|
||||
ent->tei_instance);
|
||||
fprintf(stderr, "TdiGetIpAddrsForIpEntity(tcpFile 0x%p, entityId 0x%lx)\n",
|
||||
tcpFile, ent->tei_instance);
|
||||
|
||||
status = tdiGetSetOfThings(tcpFile, INFO_CLASS_PROTOCOL, INFO_TYPE_PROVIDER,
|
||||
0x102, CL_NL_ENTITY,
|
||||
ent->tei_instance, 0, sizeof(IPAddrEntry),
|
||||
(PVOID *)addrs, numAddrs);
|
||||
0x102, CL_NL_ENTITY, ent->tei_instance, 0,
|
||||
sizeof(IPAddrEntry), (PVOID *)addrs, numAddrs);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -209,14 +201,15 @@ openTcpFile(PHANDLE tcpFile, ACCESS_MASK DesiredAccess)
|
|||
HANDLE ntdll;
|
||||
|
||||
ntdll = GetModuleHandle("ntdll.dll");
|
||||
_RtlInitUnicodeString = (pRtlInitUString)GetProcAddress(ntdll, "RtlInitUnicodeString");
|
||||
_RtlInitUnicodeString =
|
||||
(pRtlInitUString)GetProcAddress(ntdll, "RtlInitUnicodeString");
|
||||
_NTOpenFile = (pNTOpenFile)GetProcAddress(ntdll, "NtOpenFile");
|
||||
_RtlInitUnicodeString(&fileName, TcpFileName);
|
||||
InitializeObjectAttributes(&objectAttributes, &fileName, OBJ_CASE_INSENSITIVE,
|
||||
NULL, NULL);
|
||||
status = _NTOpenFile(tcpFile, DesiredAccess | SYNCHRONIZE, &objectAttributes,
|
||||
&ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT);
|
||||
&ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT);
|
||||
/* String does not need to be freed: it points to the constant
|
||||
* string we provided */
|
||||
if(!NT_SUCCESS(status))
|
||||
|
@ -228,7 +221,7 @@ closeTcpFile(HANDLE h)
|
|||
{
|
||||
pNTClose _NTClose;
|
||||
HANDLE ntdll = GetModuleHandle("ntdll.dll");
|
||||
_NTClose = (pNTClose)GetProcAddress(ntdll, "NtClose");
|
||||
_NTClose = (pNTClose)GetProcAddress(ntdll, "NtClose");
|
||||
assert(h != INVALID_HANDLE_VALUE);
|
||||
_NTClose(h);
|
||||
}
|
||||
|
@ -277,8 +270,8 @@ getNthIpEntity(HANDLE tcpFile, DWORD index, TDIEntityID *ent)
|
|||
|
||||
if(numRoutes == index && i < numEntities)
|
||||
{
|
||||
fprintf(stderr,"Index %lu is entity #%d - %04lx:%08lx\n", index, i,
|
||||
entitySet[i].tei_entity, entitySet[i].tei_instance);
|
||||
fprintf(stderr, "Index %lu is entity #%d - %04lx:%08lx\n", index, i,
|
||||
entitySet[i].tei_entity, entitySet[i].tei_instance);
|
||||
memcpy(ent, &entitySet[i], sizeof(*ent));
|
||||
tdiFreeThingSet(entitySet);
|
||||
return 0;
|
||||
|
@ -307,7 +300,8 @@ getInterfaceInfoSet(HANDLE tcpFile, IFInfo **infoSet, PDWORD numInterfaces)
|
|||
|
||||
if(!NT_SUCCESS(status))
|
||||
{
|
||||
fprintf(stderr, "getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n", status);
|
||||
fprintf(stderr, "getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -336,8 +330,9 @@ getInterfaceInfoSet(HANDLE tcpFile, IFInfo **infoSet, PDWORD numInterfaces)
|
|||
tdiGetIpAddrsForIpEntity(tcpFile, &ip_ent, &addrs, &numAddrs);
|
||||
for(j = 0; NT_SUCCESS(status) && j < numAddrs; j++)
|
||||
{
|
||||
fprintf(stderr, "ADDR %d: index %ld (target %ld)\n", j, addrs[j].iae_index,
|
||||
infoSetInt[curInterf].if_info.ent.if_index);
|
||||
fprintf(stderr, "ADDR %d: index %ld (target %ld)\n", j,
|
||||
addrs[j].iae_index,
|
||||
infoSetInt[curInterf].if_info.ent.if_index);
|
||||
if(addrs[j].iae_index == infoSetInt[curInterf].if_info.ent.if_index)
|
||||
{
|
||||
memcpy(&infoSetInt[curInterf].ip_addr, &addrs[j],
|
||||
|
@ -435,7 +430,7 @@ getIPAddrEntryForIf(HANDLE tcpFile, char *name, DWORD index, IFInfo *ifInfo)
|
|||
|
||||
if(!NT_SUCCESS(status))
|
||||
{
|
||||
fprintf(stderr,"getIPAddrEntryForIf returning %lx\n", status);
|
||||
fprintf(stderr, "getIPAddrEntryForIf returning %lx\n", status);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -455,8 +450,8 @@ getInterfaceIndexTableInt(BOOL nonLoopbackOnly)
|
|||
{
|
||||
status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
|
||||
|
||||
fprintf(stderr,"InterfaceInfoSet: %08lx, %04lx:%08lx\n", status,
|
||||
ifInfo->entity_id.tei_entity, ifInfo->entity_id.tei_instance);
|
||||
fprintf(stderr, "InterfaceInfoSet: %08lx, %04lx:%08lx\n", status,
|
||||
ifInfo->entity_id.tei_entity, ifInfo->entity_id.tei_instance);
|
||||
|
||||
if(NT_SUCCESS(status))
|
||||
{
|
||||
|
@ -466,14 +461,14 @@ getInterfaceIndexTableInt(BOOL nonLoopbackOnly)
|
|||
if(ret)
|
||||
{
|
||||
ret->numAllocated = numInterfaces;
|
||||
fprintf(stderr,"NumInterfaces = %ld\n", numInterfaces);
|
||||
fprintf(stderr, "NumInterfaces = %ld\n", numInterfaces);
|
||||
|
||||
for(i = 0; i < numInterfaces; i++)
|
||||
{
|
||||
fprintf(stderr,"Examining interface %d\n", i);
|
||||
fprintf(stderr, "Examining interface %d\n", i);
|
||||
if(!nonLoopbackOnly || !isLoopback(tcpFile, &ifInfo[i].entity_id))
|
||||
{
|
||||
fprintf(stderr,"Interface %d matches (%ld)\n", i, curInterface);
|
||||
fprintf(stderr, "Interface %d matches (%ld)\n", i, curInterface);
|
||||
ret->indexes[curInterface++] = ifInfo[i].if_info.ent.if_index;
|
||||
}
|
||||
}
|
||||
|
@ -498,10 +493,9 @@ getInterfaceIndexTable(void)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* We need this in the Microsoft C/C++ port, as we're not using Pthreads, and jeff insists
|
||||
* on naming the threads at runtime.
|
||||
* Apparently throwing exception 1080890248 is only visible when running under a machine
|
||||
* code monitor.
|
||||
* We need this in the Microsoft C/C++ port, as we're not using Pthreads, and
|
||||
* jeff insists on naming the threads at runtime. Apparently throwing exception
|
||||
* 1080890248 is only visible when running under a machine code monitor.
|
||||
*
|
||||
* -despair86 30/07/18
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue