pull/1/head
Ryan Tharp 6 years ago
commit deb97fda3f

@ -125,7 +125,6 @@ set(LIB_SRC
llarp/nodedb.cpp
llarp/path.cpp
llarp/pathbuilder.cpp
llarp/path_confirm.cpp
llarp/proofofwork.cpp
llarp/relay_ack.cpp
llarp/relay_commit.cpp
@ -137,6 +136,12 @@ set(LIB_SRC
llarp/testnet.c
llarp/time.cpp
llarp/timer.cpp
llarp/api/create_session.cpp
llarp/api/client.cpp
llarp/api/message.cpp
llarp/api/parser.cpp
llarp/routing/message_parser.cpp
llarp/routing/path_confirm.cpp
vendor/cppbackport-master/lib/fs/rename.cpp
vendor/cppbackport-master/lib/fs/filestatus.cpp
vendor/cppbackport-master/lib/fs/filetype.cpp
@ -157,12 +162,19 @@ set(LIB_SRC
set(TEST_SRC
test/main.cpp
test/api_unittest.cpp
test/dht_unittest.cpp
test/encrypted_frame_unittest.cpp
)
set(TEST_EXE testAll)
set(GTEST_DIR test/gtest)
set(CLIENT_EXE llarpc)
set(CLIENT_SRC
client/main.cpp
)
# TODO: exclude this from includes and expose stuff properly for rcutil
include_directories(llarp)
@ -179,7 +191,8 @@ else()
add_executable(rcutil daemon/rcutil.cpp)
add_executable(${EXE} ${EXE_SRC})
add_executable(${CLIENT_EXE} ${CLIENT_SRC})
if(WITH_TESTS)
enable_testing()
add_subdirectory(${GTEST_DIR})
@ -195,6 +208,7 @@ else()
if(NOT WITH_SHARED)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB})
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB})
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB})
endif()
endif()

@ -66,7 +66,7 @@ testnet-build: testnet-configure
testnet: testnet-build
mkdir -p $(TESTNET_ROOT)
python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=300 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF)
python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=1 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF)
supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
test: debug-configure

@ -0,0 +1,15 @@
#include <llarp/api.hpp>
int
main(int argc, char* argv[])
{
std::string url = llarp::api::DefaultURL;
if(argc > 1)
{
url = argv[1];
}
llarp::api::Client cl;
if(!cl.Start(url))
return 1;
return cl.Mainloop();
}

@ -137,14 +137,13 @@ s is the long term public signing key
v is the protocol version
x is a nounce value for generating vanity addresses that can be omitted
if x is included it MUST be less than or equal to 16 bytes, any larger and it is
considered invalid.
if x is included it MUST be equal to 16 bytes
{
e: "<32 bytes public encryption key>",
s: "<32 bytes public signing key>",
v: 0,
x: "<optional nounce for vanity>"
x: "<optional 16 bytes nonce for vanity>"
}
service address (SA)
@ -314,10 +313,6 @@ h = HS(BE(w))
h has log_e(y) prefix of 0x00
y = 2 means prefix of 0x00
y = 4 means prefix of 0x00 0x00
y = 32 means prefix 0x00 0x00 0x00 0x00 0x00
this proof of work requirement is subject to change
if i is equal to RC.k then any LRDM.x values are decrypted and interpreted as
@ -345,7 +340,7 @@ otherwise transmit a LRUM to the next hop
p: p,
v: 0,
x: x1,
y: HS(y)
y: y
}
link relay downstream message (LRDM)
@ -542,7 +537,7 @@ transfer data between paths.
P: "<16 bytes path id>",
T: "<N bytes data>",
V: 0,
Y: "<32 bytes nounce>",
Y: "<32 bytes nounce>"
}
transfer data to another path with id P on the local router place Y and T values

@ -58,6 +58,12 @@ namespace llarp
return !(*this == other);
}
bool
operator<(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) < 0;
}
size_t
size() const
{

@ -0,0 +1,14 @@
#ifndef LLARP_API_HPP
#define LLARP_API_HPP
#include <llarp/api/client.hpp>
#include <llarp/api/server.hpp>
namespace llarp
{
namespace api
{
const char DefaultURL[] = "127.0.0.1:34567";
}
} // namespace llarp
#endif

@ -0,0 +1,29 @@
#ifndef LLARP_API_CLIENT_HPP
#define LLARP_API_CLIENT_HPP
#include <string>
namespace llarp
{
namespace api
{
struct ClientPImpl;
struct Client
{
Client();
~Client();
bool
Start(const std::string& apiURL);
int
Mainloop();
private:
ClientPImpl* m_Impl;
};
} // namespace api
} // namespace llarp
#endif

@ -0,0 +1,125 @@
#ifndef LLARP_API_MESSAGES_HPP
#define LLARP_API_MESSAGES_HPP
#include <list>
#include <llarp/aligned.hpp>
#include <llarp/bencode.hpp>
#include <llarp/crypto.hpp>
namespace llarp
{
namespace api
{
// forward declare
struct Client;
struct Server;
/// base message
struct IMessage : public IBEncodeMessage
{
uint64_t sessionID = 0;
uint64_t msgID = 0;
uint64_t version = 0;
llarp::ShortHash hash;
// the function name this message belongs to
virtual std::string
FunctionName() const = 0;
bool
BEncode(llarp_buffer_t* buf) const;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
virtual std::list< IBEncodeMessage* >
GetParams() const = 0;
virtual bool
DecodeParams(llarp_buffer_t* buf) = 0;
bool
IsWellFormed(llarp_crypto* c, const std::string& password);
void
CalculateHash(llarp_crypto* c, const std::string& password);
};
/// a "yes we got your command" type message
struct AcknoledgeMessage : public IMessage
{
};
/// start a session with the router
struct CreateSessionMessage : public IMessage
{
std::list< IBEncodeMessage* >
GetParams() const
{
return {};
}
bool
DecodeParams(llarp_buffer_t* buf);
std::string
FunctionName() const
{
return "CreateSession";
}
};
/// a keepalive ping
struct SessionPingMessage : public IMessage
{
};
/// end a session with the router
struct DestroySessionMessage : public IMessage
{
};
/// base messgae type for hidden service control and transmission
struct HSMessage : public IMessage
{
llarp::PubKey pubkey;
llarp::Signature sig;
/// validate signature on message (server side)
bool
SignatureIsValid(llarp_crypto* crypto) const;
/// sign message using secret key (client side)
bool
SignMessge(llarp_crypto* crypto, byte_t* seckey);
};
/// create a new hidden service
struct CreateServiceMessgae : public HSMessage
{
};
/// end an already created hidden service we created
struct DestroyServiceMessage : public HSMessage
{
};
/// start lookup of another service's descriptor
struct LookupServiceMessage : public IMessage
{
};
/// publish our hidden service's descriptor
struct PublishServiceMessage : public IMessage
{
};
/// send pre encrypted data down a path we own
struct SendPathDataMessage : public IMessage
{
};
} // namespace api
} // namespace llarp
#endif

@ -0,0 +1,26 @@
#ifndef LLARP_API_PARSER_HPP
#define LLARP_API_PARSER_HPP
#include <llarp/bencode.h>
#include <llarp/api/messages.hpp>
namespace llarp
{
namespace api
{
struct MessageParser
{
MessageParser();
IMessage *
ParseMessage(llarp_buffer_t buf);
private:
static bool
OnKey(dict_reader *r, llarp_buffer_t *key);
IMessage *msg = nullptr;
dict_reader r;
};
} // namespace api
} // namespace llarp
#endif

@ -0,0 +1,29 @@
#ifndef LLARP_API_SERVER_HPP
#define LLARP_API_SERVER_HPP
#include <llarp/ev.h>
#include <llarp/router.h>
#include <string>
namespace llarp
{
namespace api
{
struct ServerPImpl;
struct Server
{
Server(llarp_router* r);
~Server();
bool
Bind(const std::string& url, llarp_ev_loop* loop);
private:
ServerPImpl* m_Impl;
};
} // namespace api
} // namespace llarp
#endif

@ -12,6 +12,13 @@ namespace llarp
return bencode_write_bytestring(buf, k, 1)
&& bencode_write_bytestring(buf, t, 1);
}
template < typename Obj_t >
bool
BEncodeWriteDictString(const char* k, const Obj_t& str, llarp_buffer_t* buf)
{
return bencode_write_bytestring(buf, k, 1)
&& bencode_write_bytestring(buf, str.c_str(), str.size());
}
template < typename Obj_t >
bool
@ -48,6 +55,23 @@ namespace llarp
return true;
}
template < typename Int_t >
bool
BEncodeMaybeReadDictInt(const char* k, Int_t& i, bool& read,
llarp_buffer_t key, llarp_buffer_t* buf)
{
if(llarp_buffer_eq(key, k))
{
if(!bencode_read_integer(buf, &i))
{
llarp::Warn("failed to decode key ", k);
return false;
}
read = true;
}
return true;
}
template < typename Item_t >
bool
BEncodeMaybeReadVersion(const char* k, Item_t& item, uint64_t expect,
@ -62,6 +86,22 @@ namespace llarp
return true;
}
template < typename List_t >
bool
BEncodeWriteDictBEncodeList(const char* k, const List_t& l,
llarp_buffer_t* buf)
{
if(!bencode_write_bytestring(buf, k, 1))
return false;
if(!bencode_start_list(buf))
return false;
for(const auto& item : l)
if(!item->BEncode(buf))
return false;
return bencode_end(buf);
}
template < typename Iter >
bool
BEncodeWriteList(Iter itr, Iter end, llarp_buffer_t* buf)
@ -102,6 +142,19 @@ namespace llarp
return bencode_write_bytestring(buf, k, 1)
&& BEncodeWriteList(list.begin(), list.end(), buf);
}
/// bencode serializable message
struct IBEncodeMessage
{
virtual ~IBEncodeMessage(){};
virtual bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) = 0;
virtual bool
BEncode(llarp_buffer_t* buf) const = 0;
};
} // namespace llarp
#endif

@ -46,7 +46,7 @@ typedef byte_t llarp_tunnel_nonce_t[TUNNONCESIZE];
/// PKE(result, publickey, secretkey, nonce)
typedef bool (*llarp_path_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *);
/// TKE(result publickey, secretkey, nonce)
/// TKE(result, publickey, secretkey, nonce)
typedef bool (*llarp_transport_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *);
/// SD/SE(buffer, key, nonce)

@ -1,8 +1,8 @@
#ifndef LLARP_LINK_MESSAGE_HPP
#define LLARP_LINK_MESSAGE_HPP
#include <llarp/bencode.h>
#include <llarp/link.h>
#include <llarp/bencode.hpp>
#include <llarp/router_id.hpp>
#include <queue>
@ -15,7 +15,7 @@ namespace llarp
typedef std::queue< ILinkMessage* > SendQueue;
/// parsed link layer message
struct ILinkMessage
struct ILinkMessage : public IBEncodeMessage
{
/// who did this message come from (rc.k)
RouterID remote = {};
@ -24,14 +24,6 @@ namespace llarp
ILinkMessage() = default;
ILinkMessage(const RouterID& id);
virtual ~ILinkMessage(){};
virtual bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) = 0;
virtual bool
BEncode(llarp_buffer_t* buf) const = 0;
virtual bool
HandleMessage(llarp_router* router) const = 0;
};
@ -63,6 +55,6 @@ namespace llarp
llarp_link_session* from;
ILinkMessage* msg = nullptr;
};
}
} // namespace llarp
#endif

@ -1,7 +1,7 @@
#ifndef LLARP_MESSAGE_PATH_CONFIRM_HPP
#define LLARP_MESSAGE_PATH_CONFIRM_HPP
#include <llarp/routing_message.hpp>
#include <llarp/routing/message.hpp>
namespace llarp
{
@ -11,18 +11,21 @@ namespace llarp
{
uint64_t pathLifetime;
uint64_t pathCreated;
PathConfirmMessage();
PathConfirmMessage(uint64_t lifetime);
~PathConfirmMessage(){};
bool
BEncode(llarp_buffer_t* buf) const;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
bool
BDecode(llarp_buffer_t* buf);
bool
HandleMessage(llarp_router* r) const;
HandleMessage(IMessageHandler* h) const;
};
} // namespace routing
} // namespace llarp

@ -0,0 +1,28 @@
#ifndef LLARP_MESSAGES_PATH_LATENCY_HPP
#define LLARP_MESSAGES_PATH_LATENCY_HPP
#include <llarp/routing/message.hpp>
namespace llarp
{
namespace routing
{
struct PathLatencyMessage : public IMessage
{
uint64_t T = 0;
uint64_t L = 0;
PathLatencyMessage();
bool
BEncode(llarp_buffer_t* buf) const;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
bool
HandleMessage(IMessageHandler* r) const;
};
} // namespace routing
} // namespace llarp
#endif

@ -10,7 +10,8 @@
#include <llarp/messages/relay_commit.hpp>
#include <llarp/path_types.hpp>
#include <llarp/router_id.hpp>
#include <llarp/routing_message.hpp>
#include <llarp/routing/handler.hpp>
#include <llarp/routing/message.hpp>
#include <list>
#include <map>
@ -173,7 +174,7 @@ namespace llarp
};
/// A path we made
struct Path : public IHopHandler
struct Path : public IHopHandler, public llarp::routing::IMessageHandler
{
typedef std::vector< PathHopConfig > HopList;
HopList hops;
@ -191,6 +192,9 @@ namespace llarp
bool
HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r);
bool
HandleHiddenServiceData(llarp_buffer_t buf);
// handle data in upstream direction
bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
@ -201,7 +205,10 @@ namespace llarp
// Is this deprecated?
const PathID_t&
PathID() const;
TXID() const;
const PathID_t&
RXID() const;
const PathID_t&
TXID() const;
@ -211,6 +218,9 @@ namespace llarp
RouterID
Upstream() const;
protected:
llarp::routing::InboundMessageParser m_InboundMessageParser;
};
enum PathBuildStatus
@ -250,7 +260,7 @@ namespace llarp
GetByUpstream(const RouterID& id, const PathID_t& path);
IHopHandler*
GetDownstream(const RouterID& id, const PathID_t& path);
GetByDownstream(const RouterID& id, const PathID_t& path);
bool
ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames);

@ -0,0 +1,19 @@
#ifndef LLARP_ROUTING_HANDLER_HPP
#define LLARP_ROUTING_HANDLER_HPP
#include <llarp/buffer.h>
namespace llarp
{
namespace routing
{
// handles messages on owned paths
struct IMessageHandler
{
virtual bool
HandleHiddenServiceData(llarp_buffer_t buf) = 0;
};
} // namespace routing
} // namespace llarp
#endif

@ -0,0 +1,39 @@
#ifndef LLARP_ROUTING_MESSAGE_HPP
#define LLARP_ROUTING_MESSAGE_HPP
#include <llarp/buffer.h>
#include <llarp/router.h>
#include <llarp/bencode.hpp>
#include <llarp/path_types.hpp>
namespace llarp
{
namespace routing
{
struct IMessageHandler;
struct IMessage : public llarp::IBEncodeMessage
{
llarp::PathID_t from;
virtual bool
HandleMessage(IMessageHandler* r) const = 0;
};
struct InboundMessageParser
{
InboundMessageParser();
bool
ParseMessageBuffer(llarp_buffer_t buf, IMessageHandler* handler);
private:
static bool
OnKey(dict_reader* r, llarp_buffer_t* key);
bool firstKey;
dict_reader reader;
IMessage* msg;
};
} // namespace routing
} // namespace llarp
#endif

@ -1,30 +0,0 @@
#ifndef LLARP_ROUTING_MESSAGE_HPP
#define LLARP_ROUTING_MESSAGE_HPP
#include <llarp/buffer.h>
#include <llarp/router.h>
#include <llarp/path_types.hpp>
namespace llarp
{
namespace routing
{
struct IMessage
{
llarp::PathID_t from;
virtual ~IMessage(){};
virtual bool
BEncode(llarp_buffer_t* buf) const = 0;
virtual bool
BDecode(llarp_buffer_t* buf) = 0;
virtual bool
HandleMessage(llarp_router* r) const = 0;
};
} // namespace routing
} // namespace llarp
#endif

@ -0,0 +1,57 @@
#ifndef LLARP_SERVICE_HPP
#define LLARP_SERVICE_HPP
#include <llarp/aligned.hpp>
#include <llarp/bencode.hpp>
#include <llarp/crypto.hpp>
namespace llarp
{
namespace service
{
/// hidden service address
typedef llarp::AlignedBuffer< 32 > Address;
typedef llarp::AlignedBuffer< 16 > VanityNonce;
struct Info : public llarp::IBEncodeMessage
{
llarp::PubKey enckey;
llarp::PubKey signkey;
uint64_t version = 0;
VanityNonce vanity;
/// calculate our address
void
CalculateAddress(llarp_crypto* c, Address& addr) const;
bool
BEncode(llarp_buffer_t* buf) const;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
};
// private keys
struct Identity : public llarp::IBEncodeMessage
{
llarp::SecretKey enckey;
llarp::SecretKey signkey;
uint64_t version = 0;
VanityNonce vanity;
// public service info
Info pub;
// regenerate secret keys
void
RegenerateKeys(llarp_crypto* c);
// load from file
bool
LoadFromFile(const std::string& fpath);
};
}; // namespace service
} // namespace llarp
#endif

@ -1,28 +0,0 @@
#ifndef LLARP_SI_H
#define LLARP_SI_H
#include <llarp/crypto.h>
#ifdef __cplusplus
extern "C" {
#endif
struct llarp_service_info
{
llarp_buffer_t name;
llarp_pubkey_t signingkey;
llarp_buffer_t vanity;
};
void
llarp_service_info_hash(struct llarp_service_info *si, llarp_hash_t *h);
bool
llarp_service_info_bencode(struct llarp_serivce_info *si, llarp_buffer_t *buff);
bool
llarp_service_info_bdecode(struct llarp_serivce_info *si, llarp_buffer_t buff);
void
llarp_service_info_free(struct llarp_service_info **si);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,145 @@
#include <arpa/inet.h>
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <llarp/api/client.hpp>
#include <llarp/api/messages.hpp>
#include <llarp/api/parser.hpp>
namespace llarp
{
namespace api
{
struct ClientPImpl
{
ClientPImpl()
{
llarp_ev_loop_alloc(&loop);
worker = llarp_init_same_process_threadpool();
logic = llarp_init_single_process_logic(worker);
}
~ClientPImpl()
{
llarp_ev_loop_free(&loop);
}
static void
HandleRecv(llarp_udp_io* u, const sockaddr* from, const void* buf,
ssize_t sz)
{
static_cast< ClientPImpl* >(u->user)->RecvFrom(from, buf, sz);
}
void
RecvFrom(const sockaddr* from, const void* b, ssize_t sz)
{
if(from->sa_family != AF_INET
|| ((sockaddr_in*)from)->sin_addr.s_addr != apiAddr.sin_addr.s_addr
|| ((sockaddr_in*)from)->sin_port != apiAddr.sin_port)
{
// address missmatch
llarp::Warn("got packet from bad address");
return;
}
llarp_buffer_t buf;
buf.base = (byte_t*)b;
buf.cur = buf.base;
buf.sz = sz;
IMessage* msg = m_MessageParser.ParseMessage(buf);
if(msg)
{
delete msg;
}
else
llarp::Warn("Got Invalid Message");
}
bool
BindDefault()
{
ouraddr.sin_family = AF_INET;
ouraddr.sin_addr.s_addr = INADDR_LOOPBACK;
ouraddr.sin_port = 0;
udp.user = this;
udp.recvfrom = &HandleRecv;
return llarp_ev_add_udp(loop, &udp, (const sockaddr*)&ouraddr) != -1;
}
bool
StartSession(const std::string& addr, uint16_t port)
{
apiAddr.sin_family = AF_INET;
if(inet_pton(AF_INET, addr.c_str(), &apiAddr.sin_addr.s_addr) == -1)
return false;
apiAddr.sin_port = htons(port);
CreateSessionMessage msg;
return SendMessage(&msg);
}
bool
SendMessage(const IMessage* msg)
{
llarp_buffer_t buf;
byte_t tmp[1500];
buf.base = tmp;
buf.cur = buf.base;
buf.sz = sizeof(tmp);
if(msg->BEncode(&buf))
return llarp_ev_udp_sendto(&udp, (const sockaddr*)&apiAddr, buf.base,
buf.sz)
!= -1;
return false;
}
int
Mainloop()
{
llarp_ev_loop_run_single_process(loop, worker, logic);
return 0;
}
llarp_threadpool* worker;
llarp_logic* logic;
llarp_ev_loop* loop;
sockaddr_in ouraddr;
sockaddr_in apiAddr;
llarp_udp_io udp;
MessageParser m_MessageParser;
};
Client::Client() : m_Impl(new ClientPImpl)
{
}
Client::~Client()
{
delete m_Impl;
}
bool
Client::Start(const std::string& url)
{
if(url.find(":") == std::string::npos)
return false;
if(!m_Impl->BindDefault())
return false;
std::string addr = url.substr(0, url.find(":"));
std::string strport = url.substr(url.find(":") + 1);
int port = std::stoi(strport);
if(port == -1)
return false;
return m_Impl->StartSession(addr, port);
}
int
Client::Mainloop()
{
return m_Impl->Mainloop();
}
} // namespace api
} // namespace llarp

@ -0,0 +1,18 @@
#include <list>
#include <llarp/api/messages.hpp>
#include <llarp/encrypted.hpp>
#include <string>
namespace llarp
{
namespace api
{
bool
CreateSessionMessage::DecodeParams(llarp_buffer_t *buf)
{
std::list< llarp::Encrypted > params;
return BEncodeReadList(params, buf);
}
} // namespace api
} // namespace llarp

@ -0,0 +1,109 @@
#include <llarp/api/messages.hpp>
namespace llarp
{
namespace api
{
bool
IMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictString("F", FunctionName(), buf))
return false;
if(!BEncodeWriteDictInt(buf, "I", sessionID))
return false;
if(!BEncodeWriteDictInt(buf, "M", msgID))
return false;
if(!BEncodeWriteDictBEncodeList("P", GetParams(), buf))
return false;
if(!BEncodeWriteDictEntry("Z", hash, buf))
return false;
return bencode_end(buf);
}
bool
IMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
{
if(llarp_buffer_eq(key, "P"))
{
return DecodeParams(val);
}
bool read = false;
if(!BEncodeMaybeReadDictInt("I", sessionID, read, key, val))
return false;
if(!BEncodeMaybeReadDictInt("M", msgID, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("Z", hash, read, key, val))
return false;
return read;
}
bool
IMessage::IsWellFormed(llarp_crypto* crypto, const std::string& password)
{
// hash password
llarp::ShortHash secret;
llarp_buffer_t passbuf;
passbuf.base = (byte_t*)password.c_str();
passbuf.cur = passbuf.base;
passbuf.sz = password.size();
crypto->shorthash(secret, passbuf);
llarp::ShortHash digest, tmpHash;
// save hash
tmpHash = hash;
// zero hash
hash.Zero();
// bencode
byte_t tmp[1500];
llarp_buffer_t buf;
buf.base = tmp;
buf.cur = buf.base;
buf.sz = sizeof(tmp);
if(!BEncode(&buf))
return false;
// rewind buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// calculate message auth
crypto->hmac(digest, buf, secret);
// restore hash
hash = tmpHash;
return tmpHash == digest;
}
void
IMessage::CalculateHash(llarp_crypto* crypto, const std::string& password)
{
// hash password
llarp::ShortHash secret;
llarp_buffer_t passbuf;
passbuf.base = (byte_t*)password.c_str();
passbuf.cur = passbuf.base;
passbuf.sz = password.size();
crypto->shorthash(secret, passbuf);
llarp::ShortHash digest;
// zero hash
hash.Zero();
// bencode
byte_t tmp[1500];
llarp_buffer_t buf;
buf.base = tmp;
buf.cur = buf.base;
buf.sz = sizeof(tmp);
if(BEncode(&buf))
{
// rewind buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// calculate message auth
crypto->hmac(hash, buf, secret);
}
}
} // namespace api
} // namespace llarp

@ -0,0 +1,60 @@
#include <functional>
#include <llarp/api/parser.hpp>
#include <map>
namespace llarp
{
namespace api
{
std::map< std::string, std::function< IMessage*() > > funcmap = {
{"CreateSession", []() { return new CreateSessionMessage; }},
};
MessageParser::MessageParser()
{
r.user = this;
r.on_key = &OnKey;
}
bool
MessageParser::OnKey(dict_reader* r, llarp_buffer_t* key)
{
MessageParser* self = static_cast< MessageParser* >(r->user);
if(self->msg == nullptr && key == nullptr) // empty message
return false;
if(self->msg == nullptr && key)
{
// first message, function name
if(!llarp_buffer_eq(*key, "f"))
return false;
llarp_buffer_t strbuf;
if(!bencode_read_string(r->buffer, &strbuf))
return false;
std::string funcname((char*)strbuf.cur, strbuf.sz);
auto itr = funcmap.find(funcname);
if(itr == funcmap.end())
return false;
self->msg = itr->second();
return true;
}
else if(self->msg && key)
{
return self->msg->DecodeKey(*key, r->buffer);
}
else if(self->msg && key == nullptr)
{
return true;
}
return false;
}
IMessage*
MessageParser::ParseMessage(llarp_buffer_t buf)
{
if(bencode_read_dict(&buf, &r))
return msg;
return nullptr;
}
} // namespace api
} // namespace llarp

@ -1397,7 +1397,7 @@ namespace iwp
UnmapAddr(addr);
session *s = static_cast< session * >(itr->second.impl);
s->done();
m_sessions.erase(itr);
m_sessions.erase(addr);
if(s->frames)
{
llarp::Warn("session has ", s->frames,

@ -428,7 +428,7 @@ llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
auto itr = n->entries.begin();
if(sz > 1)
{
auto idx = rand() % (sz - 1);
auto idx = rand() % sz;
std::advance(itr, idx);
}
if(memcmp(prev->pubkey, itr->second.pubkey, PUBKEYSIZE) == 0)
@ -442,7 +442,7 @@ llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
auto itr = n->entries.begin();
if(sz > 1)
{
auto idx = rand() % (sz - 1);
auto idx = rand() % sz;
std::advance(itr, idx);
}
llarp_rc_copy(result, &itr->second);

@ -75,12 +75,11 @@ namespace llarp
MapGet(Map_t& map, const Key_t& k, CheckValue_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto itr = map.second.find(k);
while(itr != map.second.end())
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
{
if(check(itr->second))
return itr->second;
++itr;
if(check(i->second))
return i->second;
}
return nullptr;
}
@ -90,12 +89,11 @@ namespace llarp
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto itr = map.second.find(k);
while(itr != map.second.end())
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
{
if(check(itr->second))
if(check(i->second))
return true;
++itr;
}
return false;
}
@ -108,40 +106,43 @@ namespace llarp
map.second.emplace(k, v);
}
template < typename Map_t, typename Visit_t >
void
MapIter(Map_t& map, Visit_t v)
{
std::unique_lock< std::mutex > lock(map.first);
for(const auto& item : map.second)
v(item);
}
template < typename Map_t, typename Key_t, typename Check_t >
void
MapDel(Map_t& map, const Key_t& k, Check_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto itr = map.second.find(k);
while(itr != map.second.end())
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second;)
{
if(check(itr->second))
itr = map.second.erase(itr);
if(check(i->second))
i = map.second.erase(i);
else
++itr;
++i;
}
}
void
PathContext::AddOwnPath(Path* path)
{
// FIXME: pathID was split into txID/rxID
llarp::Error("Path::AddOwnPath - pathID was split into txID/rxID, not yet implemented");
//MapPut(m_OurPaths, path->PathID(), path);
MapPut(m_OurPaths, path->TXID(), path);
MapPut(m_OurPaths, path->RXID(), path);
}
bool
PathContext::HasTransitHop(const TransitHopInfo& info)
{
// FIXME: pathID was split into txID/rxID
llarp::Error("Path::HasTransitHop - pathID was split into txID/rxID, not yet implemented");
return false;
/*
return MapHas(m_TransitPaths, info.pathID, [info](TransitHop* hop) -> bool {
return MapHas(m_TransitPaths, info.txID, [info](TransitHop* hop) -> bool {
return info == hop->info;
});
*/
}
IHopHandler*
@ -152,11 +153,20 @@ namespace llarp
});
if(own)
return own;
return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool {
return hop->info.upstream == remote;
});
}
IHopHandler*
PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id)
{
return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool {
return hop->info.downstream == remote;
});
}
const byte_t*
PathContext::OurRouterID() const
{
@ -207,6 +217,12 @@ namespace llarp
for(size_t idx = 0; idx < h->numHops; ++idx)
{
llarp_rc_copy(&hops[idx].router, &h->hops[idx].router);
hops[idx].txID.Randomize();
hops[idx].rxID.Randomize();
}
for(size_t idx = (h->numHops - 1); idx > 0; --idx)
{
hops[idx].txID = hops[idx - 1].rxID;
}
}
@ -239,10 +255,7 @@ namespace llarp
RelayUpstreamMessage* msg = new RelayUpstreamMessage;
msg->X = buf;
msg->Y = Y;
// FIXME: pathID was split into txID/rxID, is RXID correct here?
llarp::Info("Path::HandleUpstream using RXID");
msg->pathid = RXID();
msg->pathid.data_l()[1] = 0;
msg->pathid = TXID();
return r->SendToOrQueue(Upstream(), msg);
}
@ -256,22 +269,28 @@ namespace llarp
Path::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{
int idx = hops.size() - 1;
while(idx >= 0)
for(const auto& hop : hops)
{
r->crypto.xchacha20(buf, hops[idx].shared, Y);
if(idx)
idx--;
else
break;
r->crypto.xchacha20(buf, hop.shared, Y);
}
return HandleRoutingMessage(buf, r);
}
bool
Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r)
Path::HandleHiddenServiceData(llarp_buffer_t buf)
{
// TODO: implement me
return false;
}
bool
Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r)
{
if(!m_InboundMessageParser.ParseMessageBuffer(buf, this))
{
llarp::Warn("Failed to parse inbound routing message");
return false;
}
return true;
}

@ -47,10 +47,9 @@ namespace llarp
abort();
return;
}
++ctx->idx;
bool isFarthestHop = ctx->idx == ctx->path->hops.size() - 1;
bool isFarthestHop = ctx->idx == ctx->path->hops.size();
if(isFarthestHop)
{
@ -64,8 +63,8 @@ namespace llarp
// build record
LR_CommitRecord record;
record.version = LLARP_PROTO_VERSION;
// FIXME: pathID was split into txID/rxID
//record.pathid = hop.pathID;
record.txid = hop.txID;
record.rxid = hop.rxID;
record.tunnelNonce = hop.nonce;
record.nextHop = hop.upstream;
record.commkey = llarp::seckey_topublic(hop.commkey);

@ -87,16 +87,14 @@ namespace llarp
bool
RelayDownstreamMessage::HandleMessage(llarp_router *router) const
{
PathID_t id = pathid;
id.data_l()[0] = 0;
auto path = router->paths.GetByUpstream(remote, id);
auto path = router->paths.GetByUpstream(remote, pathid);
if(path)
{
return path->HandleDownstream(X.Buffer(), Y, router);
}
else
{
llarp::Warn("No such path upstream=", remote, " pathid=", id);
llarp::Warn("No such path upstream=", remote, " pathid=", pathid);
}
return false;
}

@ -639,14 +639,16 @@ llarp_router::Run()
// initialize as service node
InitServiceNode();
// immediate connect all for service node
auto delay = rand() % 100;
llarp_logic_call_later(logic, {static_cast<uint64_t>(delay), this, &ConnectAll});
uint64_t delay = rand() % 100;
llarp_logic_call_later(logic, {delay, this, &ConnectAll});
//llarp_logic_call_later(logic, {static_cast<uint64_t>(delay), this, &ConnectAll});
}
else
{
// delayed connect all for clients
auto delay = ((rand() % 10) * 500) + 1000;
llarp_logic_call_later(logic, {static_cast<uint64_t>(delay), this, &ConnectAll});
uint64_t delay = ((rand() % 10) * 500) + 1000;
llarp_logic_call_later(logic, {delay, this, &ConnectAll});
//llarp_logic_call_later(logic, {static_cast<uint64_t>(delay), this, &ConnectAll});
}
llarp::PubKey ourPubkey = pubkey();

@ -0,0 +1,69 @@
#include <llarp/messages/path_confirm.hpp>
#include <llarp/routing/message.hpp>
namespace llarp
{
namespace routing
{
InboundMessageParser::InboundMessageParser()
{
reader.user = this;
reader.on_key = &OnKey;
firstKey = false;
}
bool
InboundMessageParser::OnKey(dict_reader* r, llarp_buffer_t* key)
{
InboundMessageParser* self =
static_cast< InboundMessageParser* >(r->user);
if(key == nullptr && self->firstKey)
{
// empty dict
return false;
}
if(!key)
return true;
if(self->firstKey)
{
llarp_buffer_t strbuf;
if(!llarp_buffer_eq(*key, "A"))
return false;
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != 1)
return false;
switch(*strbuf.cur)
{
case 'P':
self->msg = new PathConfirmMessage;
break;
default:
llarp::Error("invalid routing message id: ", *strbuf.cur);
}
self->firstKey = false;
return self->msg != nullptr;
}
else
{
return self->msg->DecodeKey(*key, r->buffer);
}
}
bool
InboundMessageParser::ParseMessageBuffer(llarp_buffer_t buf,
IMessageHandler* h)
{
bool result = false;
msg = nullptr;
firstKey = true;
if(bencode_read_dict(&buf, &reader))
{
result = msg->HandleMessage(h);
delete msg;
}
return result;
}
} // namespace routing
} // namespace llarp

@ -1,16 +1,32 @@
#include <llarp/time.h>
#include <llarp/bencode.hpp>
#include <llarp/messages/path_confirm.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
PathConfirmMessage::PathConfirmMessage() : pathLifetime(0), pathCreated(0)
{
}
PathConfirmMessage::PathConfirmMessage(uint64_t lifetime)
: pathLifetime(lifetime), pathCreated(llarp_time_now_ms())
{
}
bool
PathConfirmMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("L", pathLifetime, read, key, val))
return false;
if(!BEncodeMaybeReadDictInt("S", pathCreated, read, key, val))
return false;
return read;
}
bool
PathConfirmMessage::BEncode(llarp_buffer_t* buf) const
{
@ -26,14 +42,10 @@ namespace llarp
}
bool
PathConfirmMessage::BDecode(llarp_buffer_t* buf)
{
return false;
}
bool
PathConfirmMessage::HandleMessage(llarp_router* r) const
PathConfirmMessage::HandleMessage(IMessageHandler* h) const
{
llarp::Info("got path confirm created=", pathCreated,
" lifetime=", pathLifetime);
return true;
}

@ -0,0 +1,11 @@
#include <llarp/messages/path_latency.hpp>
namespace llarp
{
namespace routing
{
PathLatencyMessage::PathLatencyMessage()
{
}
} // namespace routing
} // namespace llarp

@ -0,0 +1 @@
#include <llarp/service.hpp>

@ -11,14 +11,19 @@ namespace llarp
}
TransitHopInfo::TransitHopInfo(const TransitHopInfo& other)
: upstream(other.upstream)
: txID(other.txID)
, rxID(other.rxID)
, upstream(other.upstream)
, downstream(other.downstream)
{
}
TransitHopInfo::TransitHopInfo(const RouterID& down,
const LR_CommitRecord& record)
: upstream(record.nextHop), downstream(down)
: txID(record.txid)
, rxID(record.rxid)
, upstream(record.nextHop)
, downstream(down)
{
}
@ -55,7 +60,7 @@ namespace llarp
llarp_router* r)
{
RelayDownstreamMessage* msg = new RelayDownstreamMessage;
msg->pathid = info.rxID;
msg->pathid = info.txID;
msg->Y = Y;
r->crypto.xchacha20(buf, pathKey, Y);
@ -70,7 +75,7 @@ namespace llarp
llarp_router* r)
{
RelayUpstreamMessage* msg = new RelayUpstreamMessage;
msg->pathid = info.txID;
msg->pathid = info.rxID;
msg->Y = Y;
r->crypto.xchacha20(buf, pathKey, Y);

@ -0,0 +1,27 @@
#include <gtest/gtest.h>
#include <llarp/api/messages.hpp>
class APITest : public ::testing::Test
{
public:
llarp_crypto crypto;
std::string apiPassword = "password";
APITest()
{
llarp_crypto_libsodium_init(&crypto);
}
~APITest()
{
}
};
TEST_F(APITest, TestMessageWellFormed)
{
llarp::api::CreateSessionMessage msg;
msg.msgID = 0;
msg.sessionID = 12345;
msg.CalculateHash(&crypto, apiPassword);
llarp::Info("msghash=", msg.hash);
ASSERT_TRUE(msg.IsWellFormed(&crypto, apiPassword));
};
Loading…
Cancel
Save