initial admin api infra

pull/23/head
Jeff Becker 6 years ago
parent bb3bed11dc
commit 475ac63f4a
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -318,6 +318,7 @@ set(LIB_SRC
${UTP_SRC}
${NTRU_SRC}
llarp/address_info.cpp
llarp/arpc.cpp
llarp/bencode.cpp
llarp/buffer.cpp
llarp/config.cpp

@ -1,8 +1,6 @@
#include <llarp/logger.h>
#include <llarp/logger.hpp>
int
main(int argc, char* argv[])
{
return 1;
}
return 0;
}

@ -1,74 +0,0 @@
## Building on Linux
# or your OS or distro's package manager
$ sudo apt install build-essential libtool autoconf cmake git
$ git clone --recursive https://github.com/loki-project/lokinet-builder
$ cd lokinet-builder
$ make
## Building on Windows (mingw-w64 native, or wow64/linux/unix cross-compiler)
#i686 or x86_64
#if cross-compiling from anywhere other than wow64, export CC and CXX to
#$ARCH-w64-mingw32-g[cc++] respectively
$ pacman -Sy base-devel mingw-w64-$ARCH-toolchain git libtool autoconf cmake
$ git clone --recursive https://github.com/loki-project/lokinet-builder
$ cd lokinet-builder
$ make ensure sodium
$ cd build
$ cmake ../deps/llarp -DSODIUM_LIBRARIES=./prefix/lib/libsodium.a -DSODIUM_INCLUDE_DIR=./prefix/include -G "Unix Makefiles" -DHAVE_CXX17_FILESYSTEM=ON
$ make
$ cp llarpd ../lokinet.exe
## Building on Windows using Microsoft C/C++ (Visual Studio 2017)
* clone https://github.com/loki-project/lokinet-builder from git-bash or whatever git browser you use
* open `%CLONE_PATH%/lokinet-builder/deps/sodium/builds/msvc/vs2017/libsodium.sln` and build one of the targets
* create a `build` folder in `%CLONE_PATH%/lokinet-builder`
* run cmake-gui from `%CLONE_PATH%/lokinet-builder/deps/llarp` as the source directory
* define `SODIUM_LIB` to `%CLONE_PATH%/lokinet-builder/deps/sodium/bin/win32/%CONFIG%/%TOOLSET%/%TARGET%/libsodium.lib`
* define `SODIUM_INCLUDE_DIR` to `%CLONE_PATH%/lokinet-builder/deps/sodium/src/libsodium/include`
* define `HAVE_CXX17_FILESYSTEM` to `TRUE`
* select `Visual Studio 2017 15 %ARCH%` as the generator
* enter a custom toolset if desired (usually `v141_xp`)
* generate the developer studio project files and open in the IDE
* select a configuration
* press F7 to build everything
## Running
$ ./lokinet
or press `Debug`/`Local Windows Debugger` in the visual studio standard toolbar
### Development
Please note development builds are likely to be unstable.
##### Build requirements:
* CMake
* ninja (for unit testing with Google Tests)
* libsodium >= 1.0.14 (included here)
* c++ 11 capable C++ compiler
* if you have C++17 `<filesystem>` or `<experimental/filesystem>` declared and defined in your platform's C++ toolchain, re-run CMake (in `lokinet-builder/build`) with `-DHAVE_CXX17_FILESYSTEM=ON`.
* since each platform seems to have its own idea of where `std::[experimental::]filesystem` is defined, you will need to manually specify its library in `LDFLAGS` or `CMAKE_x_LINKER_FLAGS` as well.
##### Windows:
* Mingw-w64 is recommended for 32 or 64-bit builds.
* It *is* possible to compile with Microsoft C++ (v19 or later from VS2015+).
* `cpp17::filesystem` in `vendor/cppbackport-master` is not available for Windows.
#### Boxed warning
<div style="border:5px solid #f00;padding:5px">
<p>Inbound sessions are unsupported on Windows Server systems.</p>
<p><strong><em>Ignore this warning at your own peril.</em></strong></p>
</div>
##### Building a debug build:
#in lokinet-builder/
$ cd build
$ make

@ -0,0 +1,154 @@
LokiNET admin api
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in RFC 2119 [RFC2119].
message format is jsonrpc 2.0 like api serialized with bittorrent encoding (BEncode) over
TCP
messages are prefixed with big endian 16 bit length field indicating how many bytes the next
message is.
a version 1 aRPC message is structured as the following message:
{
"aRPC-method": "llarp",
"id" : "some-id-here",
"params": {
"key1": "val1",
"key2": "val2"
},
"v" : version_integer,
"z-key" : "<optional 32 bytes public key>",
"z-sig" : "<64 bytes siganture of the entire message requried if z-key is provided>"
}
serialzied it would be:
d13:aRPC-method5:llarp2:id12:some-id-here6:paramsd4:key14:val14:key24:val2e5:z-key32:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5:z-sig64:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe
given the signature is 64 bytes of 'A' and the public key is 32 bytes of 'A'
responses are signed by the identity key and MUST be verified by the caller.
an example of a call to llarp.nodedb.getrc:
{
"aRPC-method": "llarp.nodedb.rc.getbykey",
"id" : "<12 bytes random>",
"params": {
"key" : "<32 bytes identity key>"
}
}
the reply MUST be signed by the router's identity key
{
"aRPC-method" : "llarp.nodedb.rc.getbykey",
"id" : "<12 bytes from before>",
"return": {
"value" : [RC, RC, RC]
}
"time": uint64_milliseconds_since_epoch_timestamp_now,
"z-key": "<32 bytes identity public key>",
"z-sig": "<64 bytes sig>"
}
and on error:
{
"aRPC-method" : "llarp.nodedb.rc.getbykey",
"id" : "<12 bytes from before>",
"return": {
"error": "error message goes here"
},
"time": uint64_milliseconds_since_epoch_timestamp_now,
"z-key": "<32 bytes identity public key>",
"z-sig": "<64 bytes sig>"
}
if requests are signed then they are authenticated by the signer's public key
requesters can be granted access based on their public key, some methods MAY
require this in order to be called.
------
the methods currently provided are:
llarp.rpc.ping
get a pong back
required parameters:
ping: integer
returns:
ping
llarp.nodedb.rc.getbykey
get rc by public identity key
required parameters:
key: 32 bytes public identity key
returns:
a list of RCs (see protocol v0 spec) that have this public identity key
usually 0 or 1 RCs
llarp.nodedb.rc.getbycidr
get a list of RCs in an address range
required parameters:
cidr: ipv6 network cidr string, i.e. "::ffff.21.0.0.0/8" or "fc00::/7"
limit: integer max number of items to fetch, zero or positive integer,
if zero no limit.
returns:
a list of 0 to limit RCs that advertise themselves as being reachble via an
address in the given CIDR.
llarp.admin.sys.uptime (authentication required)
required paramters:
(none)
returns:
an integer milliseconds since unix epoch we've been online
llarp.admin.link.neighboors (authentication required)
get a list of connected service nodes on all links
required parameters:
(none)
returns:
list of 0 to N dicts in the following format:
{
"connected" : uint64_milliseconds_timestamp_connected_at
"ident" : "<32 bytes public identity key>",
"laddr" : "local address",
"raddr" : "remote address"
}

@ -1 +0,0 @@
insert lokinet api overview here

@ -0,0 +1,64 @@
#ifndef LLARP_ARPC_HPP
#define LLARP_ARPC_HPP
#include <llarp/bencode.hpp>
#include <llarp/crypto.hpp>
#include <llarp/logger.hpp>
#include <llarp/time.h>
#include <llarp/endian.h>
#include <llarp/ev.h>
#include <functional>
#include <string>
#include <map>
#include <unordered_map>
#ifndef _WIN32
#include <sys/un.h>
#endif
#include <llarp/net.hpp>
// forward declare
struct llarp_router;
namespace llarp
{
namespace arpc
{
// forward declare
struct BaseMessage;
struct Server
{
llarp_tcp_acceptor m_acceptor;
llarp_router* router;
Server(llarp_router* r);
static void
OnAccept(llarp_tcp_acceptor* a, llarp_tcp_conn* conn);
bool
Start(const std::string& bindaddr);
const llarp_crypto*
Crypto() const;
const byte_t*
SigningPublicKey() const
{
return llarp::seckey_topublic(SigningPrivateKey());
}
const byte_t*
SigningPrivateKey() const;
bool
Sign(BaseMessage* msg) const;
};
} // namespace arpc
} // namespace llarp
#endif

@ -78,6 +78,54 @@ llarp_ev_udp_sendto(struct llarp_udp_io *udp, const struct sockaddr *to,
int
llarp_ev_close_udp(struct llarp_udp_io *udp);
// forward declare
struct llarp_tcp_acceptor;
/// a single tcp connection
struct llarp_tcp_conn
{
/// user data
void *user;
/// private implementation
void *impl;
/// parent loop (dont set me)
struct llarp_ev_loop *loop;
/// handle read event
void (*read)(struct llarp_tcp_conn *, const void *, size_t);
/// handle close event (free-ing is handled by event loop)
void (*closed)(struct llarp_tcp_conn *);
};
/// queue async write a buffer in full
void
llarp_tcp_conn_async_write(struct llarp_tcp_conn *, const void *, size_t);
/// close a tcp connection
void
llarp_tcp_conn_close(struct llarp_tcp_conn *);
struct llarp_tcp_acceptor
{
/// userdata pointer
void *user;
/// internal implementation
void *impl;
/// parent event loop (dont set me)
struct llarp_ev_loop *loop;
/// handle inbound connection
void (*accepted)(struct llarp_tcp_acceptor *, struct llarp_tcp_conn *);
};
/// bind to an address and start serving async
/// return false if failed to bind
/// return true on successs
bool
llarp_tcp_serve(struct llarp_tcp_acceptor *t, const sockaddr *bindaddr);
/// close and stop accepting connections
void
llarp_tcp_acceptor_close(struct llarp_tcp_acceptor *);
#ifdef _WIN32
#define IFNAMSIZ (16)
#endif

@ -0,0 +1,405 @@
#include <llarp/arpc.hpp>
namespace llarp
{
namespace arpc
{
/// interface for request messages
struct IRequest
{
/// returns false if errmsg is set
/// returns true if retval is set
virtual bool
HandleRequest(Server* ctx, std::unique_ptr< BaseMessage >& retval,
std::string& errmsg) const = 0;
};
struct BaseMessage : public llarp::IBEncodeMessage, public IRequest
{
static constexpr size_t MaxIDSize = 128;
/// maximum size of a message
static constexpr size_t MaxSize = 1024 * 8;
BaseMessage()
{
timestamp = llarp_time_now_ms();
zkey.Zero();
zsig.Zero();
}
std::string m_id;
llarp_time_t timestamp;
llarp::PubKey zkey;
llarp::Signature zsig;
/// override me
virtual std::string
Method() const = 0;
/// encode the entire message
bool
BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictString("aRPC-method", Method(), buf))
return false;
if(!BEncodeWriteDictString("id", m_id, buf))
return false;
if(!BEncodeBody(buf))
return false;
if(!zkey.IsZero())
{
if(!BEncodeWriteDictEntry("z-key", zkey, buf))
return false;
if(!BEncodeWriteDictEntry("z-sig", zsig, buf))
return false;
}
return bencode_end(buf);
}
bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
if(llarp_buffer_eq(k, "id"))
{
return DecodeID(buf);
}
if(llarp_buffer_eq(k, "params"))
{
return DecodeParams(buf);
}
return false;
}
protected:
typedef bool (*ParamDecoder)(dict_reader*, llarp_buffer_t*);
virtual ParamDecoder
GetParamDecoder() const = 0;
bool
DecodeParams(llarp_buffer_t* buf)
{
dict_reader r;
r.user = this;
r.on_key = GetParamDecoder();
return bencode_read_dict(buf, &r);
}
bool
DecodeID(llarp_buffer_t* buf)
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
if(strbuf.sz > MaxIDSize) // too big
return false;
m_id = std::string((char*)strbuf.base, strbuf.sz);
return true;
}
/// encode body of message
virtual bool
BEncodeBody(llarp_buffer_t* buf) const = 0;
};
struct ConnHandler
{
ConnHandler(Server* s, llarp_tcp_conn* c) : parent(s), m_conn(c)
{
left = 0;
readingHeader = true;
}
bool readingHeader;
Server* parent;
llarp_tcp_conn* m_conn;
AlignedBuffer< BaseMessage::MaxSize > buf;
uint16_t left;
void
ParseMessage();
void
Close()
{
llarp_tcp_conn_close(m_conn);
}
static void
OnClosed(llarp_tcp_conn* conn)
{
ConnHandler* self = static_cast< ConnHandler* >(conn->user);
delete self;
}
static void
OnRead(llarp_tcp_conn* conn, const void* buf, size_t sz)
{
ConnHandler* self = static_cast< ConnHandler* >(conn->user);
const byte_t* ptr = (const byte_t*)buf;
do
{
if(self->readingHeader)
{
self->left = bufbe16toh(ptr);
sz -= 2;
ptr += 2;
self->readingHeader = false;
}
size_t dlt = std::min((size_t)self->left, sz);
memcpy(self->buf.data() + (self->buf.size() - self->left), ptr, dlt);
self->left -= dlt;
sz -= dlt;
if(self->left == 0)
{
self->ParseMessage();
self->readingHeader = true;
}
} while(sz > 0);
}
};
/// base type for ping req/resp
struct Ping : public BaseMessage
{
Ping() : BaseMessage()
{
}
uint64_t ping;
std::string
Method() const
{
return "llarp.rpc.ping";
}
bool
BEncodeBody(llarp_buffer_t* buf) const
{
if(!bencode_write_bytestring(buf, "params", 6))
return false;
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictInt("ping", ping, buf))
return false;
return bencode_end(buf);
}
static bool
OnParamKey(dict_reader* r, llarp_buffer_t* k)
{
Ping* self = static_cast< Ping* >(r->user);
if(k && llarp_buffer_eq(*k, "ping"))
{
return bencode_read_integer(r->buffer, &self->ping);
}
else
return k == nullptr;
}
virtual ParamDecoder
GetParamDecoder() const
{
return &OnParamKey;
}
};
struct PingResponse : public Ping
{
PingResponse(uint64_t p) : Ping()
{
ping = p;
}
bool
HandleRequest(Server*, std::unique_ptr< BaseMessage >&,
std::string&) const
{
/// TODO: handle client response
llarp::LogInfo(Method(), "pong ", ping);
return false;
}
};
struct PingRequest : public Ping
{
bool
HandleRequest(Server* serv, std::unique_ptr< BaseMessage >& retval,
std::string& errmsg) const
{
PingResponse* resp = new PingResponse(ping);
if(!serv->Sign(resp))
{
errmsg = "failed to sign response";
return false;
}
retval.reset(resp);
return true;
}
};
struct MessageReader
{
dict_reader m_reader;
BaseMessage* msg = nullptr;
MessageReader()
{
m_reader.user = this;
m_reader.on_key = &OnKey;
}
static bool
OnKey(dict_reader* r, llarp_buffer_t* key)
{
static std::unordered_map< std::string,
const std::function< BaseMessage*(void) > >
msgConstructors = {
{"llarp.rpc.ping",
[]() -> BaseMessage* { return new PingRequest(); }},
};
MessageReader* self = static_cast< MessageReader* >(r->user);
if(self->msg == nullptr)
{
// first key
if(key == nullptr || !llarp_buffer_eq(*key, "aRPC-method"))
{
// bad value
return false;
}
llarp_buffer_t strbuf;
if(!bencode_read_string(r->buffer, &strbuf))
return false;
std::string method = std::string((char*)strbuf.base, strbuf.sz);
auto itr = msgConstructors.find(method);
if(itr == msgConstructors.end())
{
// no such method
return false;
}
else
self->msg = itr->second();
return true;
}
else if(key)
return self->msg->DecodeKey(*key, r->buffer);
else
return true;
}
bool
DecodeMessage(llarp_buffer_t* buf,
std::unique_ptr< BaseMessage >& request)
{
msg = nullptr;
if(!bencode_read_dict(buf, &m_reader))
return false;
request.reset(msg);
return true;
}
};
Server::Server(llarp_router* r)
{
router = r;
m_acceptor.user = this;
m_acceptor.accepted = &OnAccept;
}
bool
Server::Start(const std::string& bindaddr)
{
llarp::Addr addr;
sockaddr* saddr = nullptr;
#ifndef _WIN32
sockaddr_un unaddr;
if(bindaddr.find("unix:") == 0)
{
unaddr.sun_family = AF_UNIX;
strncpy(unaddr.sun_path, bindaddr.substr(5).c_str(),
sizeof(unaddr.sun_path));
saddr = (sockaddr*)&unaddr;
}
else
#endif
{
// TODO: ipv6
auto idx = bindaddr.find(':');
std::string host = bindaddr.substr(0, idx);
uint16_t port = std::stoi(bindaddr.substr(idx + 1));
addr = llarp::Addr(host, port);
saddr = addr.getSockAddr();
}
return llarp_tcp_serve(&m_acceptor, saddr);
}
void
Server::OnAccept(llarp_tcp_acceptor* a, llarp_tcp_conn* conn)
{
Server* self = static_cast< Server* >(a->user);
conn->user = new ConnHandler(self, conn);
conn->read = &ConnHandler::OnRead;
conn->closed = &ConnHandler::OnClosed;
}
bool
Server::Sign(BaseMessage* msg) const
{
msg->zkey = SigningPublicKey();
msg->zsig.Zero();
llarp::Signature sig;
//
byte_t tmp[BaseMessage::MaxSize];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
return false;
// rewind buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
if(!Crypto()->sign(sig, SigningPrivateKey(), buf))
return false;
msg->zsig = sig;
return true;
}
void
ConnHandler::ParseMessage()
{
std::unique_ptr< BaseMessage > msg;
std::unique_ptr< BaseMessage > response;
std::string errmsg;
MessageReader r;
auto tmp = llarp::Buffer(buf);
if(!r.DecodeMessage(&tmp, msg))
{
llarp::LogError("failed to decode message");
Close();
return;
}
// handle request
if(!msg->HandleRequest(parent, response, errmsg))
{
// TODO: send error reply
llarp::LogError("failed to handle api message: ", errmsg);
Close();
return;
}
if(!parent->Sign(response.get()))
{
llarp::LogError("failed to sign response");
Close();
}
}
} // namespace arpc
} // namespace llarp

@ -35,8 +35,7 @@ namespace llarp
iwp_links = find_section(top, "bind", section_t{});
services = find_section(top, "services", section_t{});
system = find_section(top, "system", section_t{});
// std::ofstream ft("config_test.ini");
// parser.dump(ft);
api = find_section(top, "api", section_t{});
return true;
}
return false;
@ -130,6 +129,19 @@ llarp_generic_ensure_config(std::ofstream &f, std::string basepath)
f << "# nickname=lokinet" << std::endl;
f << std::endl << std::endl;
f << "# admin api (disabled by default)" << std::endl;
f << "[api]" << std::endl;
f << "enabled=false" << std::endl;
f << "# authkey=insertpubkey1here" << std::endl;
f << "# authkey=insertpubkey2here" << std::endl;
f << "# authkey=insertpubkey3here" << std::endl;
#ifdef _WIN32
f << "bind=127.0.0.1:1190" << std::endl;
#else
f << "bind=unix:" << basepath << "api.socket" << std::endl;
#endif
f << std::endl << std::endl;
f << "# system settings for priviledges and such" << std::endl;
f << "[system]" << std::endl;
#ifdef _WIN32
@ -302,10 +314,10 @@ extern "C"
{
iter->conf = conf;
std::map< std::string, llarp::Config::section_t & > sections = {
{"network", conf->impl.network}, {"connect", conf->impl.connect},
{"system", conf->impl.system}, {"bind", conf->impl.iwp_links},
{"netdb", conf->impl.netdb}, {"dns", conf->impl.dns},
{"services", conf->impl.services}};
{"network", conf->impl.network}, {"connect", conf->impl.connect},
{"system", conf->impl.system}, {"bind", conf->impl.iwp_links},
{"netdb", conf->impl.netdb}, {"dns", conf->impl.dns},
{"api", conf->impl.api}, {"services", conf->impl.services}};
for(const auto item : conf->impl.router)
iter->visit(iter, "router", item.first.c_str(), item.second.c_str());

@ -19,6 +19,7 @@ namespace llarp
section_t connect;
section_t services;
section_t system;
section_t api;
bool
Load(const char *fname);

@ -123,3 +123,28 @@ llarp_ev_tun_async_write(struct llarp_tun_io *tun, const void *pkt, size_t sz)
// TODO: queue write
return static_cast< llarp::ev_io * >(tun->impl)->do_write((void *)pkt, sz);
}
bool
llarp_tcp_serve(struct llarp_tcp_acceptor *tcp, const struct sockaddr *bindaddr)
{
// TODO: implement me
return false;
}
void
llarp_tcp_conn_close(struct llarp_tcp_conn *conn)
{
if(!conn)
return;
llarp::ev_io *impl = static_cast< llarp::ev_io * >(conn->impl);
conn->impl = nullptr;
// deregister
conn->loop->close_ev(impl);
// close fd and delete impl
delete impl;
// call hook if needed
if(conn->closed)
conn->closed(conn);
// delete
delete conn;
}

@ -50,7 +50,7 @@ namespace llarp
virtual int
sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
/// used for tun interface
/// used for tun interface and tcp conn
virtual bool
do_write(void* data, size_t sz)
{

@ -2,6 +2,8 @@
#include <llarp/path.hpp>
#include <llarp/pathbuilder.hpp>
#include <functional>
#include "buffer.hpp"
#include "router.hpp"
@ -14,9 +16,10 @@ namespace llarp
typedef llarp::path::PathSet PathSet_t;
PathSet_t* pathset = nullptr;
Path_t* path = nullptr;
typedef void (*Handler)(AsyncPathKeyExchangeContext< User >*);
User* user = nullptr;
Handler result = nullptr;
typedef std::function< void(AsyncPathKeyExchangeContext< User >*) > Handler;
User* user = nullptr;
Handler result;
size_t idx = 0;
llarp_threadpool* worker = nullptr;
llarp_logic* logic = nullptr;
@ -29,6 +32,7 @@ namespace llarp
AsyncPathKeyExchangeContext< User >* ctx =
static_cast< AsyncPathKeyExchangeContext< User >* >(u);
ctx->result(ctx);
delete ctx;
}
static void
@ -138,7 +142,6 @@ namespace llarp
if(!router->SendToOrQueue(remote, &ctx->LRCM))
{
llarp::LogError("failed to send LRCM");
delete ctx;
return;
}
@ -146,7 +149,6 @@ namespace llarp
router->PersistSessionUntil(remote, ctx->path->ExpireTime());
// add own path
router->paths.AddOwnPath(ctx->pathset, ctx->path);
delete ctx;
}
namespace path

@ -3,6 +3,7 @@
#include <llarp/iwp.hpp>
#include <llarp/link_message.hpp>
#include <llarp/link/utp.hpp>
#include <llarp/arpc.hpp>
#include "buffer.hpp"
#include "encode.hpp"
@ -647,6 +648,22 @@ llarp_router::async_verify_RC(const llarp::RouterContact &rc)
void
llarp_router::Run()
{
if(enableRPCServer)
{
if(rpcBindAddr.empty())
{
rpcBindAddr = DefaultRPCBindAddr;
}
rpcServer = std::make_unique< llarp::arpc::Server >(this);
if(!rpcServer->Start(rpcBindAddr))
{
llarp::LogError("Binding rpc server to ", rpcBindAddr, " failed");
rpcServer.reset();
}
else
llarp::LogInfo("Bound RPC server to ", rpcBindAddr);
}
routerProfiling.Load(routerProfilesFile.c_str());
// zero out router contact
sockaddr *dest = (sockaddr *)&this->ip4addr;
@ -1138,6 +1155,21 @@ namespace llarp
self->defaultIfName = val;
}
}
else if(StrEq(section, "api"))
{
if(StrEq(key, "enabled"))
{
self->enableRPCServer = IsTrueValue(val);
}
if(StrEq(key, "bind"))
{
self->rpcBindAddr = val;
}
if(StrEq(key, "authkey"))
{
// TODO: add pubkey to whitelist
}
}
else if(StrEq(section, "services"))
{
if(self->LoadHiddenServiceConfig(val))
@ -1218,5 +1250,20 @@ namespace llarp
self->publicOverride = true;
}
}
} // namespace llarp
}
namespace arpc
{
const byte_t *
Server::SigningPrivateKey() const
{
return router->identity;
}
const llarp_crypto *
Server::Crypto() const
{
return &router->crypto;
}
} // namespace arpc
} // namespace llarp

@ -5,6 +5,7 @@
#include <llarp/router_contact.hpp>
#include <llarp/path.hpp>
#include <llarp/link_layer.hpp>
#include <llarp/arpc.hpp>
#include <functional>
#include <list>
@ -102,6 +103,11 @@ struct llarp_router
bool
ShouldCreateDefaultHiddenService();
std::string DefaultRPCBindAddr = "127.0.0.1:1190";
bool enableRPCServer = false;
std::unique_ptr< llarp::arpc::Server > rpcServer;
std::string rpcBindAddr = DefaultRPCBindAddr;
std::unique_ptr< llarp::ILinkLayer > outboundLink;
std::vector< std::unique_ptr< llarp::ILinkLayer > > inboundLinks;

Loading…
Cancel
Save