mirror of https://github.com/oxen-io/lokinet
Merge branch 'master' of https://github.com/loki-project/loki-network
This commit is contained in:
commit
9f33edeed0
132
CMakeLists.txt
132
CMakeLists.txt
|
@ -19,7 +19,7 @@ else()
|
|||
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
|
||||
endif()
|
||||
|
||||
option(HAVE_CXX17_FILESYSTEM "Enable if your C++ compiler and runtime library implements std::[experimental::]filesystem" OFF)
|
||||
option(HAVE_CXX17_FILESYSTEM "Disable if your C++ compiler and runtime library lacks std::[experimental::]filesystem" ON)
|
||||
|
||||
if(COMPILER_SUPPORTS_CXX11 AND NOT HAVE_CXX17_FILESYSTEM)
|
||||
add_cxxflags("-std=c++11")
|
||||
|
@ -34,6 +34,8 @@ else()
|
|||
message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 or C++17 support. Please use a different C++ compiler.")
|
||||
endif()
|
||||
|
||||
add_cxxflags("-fpermissive")
|
||||
|
||||
if(DEBIAN)
|
||||
add_definitions(-DDEBIAN)
|
||||
endif()
|
||||
|
@ -144,7 +146,14 @@ else()
|
|||
)
|
||||
endif()
|
||||
|
||||
set(LIBS ${SODIUM_LIB} ${THREAD_LIB})
|
||||
if(JEMALLOC)
|
||||
set(MALLOC_LIB jemalloc)
|
||||
endif()
|
||||
|
||||
set(LIBS ${SODIUM_LIB} ${THREAD_LIB} ${MALLOC_LIB})
|
||||
if(HAVE_CXX17_FILESYSTEM)
|
||||
set(LIBS ${LIBS} stdc++fs)
|
||||
endif()
|
||||
|
||||
set(LIB lokinet)
|
||||
set(SHARED_LIB ${LIB})
|
||||
|
@ -155,7 +164,8 @@ set(TT_ROOT vendor/libtuntap-master)
|
|||
add_definitions(-D${CMAKE_SYSTEM_NAME})
|
||||
|
||||
if (UNIX)
|
||||
add_definitions(-DUNIX)
|
||||
add_definitions(-DUNIX)
|
||||
add_definitions(-DPOSIX)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
|
@ -179,6 +189,7 @@ if(UNIX)
|
|||
elseif(WIN32 OR MINGW)
|
||||
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-windows.c)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-DWIN32)
|
||||
else()
|
||||
message(FATAL_ERROR "What operating system _are_ you building on/for?")
|
||||
endif(UNIX)
|
||||
|
@ -189,7 +200,7 @@ set(LIBTUNTAP_SRC_BASE
|
|||
${TT_ROOT}/tuntap_log.cpp
|
||||
${LIBTUNTAP_IMPL})
|
||||
if (UNIX)
|
||||
set(LIBTUNTAP_SRC
|
||||
set(LIBTUNTAP_SRC
|
||||
${TT_ROOT}/tuntap-unix.c
|
||||
${LIBTUNTAP_SRC_BASE})
|
||||
endif()
|
||||
|
@ -250,7 +261,7 @@ set(LIB_PLATFORM_SRC
|
|||
${ANDROID_PLATFORM_SRC}
|
||||
# process isolation implementation
|
||||
${ISOLATE_PROC_SRC}
|
||||
# tun
|
||||
# tun
|
||||
${LIBTUNTAP_SRC}
|
||||
# win32 inline procs
|
||||
llarp/win32_inet.c
|
||||
|
@ -305,7 +316,24 @@ set(NTRU_SRC
|
|||
crypto/libntrup/src/ntru.cpp
|
||||
)
|
||||
|
||||
set(LIB_SRC
|
||||
|
||||
set(UTP_SRC
|
||||
libutp/utp_callbacks.cpp
|
||||
libutp/utp_utils.cpp
|
||||
libutp/utp_internal.cpp
|
||||
libutp/utp_api.cpp
|
||||
libutp/utp_packedsockaddr.cpp
|
||||
libutp/utp_hash.cpp
|
||||
)
|
||||
|
||||
|
||||
if(WIN32)
|
||||
set(UTP_SRC ${UTP_SRC} libutp/libutp_inet_ntop.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
set(LIB_SRC
|
||||
${UTP_SRC}
|
||||
${NTRU_SRC}
|
||||
llarp/address_info.cpp
|
||||
llarp/bencode.cpp
|
||||
|
@ -331,7 +359,6 @@ set(LIB_SRC
|
|||
llarp/pathbuilder.cpp
|
||||
llarp/pathset.cpp
|
||||
llarp/proofofwork.cpp
|
||||
llarp/relay_ack.cpp
|
||||
llarp/relay_commit.cpp
|
||||
llarp/relay_up_down.cpp
|
||||
llarp/router_contact.cpp
|
||||
|
@ -346,16 +373,11 @@ set(LIB_SRC
|
|||
llarp/dht/find_router.cpp
|
||||
llarp/dht/got_intro.cpp
|
||||
llarp/dht/got_router.cpp
|
||||
llarp/dht/search_job.cpp
|
||||
llarp/dht/publish_intro.cpp
|
||||
llarp/handlers/tun.cpp
|
||||
llarp/iwp/frame_header.cpp
|
||||
llarp/iwp/frame_state.cpp
|
||||
llarp/iwp/session.cpp
|
||||
llarp/iwp/server.cpp
|
||||
llarp/iwp/transit_message.cpp
|
||||
llarp/iwp/xmit.cpp
|
||||
llarp/link/encoder.cpp
|
||||
llarp/link/curvecp.cpp
|
||||
llarp/link/server.cpp
|
||||
llarp/link/utp.cpp
|
||||
llarp/routing/dht_message.cpp
|
||||
llarp/routing/message_parser.cpp
|
||||
llarp/routing/path_confirm.cpp
|
||||
|
@ -371,6 +393,10 @@ set(LIB_SRC
|
|||
|
||||
)
|
||||
|
||||
set(RC_SRC
|
||||
daemon/rcutil.cpp
|
||||
)
|
||||
|
||||
set(DNS_SRC
|
||||
llarp/dns.cpp
|
||||
llarp/dns_iptracker.cpp
|
||||
|
@ -399,7 +425,7 @@ set(CLIENT_SRC
|
|||
client/main.cpp
|
||||
)
|
||||
|
||||
set(ALL_SRC ${CLIENT_SRC} daemon/rcutil.cpp ${EXE_SRC} ${DNS_SRC} ${LIB_PLATFORM_SRC} ${LIB_SRC} ${TEST_SRC} ${CPP_BACKPORT_SRC})
|
||||
set(ALL_SRC ${CLIENT_SRC} ${RC_SRC} ${EXE_SRC} ${DNS_SRC} ${LIB_PLATFORM_SRC} ${LIB_SRC} ${TEST_SRC} ${CPP_BACKPORT_SRC})
|
||||
|
||||
foreach(F ${ALL_SRC})
|
||||
set_source_files_properties(${F} PROPERTIES COMPILE_FLAGS -DLOG_TAG=\\\"${F}\\\")
|
||||
|
@ -408,11 +434,15 @@ endforeach(F)
|
|||
set(LIB lokinet)
|
||||
set(SHARED_LIB ${LIB})
|
||||
set(STATIC_LIB ${LIB}-static)
|
||||
set(BACKPORT_LIB ${LIB}-backport)
|
||||
set(PLATFORM_LIB ${LIB}-platform)
|
||||
set(ANDROID_LIB ${LIB}android)
|
||||
|
||||
# TODO: exclude this from includes and expose stuff properly for rcutil
|
||||
include_directories(llarp)
|
||||
include_directories(include)
|
||||
include_directories(vendor/cppbackport-master/lib)
|
||||
# Neuro Linux box hack:
|
||||
include_directories(/usr/local/include)
|
||||
include_directories(${sodium_INCLUDE_DIR})
|
||||
|
||||
|
@ -421,15 +451,19 @@ include_directories(contrib/msc/include)
|
|||
link_directories(contrib/msc/lib)
|
||||
endif()
|
||||
|
||||
set(RC_EXE rcutil)
|
||||
set(DNS_EXE dns)
|
||||
|
||||
|
||||
if(SHADOW)
|
||||
add_shadow_plugin(shadow-plugin-${SHARED_LIB} ${EXE_SRC} ${LIB_SRC} ${LIB_PLATFORM_SRC} ${CPP_BACKPORT_SRC})
|
||||
target_link_libraries(shadow-plugin-${SHARED_LIB} ${LIBS})
|
||||
install(TARGETS shadow-plugin-${SHARED_LIB} DESTINATION plugins)
|
||||
else()
|
||||
add_executable(rcutil daemon/rcutil.cpp)
|
||||
add_executable(${RC_EXE} ${RC_SRC})
|
||||
add_executable(${EXE} ${EXE_SRC})
|
||||
add_executable(${CLIENT_EXE} ${CLIENT_SRC})
|
||||
add_executable(dns ${DNS_SRC})
|
||||
add_executable(${DNS_EXE} ${DNS_SRC})
|
||||
|
||||
|
||||
if(NOT WIN32)
|
||||
|
@ -441,57 +475,57 @@ else()
|
|||
if(WITH_STATIC)
|
||||
add_library(${STATIC_LIB} STATIC ${LIB_SRC})
|
||||
if(NOT HAVE_CXX17_FILESYSTEM)
|
||||
add_library(backport-static STATIC ${CPP_BACKPORT_SRC})
|
||||
add_library(${BACKPORT_LIB} STATIC ${CPP_BACKPORT_SRC})
|
||||
endif(NOT HAVE_CXX17_FILESYSTEM)
|
||||
add_library(llarpplatform-static STATIC ${LIB_PLATFORM_SRC})
|
||||
target_link_libraries(llarpplatform-static ${THREAD_LIB})
|
||||
add_library(${PLATFORM_LIB} STATIC ${LIB_PLATFORM_SRC})
|
||||
target_link_libraries(${PLATFORM_LIB} ${THREAD_LIB})
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
target_link_libraries(llarpplatform-static -lcap)
|
||||
target_link_libraries(${PLATFORM_LIB} -lcap)
|
||||
endif()
|
||||
if(NOT HAVE_CXX17_FILESYSTEM)
|
||||
target_link_libraries(${STATIC_LIB} ${LIBS} backport-static llarpplatform-static)
|
||||
target_link_libraries(${STATIC_LIB} ${LIBS} ${PLATFORM_LIB} ${BACKPORT_LIB})
|
||||
else()
|
||||
target_link_libraries(${STATIC_LIB} ${LIBS} llarpplatform-static)
|
||||
target_link_libraries(${STATIC_LIB} ${LIBS} ${PLATFORM_LIB})
|
||||
endif(NOT HAVE_CXX17_FILESYSTEM)
|
||||
if(NOT WITH_SHARED)
|
||||
if(NOT HAVE_CXX17_FILESYSTEM)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
|
||||
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
|
||||
if (MINGW)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
elseif(WIN32)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
|
||||
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
endif(MINGW)
|
||||
else()
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
|
||||
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
|
||||
if (MINGW)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
elseif(WIN32)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
|
||||
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
endif(MINGW)
|
||||
endif(NOT HAVE_CXX17_FILESYSTEM)
|
||||
if (MINGW)
|
||||
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
elseif(WIN32)
|
||||
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB} ws2_32 iphlpapi)
|
||||
endif(MINGW)
|
||||
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB})
|
||||
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB})
|
||||
endif(NOT WITH_SHARED)
|
||||
endif(WITH_STATIC)
|
||||
if(ANDROID)
|
||||
add_library(lokinetandroid SHARED jni/lokinet_android.cpp)
|
||||
target_link_libraries(lokinetandroid ${STATIC_LIB} ${LIBS} log)
|
||||
add_library(${ANDROID_LIB} SHARED jni/lokinet_android.cpp)
|
||||
target_link_libraries(${ANDROID_LIB} ${STATIC_LIB} ${LIBS} log)
|
||||
endif()
|
||||
|
||||
if(WITH_SHARED)
|
||||
|
@ -506,7 +540,7 @@ else()
|
|||
endif(MINGW)
|
||||
target_link_libraries(${SHARED_LIB} ${LIBS} ${THREAD_LIB})
|
||||
target_link_libraries(${EXE} ${SHARED_LIB})
|
||||
target_link_libraries(rcutil ${SHARED_LIB})
|
||||
target_link_libraries(dns ${SHARED_LIB} ${THREAD_LIB})
|
||||
target_link_libraries(${RC_EXE} ${SHARED_LIB})
|
||||
target_link_libraries(${DNS_EXE} ${SHARED_LIB} ${THREAD_LIB})
|
||||
endif(WITH_SHARED)
|
||||
endif(SHADOW)
|
||||
|
|
2
Makefile
2
Makefile
|
@ -43,7 +43,7 @@ clean:
|
|||
rm -f *.a *.so
|
||||
|
||||
debug-configure:
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
|
||||
|
||||
release-configure: clean
|
||||
cmake -GNinja -DSTATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release -DRELEASE_MOTTO="$(shell cat motto.txt)" -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
|
||||
|
|
|
@ -18,6 +18,7 @@ def clientNodeName(id): return 'client-node-%03d' % id
|
|||
|
||||
def main():
|
||||
ap = AP()
|
||||
ap.add_argument('--valgrind', type=bool, default=False)
|
||||
ap.add_argument('--dir', type=str, default='testnet_tmp')
|
||||
ap.add_argument('--svc', type=int, default=20,
|
||||
help='number of service nodes')
|
||||
|
@ -31,6 +32,11 @@ def main():
|
|||
|
||||
args = ap.parse_args()
|
||||
|
||||
if args.valgrind:
|
||||
exe = 'valgrind {}'.format(args.bin)
|
||||
else:
|
||||
exe = args.bin
|
||||
|
||||
basedir = os.path.abspath(args.dir)
|
||||
|
||||
for nodeid in range(args.svc):
|
||||
|
@ -47,12 +53,13 @@ def main():
|
|||
'dir': 'netdb'
|
||||
}
|
||||
config['connect'] = {}
|
||||
for otherid in range(args.svc):
|
||||
if otherid != nodeid:
|
||||
name = svcNodeName(otherid)
|
||||
config['connect'][name] = os.path.join(
|
||||
basedir, name, 'rc.signed')
|
||||
|
||||
for otherid in range(args.connect):
|
||||
otherid = (nodeid + otherid) % args.svc
|
||||
name = svcNodeName(otherid)
|
||||
config['connect'][name] = os.path.join(
|
||||
basedir, name, 'rc.signed')
|
||||
|
||||
d = os.path.join(args.dir, svcNodeName(nodeid))
|
||||
if not os.path.exists(d):
|
||||
os.mkdir(d)
|
||||
|
@ -106,7 +113,7 @@ stdout_logfile={}/svc-node-%(process_num)03d-log.txt
|
|||
stdout_logfile_maxbytes=0
|
||||
process_name = svc-node-%(process_num)03d
|
||||
numprocs = {}
|
||||
'''.format(os.path.join(args.dir, 'svc-node-%(process_num)03d'), args.bin, args.dir, args.svc))
|
||||
'''.format(os.path.join(args.dir, 'svc-node-%(process_num)03d'), exe, args.dir, args.svc))
|
||||
f.write('''[program:client-node]
|
||||
directory = {}
|
||||
command = {}
|
||||
|
@ -117,7 +124,7 @@ stdout_logfile={}/client-node-%(process_num)03d-log.txt
|
|||
stdout_logfile_maxbytes=0
|
||||
process_name = client-node-%(process_num)03d
|
||||
numprocs = {}
|
||||
'''.format(os.path.join(args.dir, 'client-node-%(process_num)03d'),args.bin, args.dir, args.clients))
|
||||
'''.format(os.path.join(args.dir, 'client-node-%(process_num)03d'), exe, args.dir, args.clients))
|
||||
f.write('[supervisord]\ndirectory=.\n')
|
||||
|
||||
|
||||
|
|
|
@ -186,7 +186,9 @@ hookChecker(std::string name, const struct sockaddr *from,
|
|||
job->iterative = true;
|
||||
job->found = false;
|
||||
job->hook = &HandleDHTLocate;
|
||||
llarp_rc_new(&job->result);
|
||||
|
||||
// Disable for RC refactor
|
||||
//llarp_rc_new(&job->result);
|
||||
memcpy(job->target, binaryPK, PUBKEYSIZE); // set job's target
|
||||
|
||||
// llarp_dht_lookup_router(ctx->router->dht, job);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <signal.h>
|
||||
#include "logger.hpp"
|
||||
|
||||
#include <llarp/router_contact.h>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/time.h>
|
||||
|
||||
#include <fstream>
|
||||
|
@ -30,39 +30,14 @@ handle_signal(int sig)
|
|||
#define TESTNET 0
|
||||
#endif
|
||||
|
||||
bool
|
||||
printNode(struct llarp_nodedb_iter *iter)
|
||||
{
|
||||
char ftmp[68] = {0};
|
||||
const char *hexname =
|
||||
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(iter->rc->pubkey, ftmp);
|
||||
|
||||
printf("[%zu]=>[%s]\n", iter->index, hexname);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aiLister(struct llarp_ai_list_iter *request, struct llarp_ai *addr)
|
||||
{
|
||||
static size_t count = 0;
|
||||
count++;
|
||||
llarp::Addr a(*addr);
|
||||
std::cout << "AddressInfo " << count << ": " << a << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
displayRC(llarp_rc *rc)
|
||||
displayRC(const llarp::RouterContact &rc)
|
||||
{
|
||||
char ftmp[68] = {0};
|
||||
const char *hexPubSigKey =
|
||||
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(rc->pubkey, ftmp);
|
||||
printf("PubSigKey [%s]\n", hexPubSigKey);
|
||||
|
||||
struct llarp_ai_list_iter iter;
|
||||
// iter.user
|
||||
iter.visit = &aiLister;
|
||||
llarp_ai_list_iterate(rc->addrs, &iter);
|
||||
std::cout << rc.pubkey << std::endl;
|
||||
for(const auto &addr : rc.addrs)
|
||||
{
|
||||
std::cout << "AddressInfo: " << addr << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// fwd declr
|
||||
|
@ -75,7 +50,7 @@ HandleDHTLocate(llarp_router_lookup_job *job)
|
|||
if(job->found)
|
||||
{
|
||||
// save to nodedb?
|
||||
displayRC(&job->result);
|
||||
displayRC(job->result);
|
||||
}
|
||||
// shutdown router
|
||||
|
||||
|
@ -144,6 +119,8 @@ main(int argc, char *argv[])
|
|||
conffname = defaultConfName;
|
||||
char *rcfname = nullptr;
|
||||
char *nodesdir = nullptr;
|
||||
|
||||
llarp::RouterContact rc;
|
||||
while(1)
|
||||
{
|
||||
static struct option long_options[] = {
|
||||
|
@ -266,95 +243,106 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
#undef MIN
|
||||
if(!haveRequiredOptions)
|
||||
{
|
||||
llarp::LogError("Parameters dont all have their required parameters.\n");
|
||||
return 0;
|
||||
}
|
||||
printf("parsed options\n");
|
||||
if(!genMode && !updMode && !listMode && !importMode && !exportMode
|
||||
&& !locateMode && !localMode && !readMode && !findMode && !toB32Mode
|
||||
&& !toHexMode)
|
||||
{
|
||||
llarp::LogError(
|
||||
"I don't know what to do, no generate or update parameter\n");
|
||||
return 0;
|
||||
}
|
||||
if(!haveRequiredOptions)
|
||||
{
|
||||
llarp::LogError("Parameters dont all have their required parameters.\n");
|
||||
return 0;
|
||||
}
|
||||
//printf("parsed options\n");
|
||||
|
||||
if(!genMode && !updMode && !listMode && !importMode && !exportMode
|
||||
&& !locateMode && !localMode && !readMode && !findMode && !toB32Mode
|
||||
&& !toHexMode)
|
||||
{
|
||||
llarp::LogError(
|
||||
"I don't know what to do, no generate or update parameter\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ctx = llarp_main_init(conffname, !TESTNET);
|
||||
if(!ctx)
|
||||
{
|
||||
llarp::LogError("Cant set up context");
|
||||
return 1;
|
||||
}
|
||||
signal(SIGINT, handle_signal);
|
||||
|
||||
llarp::RouterContact tmp;
|
||||
|
||||
ctx = llarp_main_init(conffname, !TESTNET);
|
||||
if(!ctx)
|
||||
{
|
||||
llarp::LogError("Cant set up context");
|
||||
return 0;
|
||||
}
|
||||
signal(SIGINT, handle_signal);
|
||||
|
||||
llarp_rc tmp;
|
||||
|
||||
if(verifyMode)
|
||||
{
|
||||
llarp_crypto crypto;
|
||||
llarp_crypto_libsodium_init(&crypto);
|
||||
llarp_rc rc;
|
||||
if(!llarp_rc_read(rcfname, &rc))
|
||||
llarp_crypto_init(&crypto);
|
||||
if(!rc.Read(rcfname))
|
||||
{
|
||||
std::cout << "failed to read " << rcfname << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if(!llarp_rc_verify_sig(&crypto, &rc))
|
||||
if(!rc.VerifySignature(&crypto))
|
||||
{
|
||||
std::cout << rcfname << " has invalid signature" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if(!llarp_rc_is_public_router(&rc))
|
||||
if(!rc.IsPublicRouter())
|
||||
{
|
||||
std::cout << rcfname << " is not a public router";
|
||||
if(llarp_ai_list_size(rc.addrs) == 0)
|
||||
if(rc.addrs.size() == 0)
|
||||
{
|
||||
std::cout << " because it has no public addresses";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
return 1;
|
||||
}
|
||||
llarp::PubKey pubkey(rc.pubkey);
|
||||
llarp::PubKey enckey(rc.enckey);
|
||||
|
||||
std::cout << "router identity and dht routing key: " << pubkey << std::endl;
|
||||
std::cout << "router encryption key: " << enckey << std::endl;
|
||||
std::cout << "router identity and dht routing key: " << rc.pubkey
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "router encryption key: " << rc.enckey << std::endl;
|
||||
|
||||
if(rc.HasNick())
|
||||
std::cout << "router nickname: " << rc.Nick() << std::endl;
|
||||
|
||||
std::cout << "advertised addresses: ";
|
||||
llarp_ai_list_iter a_itr;
|
||||
a_itr.user = nullptr;
|
||||
a_itr.visit = [](llarp_ai_list_iter *, llarp_ai *addrInfo) -> bool {
|
||||
llarp::Addr addr(*addrInfo);
|
||||
std::cout << addr << " ";
|
||||
return true;
|
||||
};
|
||||
llarp_ai_list_iterate(rc.addrs, &a_itr);
|
||||
std::cout << "advertised addresses: " << std::endl;
|
||||
for(const auto &addr : rc.addrs)
|
||||
{
|
||||
std::cout << addr << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "advertised exits: ";
|
||||
|
||||
if(llarp_xi_list_size(rc.exits))
|
||||
if(rc.exits.size())
|
||||
{
|
||||
llarp_xi_list_iter e_itr;
|
||||
e_itr.user = nullptr;
|
||||
e_itr.visit = [](llarp_xi_list_iter *, llarp_xi *xi) -> bool {
|
||||
std::cout << *xi << " ";
|
||||
return true;
|
||||
};
|
||||
llarp_xi_list_iterate(rc.exits, &e_itr);
|
||||
for(const auto &exit : rc.exits)
|
||||
{
|
||||
std::cout << exit << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "none";
|
||||
|
||||
}
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// is this Neuro or Jeff's?
|
||||
// this is the only one...
|
||||
if(listMode)
|
||||
{
|
||||
llarp_crypto crypto;
|
||||
llarp_crypto_init(&crypto);
|
||||
auto nodedb = llarp_nodedb_new(&crypto);
|
||||
llarp_nodedb_iter itr;
|
||||
itr.visit = [](llarp_nodedb_iter *i) -> bool {
|
||||
std::cout << i->rc->pubkey << std::endl;
|
||||
return true;
|
||||
};
|
||||
if(llarp_nodedb_load_dir(nodedb, nodesdir) > 0)
|
||||
llarp_nodedb_iterate_all(nodedb, itr);
|
||||
llarp_nodedb_free(&nodedb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(importMode)
|
||||
{
|
||||
if(rcfname == nullptr)
|
||||
|
@ -363,7 +351,7 @@ main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
llarp_crypto crypto;
|
||||
llarp_crypto_libsodium_init(&crypto);
|
||||
llarp_crypto_init(&crypto);
|
||||
auto nodedb = llarp_nodedb_new(&crypto);
|
||||
if(!llarp_nodedb_ensure_dir(nodesdir))
|
||||
{
|
||||
|
@ -372,46 +360,40 @@ main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
llarp_nodedb_set_dir(nodedb, nodesdir);
|
||||
llarp_rc rc;
|
||||
if(!llarp_rc_read(rcfname, &rc))
|
||||
if(!rc.Read(rcfname))
|
||||
{
|
||||
std::cout << "failed to read " << rcfname << " " << strerror(errno)
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!llarp_rc_verify_sig(&crypto, &rc))
|
||||
if(!rc.VerifySignature(&crypto))
|
||||
{
|
||||
std::cout << rcfname << " has invalid signature" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!llarp_nodedb_put_rc(nodedb, &rc))
|
||||
if(!llarp_nodedb_put_rc(nodedb, rc))
|
||||
{
|
||||
std::cout << "failed to store " << strerror(errno) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "imported " << llarp::PubKey(rc.pubkey) << std::endl;
|
||||
std::cout << "imported " << rc.pubkey << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if(genMode)
|
||||
{
|
||||
printf("Creating [%s]\n", rcfname);
|
||||
// Jeff wanted tmp to be stack created
|
||||
// do we still need to zero it out?
|
||||
llarp_rc_clear(&tmp);
|
||||
// if we zero it out then
|
||||
// allocate fresh pointers that the bencoder can expect to be ready
|
||||
tmp.addrs = llarp_ai_list_new();
|
||||
tmp.exits = llarp_xi_list_new();
|
||||
// set updated timestamp
|
||||
tmp.last_updated = llarp_time_now_ms();
|
||||
rc.last_updated = llarp_time_now_ms();
|
||||
// load longterm identity
|
||||
llarp_crypto crypt;
|
||||
llarp_crypto_libsodium_init(&crypt);
|
||||
llarp_crypto_init(&crypt);
|
||||
|
||||
// which is in daemon.ini config: router.encryption-privkey (defaults
|
||||
// "encryption.key")
|
||||
|
@ -419,59 +401,77 @@ main(int argc, char *argv[])
|
|||
llarp::SecretKey encryption;
|
||||
|
||||
llarp_findOrCreateEncryption(&crypt, encryption_keyfile.string().c_str(),
|
||||
&encryption);
|
||||
encryption);
|
||||
|
||||
llarp_rc_set_pubenckey(&tmp, llarp::seckey_topublic(encryption));
|
||||
rc.enckey = llarp::seckey_topublic(encryption);
|
||||
|
||||
// get identity public sig key
|
||||
fs::path ident_keyfile = "identity.key";
|
||||
byte_t identity[SECKEYSIZE];
|
||||
llarp::SecretKey identity;
|
||||
llarp_findOrCreateIdentity(&crypt, ident_keyfile.string().c_str(),
|
||||
identity);
|
||||
|
||||
llarp_rc_set_pubsigkey(&tmp, llarp::seckey_topublic(identity));
|
||||
rc.pubkey = llarp::seckey_topublic(identity);
|
||||
|
||||
// this causes a segfault
|
||||
llarp_rc_sign(&crypt, identity, &tmp);
|
||||
if(!rc.Sign(&crypt, identity))
|
||||
{
|
||||
std::cout << "failed to sign" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// set filename
|
||||
fs::path our_rc_file = rcfname;
|
||||
// write file
|
||||
llarp_rc_write(&tmp, our_rc_file.string().c_str());
|
||||
rc.Write(our_rc_file.string().c_str());
|
||||
|
||||
//llarp_rc_write(&tmp, our_rc_file.string().c_str());
|
||||
|
||||
// release memory for tmp lists
|
||||
llarp_rc_free(&tmp);
|
||||
//llarp_rc_free(&tmp);
|
||||
}
|
||||
if(updMode)
|
||||
{
|
||||
printf("rcutil.cpp - Loading [%s]\n", rcfname);
|
||||
llarp_rc rc;
|
||||
llarp_rc_clear(&rc);
|
||||
llarp_rc_read(rcfname, &rc);
|
||||
llarp::RouterContact tmp;
|
||||
//llarp_rc_clear(&rc);
|
||||
rc.Clear();
|
||||
// FIXME: new rc api
|
||||
//llarp_rc_read(rcfname, &rc);
|
||||
|
||||
// set updated timestamp
|
||||
rc.last_updated = llarp_time_now_ms();
|
||||
// load longterm identity
|
||||
llarp_crypto crypt;
|
||||
llarp_crypto_libsodium_init(&crypt);
|
||||
|
||||
// no longer used?
|
||||
//llarp_crypto_libsodium_init(&crypt);
|
||||
fs::path ident_keyfile = "identity.key";
|
||||
byte_t identity[SECKEYSIZE];
|
||||
llarp_findOrCreateIdentity(&crypt, ident_keyfile.string().c_str(),
|
||||
identity);
|
||||
|
||||
// FIXME: update RC API
|
||||
// get identity public key
|
||||
const uint8_t *pubkey = llarp::seckey_topublic(identity);
|
||||
llarp_rc_set_pubsigkey(&rc, pubkey);
|
||||
llarp_rc_sign(&crypt, identity, &rc);
|
||||
//const uint8_t *pubkey = llarp::seckey_topublic(identity);
|
||||
|
||||
// FIXME: update RC API
|
||||
//llarp_rc_set_pubsigkey(&rc, pubkey);
|
||||
// // FIXME: update RC API
|
||||
//llarp_rc_sign(&crypt, identity, &rc);
|
||||
|
||||
// set filename
|
||||
fs::path our_rc_file_out = "update_debug.rc";
|
||||
// write file
|
||||
llarp_rc_write(&tmp, our_rc_file_out.string().c_str());
|
||||
// FIXME: update RC API
|
||||
//rc.Write(our_rc_file.string().c_str());
|
||||
//llarp_rc_write(&tmp, our_rc_file_out.string().c_str());
|
||||
}
|
||||
|
||||
if(listMode)
|
||||
{
|
||||
llarp_crypto crypto;
|
||||
llarp_crypto_libsodium_init(&crypto);
|
||||
// no longer used?
|
||||
//llarp_crypto_libsodium_init(&crypto);
|
||||
auto nodedb = llarp_nodedb_new(&crypto);
|
||||
llarp_nodedb_iter itr;
|
||||
itr.visit = [](llarp_nodedb_iter *i) -> bool {
|
||||
|
@ -492,7 +492,7 @@ main(int argc, char *argv[])
|
|||
llarp::HexDecode(rcfname, binaryPK.data());
|
||||
|
||||
llarp::LogInfo("Looking for binary: ", binaryPK);
|
||||
struct llarp_rc *rc = llarp_main_getDatabase(ctx, binaryPK.data());
|
||||
llarp::RouterContact *rc = llarp_main_getDatabase(ctx, binaryPK.data());
|
||||
if(!rc)
|
||||
{
|
||||
llarp::LogError("Can't load RC from database");
|
||||
|
@ -500,7 +500,9 @@ main(int argc, char *argv[])
|
|||
std::string filename(rcfname);
|
||||
filename.append(".signed");
|
||||
llarp::LogInfo("Writing out: ", filename);
|
||||
llarp_rc_write(rc, filename.c_str());
|
||||
// FIXME: update RC API
|
||||
//rc.Write(our_rc_file.string().c_str());
|
||||
//llarp_rc_write(rc, filename.c_str());
|
||||
}
|
||||
if(locateMode)
|
||||
{
|
||||
|
@ -515,7 +517,7 @@ main(int argc, char *argv[])
|
|||
job->iterative = true;
|
||||
job->found = false;
|
||||
job->hook = &HandleDHTLocate;
|
||||
llarp_rc_new(&job->result);
|
||||
//llarp_rc_new(&job->result);
|
||||
memcpy(job->target, binaryPK, PUBKEYSIZE); // set job's target
|
||||
|
||||
// create query DHT request
|
||||
|
@ -552,7 +554,8 @@ main(int argc, char *argv[])
|
|||
llarp::LogInfo("Addr ", addr);
|
||||
llarp::routing::DHTMessage *msg = new llarp::routing::DHTMessage();
|
||||
// uint64_t txid, const llarp::service::Address& addr
|
||||
msg->M.push_back(new llarp::dht::FindIntroMessage(tag, 1));
|
||||
// FIXME: new API?
|
||||
//msg->M.push_back(new llarp::dht::FindIntroMessage(tag, 1));
|
||||
|
||||
// I guess we may need a router to get any replies
|
||||
llarp::LogInfo("Processing");
|
||||
|
@ -561,16 +564,15 @@ main(int argc, char *argv[])
|
|||
}
|
||||
if(localMode)
|
||||
{
|
||||
llarp_rc *rc = llarp_main_getLocalRC(ctx);
|
||||
displayRC(rc);
|
||||
// FIXME: update llarp_main_getLocalRC
|
||||
//llarp::RouterContact *rc = llarp_main_getLocalRC(ctx);
|
||||
//displayRC(rc);
|
||||
}
|
||||
if(readMode)
|
||||
{
|
||||
llarp_rc result;
|
||||
llarp_rc_clear(&result);
|
||||
llarp_rc_read(rcfname, &result);
|
||||
displayRC(&result);
|
||||
if(rc.Read(rcfname))
|
||||
displayRC(rc);
|
||||
}
|
||||
|
||||
if(toB32Mode)
|
||||
{
|
||||
llarp::LogInfo("Converting hex string ", rcfname);
|
||||
|
@ -596,5 +598,5 @@ main(int argc, char *argv[])
|
|||
}
|
||||
// it's a unique_ptr, should clean up itself
|
||||
// llarp_main_free(ctx);
|
||||
return 1; // success
|
||||
return 0; // success
|
||||
}
|
||||
|
|
|
@ -106,6 +106,12 @@ sent in reply to FRCM only
|
|||
V: 0
|
||||
}
|
||||
|
||||
* send a GRCM with R to requesters in all linked transactions
|
||||
* terminate transaction with id T
|
||||
in response to an exploritory FRCM if the target router is not found the form
|
||||
|
||||
{
|
||||
A: "S",
|
||||
N: [list, of, router, publickeys, near, target],
|
||||
R: [],
|
||||
T: transaction_id_uint64,
|
||||
V: 0
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include <llarp/ev.h>
|
||||
#include <llarp/logic.h>
|
||||
#include <llarp/mem.h>
|
||||
#include <llarp/nodedb.h>
|
||||
#include <llarp/router.h>
|
||||
#include <llarp/version.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -46,10 +44,10 @@ extern "C"
|
|||
|
||||
/// put RC into nodeDB
|
||||
bool
|
||||
llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc);
|
||||
llarp_main_putDatabase(struct llarp_main *ptr, struct llarp::RouterContact *rc);
|
||||
|
||||
/// get RC from nodeDB
|
||||
struct llarp_rc *
|
||||
llarp::RouterContact *
|
||||
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk);
|
||||
|
||||
// fwd declr
|
||||
|
@ -83,7 +81,7 @@ extern "C"
|
|||
uint16_t server_port, const char *upstream_host,
|
||||
uint16_t upstream_port);
|
||||
|
||||
struct llarp_rc *
|
||||
llarp::RouterContact *
|
||||
llarp_main_getLocalRC(struct llarp_main *ptr);
|
||||
|
||||
void
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <llarp/threading.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <llarp/crypto.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -39,9 +40,9 @@ namespace llarp
|
|||
IterateDatabase(struct llarp_nodedb_iter i);
|
||||
|
||||
bool
|
||||
PutDatabase(struct llarp_rc *rc);
|
||||
PutDatabase(struct llarp::RouterContact *rc);
|
||||
|
||||
struct llarp_rc *
|
||||
llarp::RouterContact *
|
||||
GetDatabase(const byte_t *pk);
|
||||
|
||||
int
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
#ifndef LLARP_AI_HPP
|
||||
#define LLARP_AI_HPP
|
||||
#include <llarp/mem.h>
|
||||
#include <llarp/net.h>
|
||||
#include <stdbool.h>
|
||||
#include <llarp/bencode.hpp>
|
||||
#include <llarp/crypto.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* address_info.hpp
|
||||
*
|
||||
* utilities for handling addresses on the llarp network
|
||||
*/
|
||||
|
||||
/// address information model
|
||||
namespace llarp
|
||||
{
|
||||
struct AddressInfo : public IBEncodeMessage
|
||||
{
|
||||
uint16_t rank;
|
||||
std::string dialect;
|
||||
llarp::PubKey pubkey;
|
||||
struct in6_addr ip;
|
||||
uint16_t port;
|
||||
|
||||
AddressInfo() : IBEncodeMessage()
|
||||
{
|
||||
}
|
||||
|
||||
AddressInfo(const AddressInfo& other)
|
||||
: IBEncodeMessage()
|
||||
, rank(other.rank)
|
||||
, dialect(other.dialect)
|
||||
, pubkey(other.pubkey)
|
||||
{
|
||||
port = other.port;
|
||||
version = other.version;
|
||||
memcpy(ip.s6_addr, other.ip.s6_addr, 16);
|
||||
}
|
||||
|
||||
~AddressInfo();
|
||||
|
||||
AddressInfo&
|
||||
operator=(const AddressInfo& other);
|
||||
|
||||
bool
|
||||
operator==(const AddressInfo& other) const;
|
||||
|
||||
bool
|
||||
operator<(const AddressInfo& other) const;
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf);
|
||||
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& out, const AddressInfo& a)
|
||||
{
|
||||
char tmp[128] = {0};
|
||||
inet_ntop(AF_INET6, &a.ip, tmp, sizeof(tmp));
|
||||
return out << tmp << "." << std::to_string(a.port);
|
||||
}
|
||||
|
||||
struct Hash
|
||||
{
|
||||
size_t
|
||||
operator()(const AddressInfo& addr) const
|
||||
{
|
||||
return *addr.pubkey.data_l();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
/// aligned buffer, aligns to the nears 8 bytes
|
||||
template < size_t sz, bool randomize = false >
|
||||
/// aligned buffer, aligns to the nears Long_t
|
||||
template < size_t sz, bool randomize = false, typename Long_t = uint64_t >
|
||||
struct AlignedBuffer
|
||||
{
|
||||
AlignedBuffer()
|
||||
|
@ -84,7 +84,7 @@ namespace llarp
|
|||
operator^(const AlignedBuffer& other) const
|
||||
{
|
||||
AlignedBuffer< sz > ret;
|
||||
for(size_t idx = 0; idx < sz / 8; ++idx)
|
||||
for(size_t idx = 0; idx < sz / sizeof(Long_t); ++idx)
|
||||
ret.l[idx] = l[idx] ^ other.l[idx];
|
||||
return ret;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ namespace llarp
|
|||
AlignedBuffer&
|
||||
operator^=(const AlignedBuffer& other)
|
||||
{
|
||||
for(size_t idx = 0; idx < sz / 8; ++idx)
|
||||
for(size_t idx = 0; idx < sz / sizeof(Long_t); ++idx)
|
||||
l[idx] ^= other.l[idx];
|
||||
return *this;
|
||||
}
|
||||
|
@ -146,13 +146,13 @@ namespace llarp
|
|||
return &b[0];
|
||||
}
|
||||
|
||||
uint64_t*
|
||||
Long_t*
|
||||
data_l()
|
||||
{
|
||||
return &l[0];
|
||||
}
|
||||
|
||||
const uint64_t*
|
||||
const Long_t*
|
||||
data_l() const
|
||||
{
|
||||
return &l[0];
|
||||
|
@ -182,9 +182,7 @@ namespace llarp
|
|||
return false;
|
||||
if(strbuf.sz != sz)
|
||||
{
|
||||
llarp::LogErrorTag("AlignedBuffer::BDecode",
|
||||
"bdecode buffer size missmatch ", strbuf.sz,
|
||||
"!=", sz);
|
||||
llarp::LogError("bdecode buffer size missmatch ", strbuf.sz, "!=", sz);
|
||||
return false;
|
||||
}
|
||||
memcpy(b, strbuf.base, sz);
|
||||
|
@ -194,7 +192,7 @@ namespace llarp
|
|||
struct Hash
|
||||
{
|
||||
size_t
|
||||
operator()(const AlignedBuffer< sz >& buf) const
|
||||
operator()(const AlignedBuffer& buf) const
|
||||
{
|
||||
return *buf.data_l();
|
||||
}
|
||||
|
@ -203,7 +201,7 @@ namespace llarp
|
|||
protected:
|
||||
union {
|
||||
byte_t b[sz];
|
||||
uint64_t l[(sz / 8) + (sz % 8)];
|
||||
Long_t l[(sz / sizeof(Long_t)) + (sz % sizeof(Long_t))];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <llarp/logger.hpp>
|
||||
#include <llarp/mem.hpp>
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -38,6 +39,20 @@ namespace llarp
|
|||
return bencode_write_bytestring(buf, k, 1) && bencode_write_uint64(buf, i);
|
||||
}
|
||||
|
||||
template < typename List_t >
|
||||
bool
|
||||
BEncodeMaybeReadDictList(const char* k, List_t& item, bool& read,
|
||||
llarp_buffer_t key, llarp_buffer_t* buf)
|
||||
{
|
||||
if(llarp_buffer_eq(key, k))
|
||||
{
|
||||
if(!BEncodeReadList(item, buf))
|
||||
return false;
|
||||
read = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename Item_t >
|
||||
bool
|
||||
BEncodeMaybeReadDictEntry(const char* k, Item_t& item, bool& read,
|
||||
|
@ -105,6 +120,43 @@ namespace llarp
|
|||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
template < typename Array >
|
||||
bool
|
||||
BEncodeWriteDictArray(const char* k, const Array& array, llarp_buffer_t* buf)
|
||||
{
|
||||
if(!bencode_write_bytestring(buf, k, 1))
|
||||
return false;
|
||||
if(!bencode_start_list(buf))
|
||||
return false;
|
||||
|
||||
for(size_t idx = 0; idx < array.size(); ++idx)
|
||||
if(!array[idx].BEncode(buf))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
template < typename Array >
|
||||
bool
|
||||
BEncodeReadArray(Array& array, llarp_buffer_t* buf)
|
||||
{
|
||||
if(*buf->cur != 'l') // ensure is a list
|
||||
return false;
|
||||
|
||||
buf->cur++;
|
||||
size_t idx = 0;
|
||||
while(llarp_buffer_size_left(*buf) && *buf->cur != 'e')
|
||||
{
|
||||
if(idx >= array.size())
|
||||
return false;
|
||||
if(!array[idx++].BDecode(buf))
|
||||
return false;
|
||||
}
|
||||
if(*buf->cur != 'e') // make sure we're at a list end
|
||||
return false;
|
||||
buf->cur++;
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename Iter >
|
||||
bool
|
||||
BEncodeWriteList(Iter itr, Iter end, llarp_buffer_t* buf)
|
||||
|
@ -188,15 +240,23 @@ namespace llarp
|
|||
}
|
||||
|
||||
// TODO: check for shadowed values elsewhere
|
||||
uint64_t version = 0;
|
||||
uint64_t version = LLARP_PROTO_VERSION;
|
||||
|
||||
static bool
|
||||
OnKey(dict_reader* r, llarp_buffer_t* k)
|
||||
{
|
||||
if(k)
|
||||
return static_cast< IBEncodeMessage* >(r->user)->DecodeKey(*k,
|
||||
r->buffer);
|
||||
return true;
|
||||
return static_cast< IBEncodeMessage* >(r->user)->HandleKey(k, r->buffer);
|
||||
}
|
||||
|
||||
bool
|
||||
HandleKey(llarp_buffer_t* k, llarp_buffer_t* val)
|
||||
{
|
||||
if(k == nullptr)
|
||||
return true;
|
||||
if(DecodeKey(*k, val))
|
||||
return true;
|
||||
llarp::LogError("unhandled key '", *k->cur, "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
template < size_t bufsz, size_t align = 128 >
|
||||
|
@ -210,6 +270,52 @@ namespace llarp
|
|||
}
|
||||
};
|
||||
|
||||
/// read entire file and decode its contents into t
|
||||
template < typename T >
|
||||
bool
|
||||
BDecodeReadFile(const char* fpath, T& t)
|
||||
{
|
||||
byte_t* ptr = nullptr;
|
||||
size_t sz = 0;
|
||||
{
|
||||
std::ifstream f;
|
||||
f.open(fpath);
|
||||
if(!f.is_open())
|
||||
return false;
|
||||
f.seekg(0, std::ios::end);
|
||||
sz = f.tellg();
|
||||
f.seekg(0, std::ios::beg);
|
||||
ptr = new byte_t[sz];
|
||||
f.read((char*)ptr, sz);
|
||||
}
|
||||
llarp_buffer_t buf = InitBuffer(ptr, sz);
|
||||
auto result = t.BDecode(&buf);
|
||||
if(!result)
|
||||
DumpBuffer(buf);
|
||||
delete[] ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// bencode and write to file
|
||||
template < typename T, size_t bufsz >
|
||||
bool
|
||||
BEncodeWriteFile(const char* fpath, const T& t)
|
||||
{
|
||||
uint8_t tmp[bufsz] = {0};
|
||||
auto buf = StackBuffer< decltype(tmp) >(tmp);
|
||||
if(!t.BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
{
|
||||
std::ofstream f;
|
||||
f.open(fpath);
|
||||
if(!f.is_open())
|
||||
return false;
|
||||
f.write((char*)buf.base, buf.sz);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <cmath>
|
||||
#include <functional>
|
||||
|
||||
#include <queue>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace llarp
|
||||
|
@ -34,29 +34,11 @@ namespace llarp
|
|||
{
|
||||
}
|
||||
};
|
||||
template < typename T, typename GetTime >
|
||||
struct CoDelCompareTime
|
||||
{
|
||||
bool
|
||||
operator()(const T& left, const T& right) const
|
||||
{
|
||||
return GetTime()(left) < GetTime()(right);
|
||||
}
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct CoDelComparePriority
|
||||
{
|
||||
bool
|
||||
operator()(const T& left, const T& right) const
|
||||
{
|
||||
return left < right;
|
||||
}
|
||||
};
|
||||
|
||||
template < typename T, typename GetTime, typename PutTime, typename Compare,
|
||||
typename Mutex_t = util::Mutex, typename Lock_t = util::Lock,
|
||||
llarp_time_t dropMs = 5, llarp_time_t initialIntervalMs = 100 >
|
||||
llarp_time_t dropMs = 5, llarp_time_t initialIntervalMs = 100,
|
||||
size_t MaxSize = 1024 >
|
||||
struct CoDelQueue
|
||||
{
|
||||
CoDelQueue(const std::string& name) : m_name(name)
|
||||
|
@ -67,26 +49,29 @@ namespace llarp
|
|||
Size()
|
||||
{
|
||||
Lock_t lock(m_QueueMutex);
|
||||
return m_Queue.size();
|
||||
return m_QueueIdx;
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
bool
|
||||
EmplaceIf(std::function< bool(T*) > pred, Args&&... args)
|
||||
EmplaceIf(std::function< bool(T&) > pred, Args&&... args)
|
||||
{
|
||||
T* ptr = new T(std::forward< Args >(args)...);
|
||||
if(!pred(ptr))
|
||||
Lock_t lock(m_QueueMutex);
|
||||
if(m_QueueIdx == MaxSize)
|
||||
return false;
|
||||
T* t = &m_Queue[m_QueueIdx];
|
||||
new(t) T(std::forward< Args >(args)...);
|
||||
if(!pred(*t))
|
||||
{
|
||||
delete ptr;
|
||||
t->~T();
|
||||
return false;
|
||||
}
|
||||
PutTime()(ptr);
|
||||
{
|
||||
Lock_t lock(m_QueueMutex);
|
||||
if(firstPut == 0)
|
||||
firstPut = GetTime()(ptr);
|
||||
m_Queue.push(ptr);
|
||||
}
|
||||
|
||||
PutTime()(m_Queue[m_QueueIdx]);
|
||||
if(firstPut == 0)
|
||||
firstPut = GetTime()(m_Queue[m_QueueIdx]);
|
||||
++m_QueueIdx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -94,57 +79,63 @@ namespace llarp
|
|||
void
|
||||
Emplace(Args&&... args)
|
||||
{
|
||||
T* ptr = new T(std::forward< Args >(args)...);
|
||||
PutTime()(ptr);
|
||||
{
|
||||
Lock_t lock(m_QueueMutex);
|
||||
if(firstPut == 0)
|
||||
firstPut = GetTime()(ptr);
|
||||
m_Queue.push(ptr);
|
||||
}
|
||||
Lock_t lock(m_QueueMutex);
|
||||
if(m_QueueIdx == MaxSize)
|
||||
return;
|
||||
T* t = &m_Queue[m_QueueIdx];
|
||||
new(t) T(std::forward< Args >(args)...);
|
||||
PutTime()(m_Queue[m_QueueIdx]);
|
||||
if(firstPut == 0)
|
||||
firstPut = GetTime()(m_Queue[m_QueueIdx]);
|
||||
++m_QueueIdx;
|
||||
}
|
||||
|
||||
void
|
||||
Put(T* ptr)
|
||||
{
|
||||
PutTime()(ptr);
|
||||
{
|
||||
Lock_t lock(m_QueueMutex);
|
||||
if(firstPut == 0)
|
||||
firstPut = GetTime()(ptr);
|
||||
m_Queue.push(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/// visit returns true to discard entry otherwise the entry is
|
||||
/// re quened
|
||||
template < typename Visit >
|
||||
void
|
||||
ProcessIf(Visit visitor)
|
||||
Process(Visit v)
|
||||
{
|
||||
return Process(v, [](T&) -> bool { return false; });
|
||||
}
|
||||
|
||||
template < typename Visit, typename Filter >
|
||||
void
|
||||
Process(Visit visitor, Filter f)
|
||||
{
|
||||
llarp_time_t lowest = 0xFFFFFFFFFFFFFFFFUL;
|
||||
// auto start = llarp_time_now_ms();
|
||||
// llarp::LogInfo("CoDelQueue::Process - start at ", start);
|
||||
Lock_t lock(m_QueueMutex);
|
||||
auto start = firstPut;
|
||||
Queue_t requeue;
|
||||
while(m_Queue.size())
|
||||
if(m_QueueIdx == 1)
|
||||
{
|
||||
llarp::LogDebug("CoDelQueue::Process - queue has ", m_Queue.size());
|
||||
T* item = m_Queue.top();
|
||||
auto dlt = start - GetTime()(item);
|
||||
visitor(m_Queue[0]);
|
||||
T* t = &m_Queue[0];
|
||||
t->~T();
|
||||
m_QueueIdx = 0;
|
||||
firstPut = 0;
|
||||
return;
|
||||
}
|
||||
size_t idx = 0;
|
||||
while(m_QueueIdx)
|
||||
{
|
||||
llarp::LogDebug(m_name, " - queue has ", m_QueueIdx);
|
||||
T* item = &m_Queue[idx++];
|
||||
if(f(*item))
|
||||
break;
|
||||
--m_QueueIdx;
|
||||
auto dlt = start - GetTime()(*item);
|
||||
// llarp::LogInfo("CoDelQueue::Process - dlt ", dlt);
|
||||
lowest = std::min(dlt, lowest);
|
||||
if(m_Queue.size() == 1)
|
||||
if(m_QueueIdx == 0)
|
||||
{
|
||||
// llarp::LogInfo("CoDelQueue::Process - single item: lowest ",
|
||||
// lowest, " dropMs: ", dropMs);
|
||||
if(lowest > dropMs)
|
||||
{
|
||||
item->~T();
|
||||
nextTickInterval += initialIntervalMs / std::sqrt(++dropNum);
|
||||
m_Queue.pop();
|
||||
delete item;
|
||||
break;
|
||||
firstPut = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -152,40 +143,21 @@ namespace llarp
|
|||
dropNum = 0;
|
||||
}
|
||||
}
|
||||
// llarp::LogInfo("CoDelQueue::Process - passing");
|
||||
if(visitor(item))
|
||||
{
|
||||
delete item;
|
||||
}
|
||||
else
|
||||
{
|
||||
requeue.push(item);
|
||||
}
|
||||
m_Queue.pop();
|
||||
visitor(*item);
|
||||
item->~T();
|
||||
}
|
||||
m_Queue = std::move(requeue);
|
||||
firstPut = 0;
|
||||
}
|
||||
|
||||
template < typename Func >
|
||||
void
|
||||
Process(Func visitor)
|
||||
{
|
||||
ProcessIf([visitor](T* t) -> bool {
|
||||
visitor(t);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
llarp_time_t firstPut = 0;
|
||||
size_t dropNum = 0;
|
||||
llarp_time_t nextTickInterval = initialIntervalMs;
|
||||
Mutex_t m_QueueMutex;
|
||||
typedef std::priority_queue< T*, std::vector< T* >, Compare > Queue_t;
|
||||
Queue_t m_Queue;
|
||||
size_t m_QueueIdx = 0;
|
||||
T m_Queue[MaxSize];
|
||||
std::string m_name;
|
||||
};
|
||||
} // namespace util
|
||||
}; // namespace util
|
||||
} // namespace util
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,7 +57,7 @@ typedef bool (*llarp_hmac_func)(byte_t *, llarp_buffer_t, const byte_t *);
|
|||
/// S(sig, secretkey, body)
|
||||
typedef bool (*llarp_sign_func)(byte_t *, const byte_t *, llarp_buffer_t);
|
||||
|
||||
/// V(sig, body, secretkey)
|
||||
/// V(pubkey, body, sig)
|
||||
typedef bool (*llarp_verify_func)(const byte_t *, llarp_buffer_t,
|
||||
const byte_t *);
|
||||
|
||||
|
@ -100,9 +100,9 @@ struct llarp_crypto
|
|||
bool (*pqe_encrypt)(byte_t *, byte_t *, const byte_t *);
|
||||
};
|
||||
|
||||
/// set crypto function pointers to use libsodium
|
||||
/// initialize crypto subsystem
|
||||
void
|
||||
llarp_crypto_libsodium_init(struct llarp_crypto *c);
|
||||
llarp_crypto_init(struct llarp_crypto *c);
|
||||
|
||||
/// check for initialize crypto
|
||||
bool
|
||||
|
|
|
@ -65,11 +65,11 @@ struct iwp_async_intro
|
|||
uint8_t *buf;
|
||||
size_t sz;
|
||||
/// nonce paramter
|
||||
uint8_t *nonce;
|
||||
uint8_t nonce[32];
|
||||
/// remote public key
|
||||
uint8_t *remote_pubkey;
|
||||
uint8_t remote_pubkey[32];
|
||||
/// local private key
|
||||
uint8_t *secretkey;
|
||||
uint8_t secretkey[64];
|
||||
/// callback
|
||||
iwp_intro_hook hook;
|
||||
};
|
||||
|
@ -184,26 +184,26 @@ struct iwp_async_frame
|
|||
struct FramePutTime
|
||||
{
|
||||
void
|
||||
operator()(iwp_async_frame *frame) const
|
||||
operator()(iwp_async_frame &frame) const
|
||||
{
|
||||
frame->created = llarp_time_now_ms();
|
||||
frame.created = llarp_time_now_ms();
|
||||
}
|
||||
};
|
||||
struct FrameGetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const iwp_async_frame *frame) const
|
||||
operator()(const iwp_async_frame &frame) const
|
||||
{
|
||||
return frame->created;
|
||||
return frame.created;
|
||||
}
|
||||
};
|
||||
|
||||
struct FrameCompareTime
|
||||
{
|
||||
bool
|
||||
operator()(const iwp_async_frame *left, const iwp_async_frame *right) const
|
||||
operator()(const iwp_async_frame &left, const iwp_async_frame &right) const
|
||||
{
|
||||
return left->created < right->created;
|
||||
return left.created < right.created;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <llarp/buffer.h>
|
||||
#include <llarp/router.h>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
|
||||
/**
|
||||
* dht.h
|
||||
|
@ -24,6 +26,7 @@ llarp_dht_context_free(struct llarp_dht_context* dht);
|
|||
void
|
||||
llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key);
|
||||
|
||||
// remove this? dns needs it atm
|
||||
struct llarp_router_lookup_job;
|
||||
|
||||
typedef void (*llarp_router_lookup_handler)(struct llarp_router_lookup_job*);
|
||||
|
@ -34,22 +37,19 @@ struct llarp_router_lookup_job
|
|||
void* user;
|
||||
llarp_router_lookup_handler hook;
|
||||
struct llarp_dht_context* dht;
|
||||
byte_t target[PUBKEYSIZE];
|
||||
//byte_t target[PUBKEYSIZE];
|
||||
llarp::PubKey target;
|
||||
bool found;
|
||||
// make sure you initialize addr and exits
|
||||
struct llarp_rc result;
|
||||
llarp::RouterContact result;
|
||||
bool iterative;
|
||||
};
|
||||
// end dns requirement
|
||||
|
||||
/// start allowing dht participation on a context
|
||||
void
|
||||
llarp_dht_allow_transit(struct llarp_dht_context* ctx);
|
||||
|
||||
/// put router as a dht peer
|
||||
/// internal function do not use
|
||||
void
|
||||
__llarp_dht_put_peer(struct llarp_dht_context* ctx, struct llarp_rc* rc);
|
||||
|
||||
/// remove router from tracked dht peer list
|
||||
/// internal function do not use
|
||||
void
|
||||
|
|
|
@ -19,7 +19,8 @@ namespace llarp
|
|||
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
|
||||
|
||||
bool
|
||||
GetRandomNodeExcluding(Key_t& result, std::set< Key_t > exclude) const
|
||||
GetRandomNodeExcluding(Key_t& result,
|
||||
const std::set< Key_t >& exclude) const
|
||||
{
|
||||
std::vector< Key_t > candidates;
|
||||
for(const auto& item : nodes)
|
||||
|
@ -50,9 +51,52 @@ namespace llarp
|
|||
return nodes.size() > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
GetManyRandom(std::set< Key_t >& result, size_t N) const
|
||||
{
|
||||
if(nodes.size() < N)
|
||||
return false;
|
||||
if(nodes.size() == N)
|
||||
{
|
||||
for(const auto& node : nodes)
|
||||
{
|
||||
result.insert(node.first);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
size_t expecting = N;
|
||||
size_t sz = nodes.size();
|
||||
while(N)
|
||||
{
|
||||
auto itr = nodes.begin();
|
||||
std::advance(itr, llarp_randint() % sz);
|
||||
if(result.insert(itr->first).second)
|
||||
--N;
|
||||
}
|
||||
return result.size() == expecting;
|
||||
}
|
||||
|
||||
bool
|
||||
GetManyNearExcluding(const Key_t& target, std::set< Key_t >& result,
|
||||
size_t N, const std::set< Key_t >& exclude) const
|
||||
{
|
||||
std::set< Key_t > s;
|
||||
for(const auto& k : exclude)
|
||||
s.insert(k);
|
||||
Key_t peer;
|
||||
while(N--)
|
||||
{
|
||||
if(!FindCloseExcluding(target, peer, s))
|
||||
return false;
|
||||
s.insert(peer);
|
||||
result.insert(peer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FindCloseExcluding(const Key_t& target, Key_t& result,
|
||||
std::set< Key_t > exclude) const
|
||||
const std::set< Key_t >& exclude) const
|
||||
{
|
||||
Key_t maxdist;
|
||||
maxdist.Fill(0xff);
|
||||
|
@ -91,4 +135,4 @@ namespace llarp
|
|||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <llarp/dht/message.hpp>
|
||||
#include <llarp/dht/messages/findintro.hpp>
|
||||
#include <llarp/dht/node.hpp>
|
||||
#include <llarp/dht/search_job.hpp>
|
||||
#include <llarp/service/IntroSet.hpp>
|
||||
|
||||
#include <set>
|
||||
|
@ -17,123 +16,209 @@ namespace llarp
|
|||
{
|
||||
namespace dht
|
||||
{
|
||||
struct TXOwner
|
||||
{
|
||||
Key_t node;
|
||||
uint64_t txid = 0;
|
||||
|
||||
TXOwner() = default;
|
||||
|
||||
TXOwner(const Key_t& k, uint64_t id) : node(k), txid(id)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const TXOwner& other) const
|
||||
{
|
||||
return txid == other.txid && node == other.node;
|
||||
}
|
||||
bool
|
||||
operator<(const TXOwner& other) const
|
||||
{
|
||||
return txid < other.txid || node < other.node;
|
||||
}
|
||||
|
||||
struct Hash
|
||||
{
|
||||
std::size_t
|
||||
operator()(TXOwner const& o) const noexcept
|
||||
{
|
||||
std::size_t sz2;
|
||||
memcpy(&sz2, &o.node[0], sizeof(std::size_t));
|
||||
return o.txid ^ (sz2 << 1);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct Context;
|
||||
|
||||
template < typename K, typename V >
|
||||
struct TX
|
||||
{
|
||||
TX(const TXOwner& asker, const K& k, Context* p)
|
||||
: target(k), whoasked(asker)
|
||||
{
|
||||
parent = p;
|
||||
}
|
||||
|
||||
virtual ~TX(){};
|
||||
|
||||
K target;
|
||||
Context* parent;
|
||||
std::set< Key_t > peersAsked;
|
||||
std::vector< V > valuesFound;
|
||||
TXOwner whoasked;
|
||||
|
||||
void
|
||||
OnFound(const Key_t& askedPeer, const V& value)
|
||||
{
|
||||
peersAsked.insert(askedPeer);
|
||||
valuesFound.push_back(value);
|
||||
}
|
||||
|
||||
virtual void
|
||||
Start(const TXOwner& peer) = 0;
|
||||
|
||||
virtual bool
|
||||
GetNextPeer(Key_t& next, const std::set< Key_t >& exclude) = 0;
|
||||
|
||||
virtual void
|
||||
DoNextRequest(const Key_t& peer) = 0;
|
||||
|
||||
/// return true if we want to persist this tx
|
||||
bool
|
||||
AskNextPeer(const Key_t& prevPeer)
|
||||
{
|
||||
peersAsked.insert(prevPeer);
|
||||
Key_t peer;
|
||||
if(!GetNextPeer(peer, peersAsked))
|
||||
{
|
||||
// no more peers
|
||||
SendReply();
|
||||
return false;
|
||||
}
|
||||
DoNextRequest(peer);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void
|
||||
SendReply() = 0;
|
||||
};
|
||||
|
||||
typedef std::function< void(const std::vector< service::IntroSet >&) >
|
||||
IntroSetLookupHandler;
|
||||
|
||||
typedef std::function< void(const std::vector< RouterContact >&) >
|
||||
RouterLookupHandler;
|
||||
|
||||
struct Context
|
||||
{
|
||||
Context();
|
||||
~Context();
|
||||
|
||||
SearchJob*
|
||||
FindPendingTX(const Key_t& owner, uint64_t txid);
|
||||
/// on behalf of whoasked request introset for target from dht router with
|
||||
/// key askpeer
|
||||
void
|
||||
LookupIntroSetRecursive(const service::Address& target,
|
||||
const Key_t& whoasked, uint64_t whoaskedTX,
|
||||
const Key_t& askpeer, uint64_t R,
|
||||
IntroSetLookupHandler result = nullptr);
|
||||
|
||||
void
|
||||
RemovePendingTX(const Key_t& owner, uint64_t txid);
|
||||
LookupIntroSetIterative(const service::Address& target,
|
||||
const Key_t& whoasked, uint64_t whoaskedTX,
|
||||
const Key_t& askpeer,
|
||||
IntroSetLookupHandler result = nullptr);
|
||||
|
||||
/// on behalf of whoasked request router with public key target from dht
|
||||
/// router with key askpeer
|
||||
void
|
||||
LookupServiceDirect(const Key_t& target, const Key_t& whoasked,
|
||||
uint64_t whoaskedTX, const Key_t& askpeer,
|
||||
SearchJob::IntroSetHookFunc handler,
|
||||
bool iterateive = false,
|
||||
std::set< Key_t > excludes = {});
|
||||
LookupRouterRecursive(const RouterID& target, const Key_t& whoasked,
|
||||
uint64_t whoaskedTX, const Key_t& askpeer,
|
||||
RouterLookupHandler result = nullptr);
|
||||
|
||||
bool
|
||||
LookupRouter(const RouterID& target, RouterLookupHandler result)
|
||||
{
|
||||
Key_t askpeer;
|
||||
if(!nodes->FindClosest(target.data(), askpeer))
|
||||
return false;
|
||||
LookupRouterRecursive(target, OurKey(), 0, askpeer, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// on behalf of whoasked request introsets with tag from dht router with
|
||||
/// key askpeer with Recursion depth R
|
||||
void
|
||||
LookupRouter(const Key_t& target, const Key_t& whoasked,
|
||||
uint64_t whoaskedTX, const Key_t& askpeer,
|
||||
llarp_router_lookup_job* job = nullptr,
|
||||
bool iterative = false, std::set< Key_t > excludes = {});
|
||||
|
||||
void
|
||||
LookupIntroSet(const service::Address& addr, const Key_t& whoasked,
|
||||
uint64_t whoaskedTX, const Key_t& askpeer, uint64_t R,
|
||||
std::set< Key_t > excludes = {});
|
||||
|
||||
void
|
||||
LookupTag(const service::Tag& tag, const Key_t& whoasked,
|
||||
uint64_t whoaskedTX, const Key_t& askpeer,
|
||||
const std::set< service::IntroSet >& include = {},
|
||||
uint64_t R = 0);
|
||||
|
||||
void
|
||||
LookupRouterViaJob(llarp_router_lookup_job* job);
|
||||
LookupTagRecursive(const service::Tag& tag, const Key_t& whoasked,
|
||||
uint64_t whoaskedTX, const Key_t& askpeer, uint64_t R);
|
||||
|
||||
/// issue dht lookup for tag via askpeer and send reply to local path
|
||||
void
|
||||
LookupTagForPath(const service::Tag& tag, uint64_t txid,
|
||||
const llarp::PathID_t& path, const Key_t& askpeer);
|
||||
|
||||
/// issue dht lookup for router via askpeer and send reply to local path
|
||||
void
|
||||
LookupRouterForPath(const RouterID& target, uint64_t txid,
|
||||
const llarp::PathID_t& path, const Key_t& askpeer);
|
||||
|
||||
/// issue dht lookup for introset for addr via askpeer and send reply to
|
||||
/// local path
|
||||
void
|
||||
LookupIntroSetForPath(const service::Address& addr, uint64_t txid,
|
||||
const llarp::PathID_t& path, Key_t askpeer);
|
||||
const llarp::PathID_t& path, const Key_t& askpeer);
|
||||
|
||||
template < typename Job, typename Result >
|
||||
/// send a dht message to peer, if keepalive is true then keep the session
|
||||
/// with that peer alive for 10 seconds
|
||||
void
|
||||
DHTSendTo(const Key_t& peer, IMessage* msg, bool keepalive = true);
|
||||
|
||||
/// get routers closest to target excluding requester
|
||||
bool
|
||||
TryLookupAgain(Job* j, Result r, uint64_t R)
|
||||
{
|
||||
const Key_t targetKey = j->target.ToKey();
|
||||
Key_t askpeer;
|
||||
std::set< Key_t > exclude = j->asked;
|
||||
if(!nodes->FindCloseExcluding(targetKey, askpeer, exclude))
|
||||
{
|
||||
j->Exausted();
|
||||
return true;
|
||||
}
|
||||
if((OurKey() ^ targetKey) < (askpeer ^ targetKey))
|
||||
{
|
||||
j->Exausted();
|
||||
return true;
|
||||
}
|
||||
auto id = ++ids;
|
||||
TXOwner ownerKey;
|
||||
ownerKey.node = askpeer;
|
||||
ownerKey.txid = id;
|
||||
SearchJob job(j->whoasked, j->txid, r, [j]() { delete j; });
|
||||
pendingTX[ownerKey] = job;
|
||||
auto msg = new FindIntroMessage(id, j->target);
|
||||
msg->R = R;
|
||||
llarp::LogInfo("asking ", askpeer, " for ", j->target.ToString(),
|
||||
" with txid=", id);
|
||||
DHTSendTo(askpeer, msg);
|
||||
j->asked.insert(std::move(askpeer));
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DHTSendTo(const Key_t& peer, IMessage* msg);
|
||||
|
||||
void
|
||||
LookupIntroSetRelayed(const Key_t& requester, uint64_t txid,
|
||||
const service::Address& addr, bool recursive,
|
||||
std::vector< IMessage* >& reply);
|
||||
HandleExploritoryRouterLookup(
|
||||
const Key_t& requester, uint64_t txid, const RouterID& target,
|
||||
std::vector< std::unique_ptr< IMessage > >& reply);
|
||||
|
||||
std::set< service::IntroSet >
|
||||
FindRandomIntroSetsWithTag(const service::Tag& tag, size_t max = 2);
|
||||
FindRandomIntroSetsWithTagExcluding(
|
||||
const service::Tag& tag, size_t max = 2,
|
||||
const std::set< service::IntroSet >& excludes = {});
|
||||
|
||||
/// handle rc lookup from requester for target
|
||||
void
|
||||
LookupRouterRelayed(const Key_t& requester, uint64_t txid,
|
||||
const Key_t& target, bool recursive,
|
||||
std::vector< IMessage* >& replies);
|
||||
std::vector< std::unique_ptr< IMessage > >& replies);
|
||||
|
||||
/// relay a dht messeage from a local path to the main network
|
||||
bool
|
||||
RelayRequestForPath(const llarp::PathID_t& localPath,
|
||||
const IMessage* msg);
|
||||
|
||||
/// send introset to peer from source with S counter and excluding peers
|
||||
void
|
||||
PropagateIntroSetTo(const Key_t& from, uint64_t fromTX,
|
||||
PropagateIntroSetTo(const Key_t& source, uint64_t sourceTX,
|
||||
const service::IntroSet& introset, const Key_t& peer,
|
||||
uint64_t S, const std::set< Key_t >& exclude);
|
||||
|
||||
/// initialize dht context and explore every exploreInterval milliseconds
|
||||
void
|
||||
Init(const Key_t& us, llarp_router* router);
|
||||
Init(const Key_t& us, llarp_router* router, llarp_time_t exploreInterval);
|
||||
|
||||
/// get localally stored introset by service address
|
||||
const llarp::service::IntroSet*
|
||||
GetIntroSetByServiceAddress(const llarp::service::Address& addr) const;
|
||||
|
||||
void
|
||||
QueueRouterLookup(llarp_router_lookup_job* job);
|
||||
|
||||
static void
|
||||
handle_cleaner_timer(void* user, uint64_t orig, uint64_t left);
|
||||
|
||||
static void
|
||||
queue_router_lookup(void* user);
|
||||
handle_explore_timer(void* user, uint64_t orig, uint64_t left);
|
||||
|
||||
/// explore dht for new routers
|
||||
void
|
||||
Explore(size_t N = 3);
|
||||
|
||||
llarp_router* router = nullptr;
|
||||
// for router contacts
|
||||
|
@ -149,7 +234,136 @@ namespace llarp
|
|||
return ourKey;
|
||||
}
|
||||
|
||||
template < typename K, typename V, typename K_Hash,
|
||||
llarp_time_t requestTimeoutMS = 5000UL >
|
||||
struct TXHolder
|
||||
{
|
||||
// tx who are waiting for a reply for each key
|
||||
std::unordered_multimap< K, TXOwner, K_Hash > waiting;
|
||||
// tx timesouts by key
|
||||
std::unordered_map< K, llarp_time_t, K_Hash > timeouts;
|
||||
// maps remote peer with tx to handle reply from them
|
||||
std::unordered_map< TXOwner, std::unique_ptr< TX< K, V > >,
|
||||
TXOwner::Hash >
|
||||
tx;
|
||||
|
||||
const TX< K, V >*
|
||||
GetPendingLookupFrom(const TXOwner& owner) const
|
||||
{
|
||||
auto itr = tx.find(owner);
|
||||
if(itr == tx.end())
|
||||
return nullptr;
|
||||
else
|
||||
return itr->second.get();
|
||||
}
|
||||
|
||||
bool
|
||||
HasPendingLookupFrom(const TXOwner& owner) const
|
||||
{
|
||||
return GetPendingLookupFrom(owner) != nullptr;
|
||||
}
|
||||
|
||||
TX< K, V >*
|
||||
NewTX(const TXOwner& owner, const K& k, TX< K, V >* t)
|
||||
{
|
||||
tx.emplace(owner, std::unique_ptr< TX< K, V > >(t));
|
||||
waiting.insert(std::make_pair(k, owner));
|
||||
auto itr = timeouts.find(k);
|
||||
if(itr == timeouts.end())
|
||||
timeouts.insert(
|
||||
std::make_pair(k, llarp_time_now_ms() + requestTimeoutMS));
|
||||
return t;
|
||||
}
|
||||
|
||||
/// mark tx as not fond
|
||||
void
|
||||
NotFound(const TXOwner& from)
|
||||
{
|
||||
bool sendReply = true;
|
||||
auto txitr = tx.find(from);
|
||||
if(txitr == tx.end())
|
||||
return;
|
||||
|
||||
// ask for next peer
|
||||
if(txitr->second->AskNextPeer(from.node))
|
||||
sendReply = false;
|
||||
Inform(from, txitr->second->target, {}, sendReply, sendReply);
|
||||
}
|
||||
|
||||
void
|
||||
Found(const TXOwner& from, const K& k, const std::vector< V >& values)
|
||||
{
|
||||
Inform(from, k, values, true);
|
||||
}
|
||||
|
||||
/// inform all watches for key of values found
|
||||
void
|
||||
Inform(const TXOwner& from, const K& key,
|
||||
const std::vector< V >& values, bool sendreply = false,
|
||||
bool removeTimeouts = true)
|
||||
{
|
||||
auto range = waiting.equal_range(key);
|
||||
auto itr = range.first;
|
||||
while(itr != range.second)
|
||||
{
|
||||
auto txitr = tx.find(itr->second);
|
||||
if(txitr != tx.end())
|
||||
{
|
||||
for(const auto& value : values)
|
||||
txitr->second->OnFound(from.node, value);
|
||||
if(sendreply)
|
||||
{
|
||||
txitr->second->SendReply();
|
||||
tx.erase(txitr);
|
||||
}
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
|
||||
if(sendreply)
|
||||
waiting.erase(key);
|
||||
|
||||
if(removeTimeouts)
|
||||
timeouts.erase(key);
|
||||
}
|
||||
|
||||
void
|
||||
Expire(llarp_time_t now)
|
||||
{
|
||||
auto itr = timeouts.begin();
|
||||
while(itr != timeouts.end())
|
||||
{
|
||||
if(now > itr->second && now - itr->second >= requestTimeoutMS)
|
||||
{
|
||||
Inform(TXOwner{}, itr->first, {}, true, false);
|
||||
itr = timeouts.erase(itr);
|
||||
}
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TXHolder< service::Address, service::IntroSet, service::Address::Hash >
|
||||
pendingIntrosetLookups;
|
||||
|
||||
TXHolder< service::Tag, service::IntroSet, service::Tag::Hash >
|
||||
pendingTagLookups;
|
||||
|
||||
TXHolder< RouterID, RouterContact, RouterID::Hash > pendingRouterLookups;
|
||||
|
||||
TXHolder< RouterID, RouterID, RouterID::Hash > pendingExploreLookups;
|
||||
|
||||
uint64_t
|
||||
NextID()
|
||||
{
|
||||
return ++ids;
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
ExploreNetworkVia(const Key_t& peer);
|
||||
|
||||
void
|
||||
ScheduleCleanupTimer();
|
||||
|
||||
|
@ -158,35 +372,6 @@ namespace llarp
|
|||
|
||||
uint64_t ids;
|
||||
|
||||
struct TXOwner
|
||||
{
|
||||
Key_t node;
|
||||
uint64_t txid = 0;
|
||||
|
||||
bool
|
||||
operator==(const TXOwner& other) const
|
||||
{
|
||||
return txid == other.txid && node == other.node;
|
||||
}
|
||||
bool
|
||||
operator<(const TXOwner& other) const
|
||||
{
|
||||
return txid < other.txid || node < other.node;
|
||||
}
|
||||
};
|
||||
|
||||
struct TXOwnerHash
|
||||
{
|
||||
std::size_t
|
||||
operator()(TXOwner const& o) const noexcept
|
||||
{
|
||||
std::size_t sz2;
|
||||
memcpy(&sz2, &o.node[0], sizeof(std::size_t));
|
||||
return o.txid ^ (sz2 << 1);
|
||||
}
|
||||
}; // namespace dht
|
||||
|
||||
std::unordered_map< TXOwner, SearchJob, TXOwnerHash > pendingTX;
|
||||
Key_t ourKey;
|
||||
}; // namespace llarp
|
||||
} // namespace dht
|
||||
|
@ -199,4 +384,4 @@ struct llarp_dht_context
|
|||
llarp_dht_context(llarp_router* router);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -22,20 +22,22 @@ namespace llarp
|
|||
}
|
||||
|
||||
virtual bool
|
||||
HandleMessage(llarp_dht_context* dht,
|
||||
std::vector< IMessage* >& replies) const = 0;
|
||||
HandleMessage(
|
||||
llarp_dht_context* dht,
|
||||
std::vector< std::unique_ptr< IMessage > >& replies) const = 0;
|
||||
|
||||
Key_t From;
|
||||
PathID_t pathID;
|
||||
};
|
||||
|
||||
IMessage*
|
||||
std::unique_ptr< IMessage >
|
||||
DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed = false);
|
||||
|
||||
bool
|
||||
DecodeMesssageList(const Key_t& from, llarp_buffer_t* buf,
|
||||
std::vector< IMessage* >& dst, bool relayed = false);
|
||||
DecodeMesssageList(Key_t from, llarp_buffer_t* buf,
|
||||
std::vector< std::unique_ptr< IMessage > >& dst,
|
||||
bool relayed = false);
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -27,8 +27,9 @@ namespace llarp
|
|||
S.Zero();
|
||||
}
|
||||
|
||||
FindIntroMessage(uint64_t txid, const llarp::service::Address& addr)
|
||||
: IMessage({}), S(addr), T(txid)
|
||||
FindIntroMessage(uint64_t txid, const llarp::service::Address& addr,
|
||||
uint64_t r)
|
||||
: IMessage({}), R(r), S(addr), T(txid)
|
||||
{
|
||||
N.Zero();
|
||||
}
|
||||
|
@ -43,8 +44,8 @@ namespace llarp
|
|||
|
||||
bool
|
||||
HandleMessage(llarp_dht_context* ctx,
|
||||
std::vector< IMessage* >& replies) const;
|
||||
std::vector< std::unique_ptr< IMessage > >& replies) const;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -12,11 +12,18 @@ namespace llarp
|
|||
{
|
||||
}
|
||||
|
||||
FindRouterMessage(const Key_t& from, const Key_t& target, uint64_t id)
|
||||
FindRouterMessage(const Key_t& from, const RouterID& target, uint64_t id)
|
||||
: IMessage(from), K(target), txid(id)
|
||||
{
|
||||
}
|
||||
|
||||
// exploritory
|
||||
FindRouterMessage(const Key_t& from, uint64_t id)
|
||||
: IMessage(from), exploritory(true), txid(id)
|
||||
{
|
||||
K.Randomize();
|
||||
}
|
||||
|
||||
~FindRouterMessage();
|
||||
|
||||
bool
|
||||
|
@ -27,10 +34,11 @@ namespace llarp
|
|||
|
||||
virtual bool
|
||||
HandleMessage(llarp_dht_context* ctx,
|
||||
std::vector< IMessage* >& replies) const;
|
||||
std::vector< std::unique_ptr< IMessage > >& replies) const;
|
||||
|
||||
Key_t K;
|
||||
RouterID K;
|
||||
bool iterative = false;
|
||||
bool exploritory = false;
|
||||
uint64_t txid = 0;
|
||||
uint64_t version = 0;
|
||||
};
|
||||
|
@ -47,8 +55,8 @@ namespace llarp
|
|||
/// TODO: smart path expiration logic needs to be implemented
|
||||
virtual bool
|
||||
HandleMessage(llarp_dht_context* ctx,
|
||||
std::vector< IMessage* >& replies) const;
|
||||
std::vector< std::unique_ptr< IMessage > >& replies) const;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace llarp
|
|||
|
||||
virtual bool
|
||||
HandleMessage(llarp_dht_context* ctx,
|
||||
std::vector< IMessage* >& replies) const;
|
||||
std::vector< std::unique_ptr< IMessage > >& replies) const;
|
||||
};
|
||||
|
||||
struct RelayedGotIntroMessage : public GotIntroMessage
|
||||
|
@ -42,8 +42,8 @@ namespace llarp
|
|||
|
||||
bool
|
||||
HandleMessage(llarp_dht_context* ctx,
|
||||
std::vector< IMessage* >& replies) const;
|
||||
std::vector< std::unique_ptr< IMessage > >& replies) const;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef LLARP_DHT_MESSAGES_GOT_ROUTER_HPP
|
||||
#define LLARP_DHT_MESSAGES_GOT_ROUTER_HPP
|
||||
#include <llarp/dht/message.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -12,16 +13,17 @@ namespace llarp
|
|||
: IMessage(from), relayed(tunneled)
|
||||
{
|
||||
}
|
||||
GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result,
|
||||
GotRouterMessage(const Key_t& from, uint64_t id,
|
||||
const std::vector< RouterContact >& results,
|
||||
bool tunneled)
|
||||
: IMessage(from), txid(id), relayed(tunneled)
|
||||
: IMessage(from), R(results), txid(id), relayed(tunneled)
|
||||
{
|
||||
}
|
||||
|
||||
GotRouterMessage(uint64_t id, const std::vector< RouterID >& near,
|
||||
bool tunneled)
|
||||
: IMessage({}), N(near), txid(id), relayed(tunneled)
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
R.emplace_back();
|
||||
llarp_rc_clear(&R.back());
|
||||
llarp_rc_copy(&R.back(), result);
|
||||
}
|
||||
}
|
||||
|
||||
~GotRouterMessage();
|
||||
|
@ -34,13 +36,14 @@ namespace llarp
|
|||
|
||||
virtual bool
|
||||
HandleMessage(llarp_dht_context* ctx,
|
||||
std::vector< IMessage* >& replies) const;
|
||||
std::vector< std::unique_ptr< IMessage > >& replies) const;
|
||||
|
||||
std::vector< llarp_rc > R;
|
||||
std::vector< RouterContact > R;
|
||||
std::vector< RouterID > N;
|
||||
uint64_t txid = 0;
|
||||
uint64_t version = 0;
|
||||
bool relayed = false;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -38,8 +38,8 @@ namespace llarp
|
|||
|
||||
virtual bool
|
||||
HandleMessage(llarp_dht_context* ctx,
|
||||
std::vector< IMessage* >& replies) const;
|
||||
std::vector< std::unique_ptr< IMessage > >& replies) const;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef LLARP_DHT_NODE_HPP
|
||||
#define LLARP_DHT_NODE_HPP
|
||||
|
||||
#include <llarp/router_contact.h>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/dht/key.hpp>
|
||||
#include <llarp/service/IntroSet.hpp>
|
||||
|
||||
|
@ -11,18 +11,19 @@ namespace llarp
|
|||
{
|
||||
struct RCNode
|
||||
{
|
||||
llarp_rc* rc;
|
||||
llarp::RouterContact rc;
|
||||
|
||||
Key_t ID;
|
||||
|
||||
RCNode() : rc(nullptr)
|
||||
RCNode()
|
||||
{
|
||||
ID.Zero();
|
||||
}
|
||||
|
||||
RCNode(llarp_rc* other) : rc(other)
|
||||
RCNode(const llarp::RouterContact& other)
|
||||
{
|
||||
ID = other->pubkey;
|
||||
rc = other;
|
||||
ID = other.pubkey.data();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -47,4 +48,4 @@ namespace llarp
|
|||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
|
||||
#ifndef LLARP_DHT_SEARCH_JOB_HPP
|
||||
#define LLARP_DHT_SEARCH_JOB_HPP
|
||||
#include <llarp/dht.h>
|
||||
#include <llarp/time.h>
|
||||
#include <functional>
|
||||
#include <llarp/dht/key.hpp>
|
||||
#include <llarp/service/IntroSet.hpp>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
/// TODO: this should be made into a templated type
|
||||
struct SearchJob
|
||||
{
|
||||
const static uint64_t JobTimeout = 30000;
|
||||
|
||||
typedef std::function< bool(
|
||||
const std::vector< llarp::service::IntroSet >&) >
|
||||
IntroSetHookFunc;
|
||||
|
||||
typedef std::function< void(void) > DoneFunc;
|
||||
SearchJob();
|
||||
/// for routers
|
||||
SearchJob(const Key_t& requester, uint64_t requesterTX,
|
||||
const Key_t& target, const std::set< Key_t >& excludes,
|
||||
llarp_router_lookup_job* job);
|
||||
/// for introsets
|
||||
SearchJob(const Key_t& requester, uint64_t requesterTX,
|
||||
const Key_t& target, const std::set< Key_t >& excludes,
|
||||
IntroSetHookFunc found, DoneFunc done);
|
||||
// for introsets via tag
|
||||
SearchJob(const Key_t& requester, uint64_t requseterTX,
|
||||
IntroSetHookFunc found, DoneFunc done);
|
||||
|
||||
void
|
||||
FoundRouter(const llarp_rc* router) const;
|
||||
|
||||
bool
|
||||
FoundIntros(
|
||||
const std::vector< llarp::service::IntroSet >& introset) const;
|
||||
|
||||
void
|
||||
Timeout() const;
|
||||
|
||||
bool
|
||||
IsExpired(llarp_time_t now) const;
|
||||
|
||||
// only set if looking up router
|
||||
llarp_router_lookup_job* job = nullptr;
|
||||
IntroSetHookFunc foundIntroHook;
|
||||
DoneFunc onDone;
|
||||
llarp_time_t started;
|
||||
Key_t requester;
|
||||
uint64_t requesterTX;
|
||||
Key_t target;
|
||||
std::set< Key_t > exclude;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef LLARP_DTLS_HPP
|
||||
#define LLARP_DTLS_HPP
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dtls
|
||||
{
|
||||
struct Base
|
||||
{
|
||||
Base(uint16_t mtu)
|
||||
{
|
||||
_ctx = SSL_CTX_new(DTLS_with_buffers_method());
|
||||
SSL_CTX_set_custom_verify(_ctx, SSL_VERIFY_PEER, []());
|
||||
}
|
||||
|
||||
~Base()
|
||||
{
|
||||
if(_ctx)
|
||||
SSL_CTX_free(_ctx);
|
||||
}
|
||||
|
||||
SSL_CTX* _ctx = nullptr;
|
||||
};
|
||||
|
||||
} // namespace dtls
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -5,12 +5,15 @@
|
|||
#include <llarp/buffer.h>
|
||||
#include <sodium.h>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
/// encrypted buffer base type
|
||||
struct Encrypted
|
||||
{
|
||||
static const size_t MAX_SIZE = (1024 * 8);
|
||||
|
||||
Encrypted(Encrypted&&) = delete;
|
||||
Encrypted(const Encrypted& other);
|
||||
Encrypted();
|
||||
|
@ -31,15 +34,13 @@ namespace llarp
|
|||
}
|
||||
|
||||
Encrypted&
|
||||
operator=(llarp_buffer_t buf)
|
||||
operator=(const llarp_buffer_t& buf)
|
||||
{
|
||||
if(_data)
|
||||
delete[] _data;
|
||||
_data = nullptr;
|
||||
_sz = buf.sz;
|
||||
if(buf.sz > MAX_SIZE)
|
||||
return *this;
|
||||
_sz = buf.sz;
|
||||
if(_sz)
|
||||
{
|
||||
_data = new byte_t[_sz];
|
||||
memcpy(_data, buf.base, _sz);
|
||||
}
|
||||
UpdateBuffer();
|
||||
|
@ -57,7 +58,7 @@ namespace llarp
|
|||
void
|
||||
Randomize()
|
||||
{
|
||||
if(_data && _sz)
|
||||
if(_sz)
|
||||
randombytes(_data, _sz);
|
||||
}
|
||||
|
||||
|
@ -69,10 +70,9 @@ namespace llarp
|
|||
return false;
|
||||
if(strbuf.sz == 0)
|
||||
return false;
|
||||
if(_data)
|
||||
delete[] _data;
|
||||
_sz = strbuf.sz;
|
||||
_data = new byte_t[_sz];
|
||||
if(strbuf.sz > MAX_SIZE)
|
||||
return false;
|
||||
_sz = strbuf.sz;
|
||||
memcpy(_data, strbuf.base, _sz);
|
||||
UpdateBuffer();
|
||||
return true;
|
||||
|
@ -116,10 +116,10 @@ namespace llarp
|
|||
m_Buffer.cur = data();
|
||||
m_Buffer.sz = size();
|
||||
}
|
||||
byte_t* _data = nullptr;
|
||||
size_t _sz = 0;
|
||||
byte_t _data[MAX_SIZE];
|
||||
size_t _sz = 0;
|
||||
llarp_buffer_t m_Buffer;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -33,11 +33,11 @@ namespace llarp
|
|||
EncryptedFrame&
|
||||
operator=(const EncryptedFrame& other)
|
||||
{
|
||||
if(_data)
|
||||
delete[] _data;
|
||||
_sz = other._sz;
|
||||
_data = new byte_t[_sz];
|
||||
memcpy(_data, other._data, _sz);
|
||||
if(other._sz <= MAX_SIZE)
|
||||
{
|
||||
_sz = other._sz;
|
||||
memcpy(_data, other._data, _sz);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef LLARP_ESTABLISH_JOB_HPP
|
||||
#define LLARP_ESTABLISH_JOB_HPP
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct OutboundLinkEstablishJob
|
||||
{
|
||||
RouterContact rc;
|
||||
|
||||
OutboundLinkEstablishJob(const RouterContact& remote) : rc(remote)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~OutboundLinkEstablishJob(){};
|
||||
|
||||
virtual void
|
||||
Success() = 0;
|
||||
|
||||
virtual void
|
||||
Failed() = 0;
|
||||
|
||||
virtual void
|
||||
AttemptTimedout() = 0;
|
||||
|
||||
virtual void
|
||||
Attempt() = 0;
|
||||
|
||||
virtual bool
|
||||
ShouldRetry() const = 0;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -52,6 +52,8 @@ llarp_ev_loop_stop(struct llarp_ev_loop *ev);
|
|||
/// UDP handling configuration
|
||||
struct llarp_udp_io
|
||||
{
|
||||
/// set after added
|
||||
int fd;
|
||||
void *user;
|
||||
void *impl;
|
||||
struct llarp_ev_loop *parent;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef LLARP_XI_HPP
|
||||
#define LLARP_XI_HPP
|
||||
#include <llarp/bencode.hpp>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/net.h>
|
||||
#include <iostream>
|
||||
#include <llarp/bits.hpp>
|
||||
|
||||
/**
|
||||
* exit_info.h
|
||||
*
|
||||
* utilities for handling exits on the llarp network
|
||||
*/
|
||||
|
||||
/// Exit info model
|
||||
namespace llarp
|
||||
{
|
||||
struct ExitInfo : public IBEncodeMessage
|
||||
{
|
||||
struct in6_addr address;
|
||||
struct in6_addr netmask;
|
||||
PubKey pubkey;
|
||||
|
||||
ExitInfo() : IBEncodeMessage()
|
||||
{
|
||||
}
|
||||
|
||||
ExitInfo(const ExitInfo &other) : IBEncodeMessage()
|
||||
{
|
||||
pubkey = other.pubkey;
|
||||
memcpy(address.s6_addr, other.address.s6_addr, 16);
|
||||
memcpy(netmask.s6_addr, other.netmask.s6_addr, 16);
|
||||
version = other.version;
|
||||
}
|
||||
|
||||
~ExitInfo();
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t *buf) const;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t k, llarp_buffer_t *buf);
|
||||
|
||||
ExitInfo &
|
||||
operator=(const ExitInfo &other);
|
||||
|
||||
friend std::ostream &
|
||||
operator<<(std::ostream &out, const ExitInfo &xi)
|
||||
{
|
||||
char tmp[128] = {0};
|
||||
if(inet_ntop(AF_INET6, &xi.address, tmp, sizeof(tmp)))
|
||||
out << std::string(tmp);
|
||||
else
|
||||
return out;
|
||||
out << std::string("/");
|
||||
return out << std::to_string(
|
||||
llarp::bits::count_array_bits(xi.netmask.s6_addr));
|
||||
}
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -16,7 +16,7 @@ typedef struct ip_hdr
|
|||
unsigned char
|
||||
ip_header_len : 4; // 4-bit header length (in 32-bit words) normally=5
|
||||
// (Means 20 Bytes may be 24 also)
|
||||
unsigned char version : 4; // 4-bit IPv4 version
|
||||
unsigned char ip_version : 4; // 4-bit IPv4 version
|
||||
unsigned char ip_tos; // IP type of service
|
||||
unsigned short ip_total_length; // Total length
|
||||
unsigned short ip_id; // Unique identifier
|
||||
|
@ -75,27 +75,27 @@ namespace llarp
|
|||
struct GetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const IPv4Packet* pkt) const
|
||||
operator()(const IPv4Packet& pkt) const
|
||||
{
|
||||
return pkt->timestamp;
|
||||
return pkt.timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
struct PutTime
|
||||
{
|
||||
void
|
||||
operator()(IPv4Packet* pkt) const
|
||||
operator()(IPv4Packet& pkt) const
|
||||
{
|
||||
pkt->timestamp = llarp_time_now_ms();
|
||||
pkt.timestamp = llarp_time_now_ms();
|
||||
}
|
||||
};
|
||||
|
||||
struct CompareOrder
|
||||
{
|
||||
bool
|
||||
operator()(const IPv4Packet* left, const IPv4Packet* right)
|
||||
operator()(const IPv4Packet& left, const IPv4Packet& right)
|
||||
{
|
||||
return left->timestamp < right->timestamp;
|
||||
return left.timestamp < right.timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ struct llarp_iwp_args
|
|||
struct llarp_logic* logic;
|
||||
struct llarp_threadpool* cryptoworker;
|
||||
struct llarp_router* router;
|
||||
std::string keyfile;
|
||||
bool permitInbound;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "llarp/address_info.h"
|
||||
|
||||
struct llarp_link;
|
||||
struct llarp_link_session;
|
||||
|
||||
struct llarp_link_establish_job
|
||||
{
|
||||
void *user;
|
||||
void (*result)(struct llarp_link_establish_job *);
|
||||
struct llarp_ai ai;
|
||||
uint64_t timeout;
|
||||
uint16_t retries;
|
||||
|
||||
byte_t pubkey[PUBKEYSIZE];
|
||||
/** set on success by try_establish */
|
||||
struct llarp_link *link;
|
||||
/** set on success by try_establish */
|
||||
struct llarp_link_session *session;
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "llarp/buffer.h"
|
||||
|
||||
enum header_flag
|
||||
{
|
||||
eSessionInvalidated = (1 << 0),
|
||||
eHighPacketDrop = (1 << 1),
|
||||
eHighMTUDetected = (1 << 2),
|
||||
eProtoUpgrade = (1 << 3)
|
||||
};
|
||||
|
||||
struct frame_header
|
||||
{
|
||||
byte_t *ptr;
|
||||
|
||||
frame_header(byte_t *buf);
|
||||
|
||||
byte_t *
|
||||
data();
|
||||
|
||||
uint8_t &
|
||||
version();
|
||||
|
||||
uint8_t &
|
||||
msgtype();
|
||||
|
||||
uint16_t
|
||||
size() const;
|
||||
|
||||
void
|
||||
setsize(uint16_t sz);
|
||||
|
||||
uint8_t &
|
||||
flags();
|
||||
|
||||
void
|
||||
setflag(header_flag f);
|
||||
};
|
|
@ -1,121 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <llarp/codel.hpp>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include "frame_header.hpp"
|
||||
#include "inbound_message.hpp"
|
||||
#include "llarp/logger.hpp"
|
||||
#include "llarp/time.h"
|
||||
#include "llarp/types.h"
|
||||
#include "sendbuf.hpp"
|
||||
#include "sendqueue.hpp"
|
||||
#include "transit_message.hpp"
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
|
||||
enum msgtype
|
||||
{
|
||||
eALIV = 0x00,
|
||||
eXMIT = 0x01,
|
||||
eACKS = 0x02,
|
||||
eFRAG = 0x03
|
||||
};
|
||||
|
||||
static inline byte_t *
|
||||
init_sendbuf(sendbuf_t *buf, msgtype t, uint16_t sz, uint8_t flags)
|
||||
{
|
||||
frame_header hdr(buf->data());
|
||||
hdr.version() = 0;
|
||||
hdr.msgtype() = t;
|
||||
hdr.setsize(sz);
|
||||
buf->data()[4] = 0;
|
||||
buf->data()[5] = flags;
|
||||
return hdr.data();
|
||||
}
|
||||
|
||||
struct llarp_router;
|
||||
struct llarp_link_session;
|
||||
|
||||
struct frame_state
|
||||
{
|
||||
byte_t rxflags = 0;
|
||||
byte_t txflags = 0;
|
||||
uint64_t rxids = 0;
|
||||
uint64_t txids = 0;
|
||||
llarp_time_t lastEvent = 0;
|
||||
std::unordered_map< uint64_t, llarp::ShortHash > rxIDs;
|
||||
std::unordered_map< llarp::ShortHash, transit_message *,
|
||||
llarp::ShortHash::Hash >
|
||||
rx;
|
||||
std::unordered_map< uint64_t, transit_message * > tx;
|
||||
|
||||
// typedef std::queue< sendbuf_t * > sendqueue_t;
|
||||
|
||||
typedef llarp::util::CoDelQueue<
|
||||
InboundMessage, InboundMessage::GetTime, InboundMessage::PutTime,
|
||||
InboundMessage::OrderCompare, llarp::util::DummyMutex,
|
||||
llarp::util::DummyLock >
|
||||
recvqueue_t;
|
||||
|
||||
llarp_link_session *parent = nullptr;
|
||||
|
||||
sendqueue_t sendqueue;
|
||||
recvqueue_t recvqueue;
|
||||
uint64_t nextMsgID = 0;
|
||||
|
||||
frame_state(llarp_link_session *session)
|
||||
: parent(session)
|
||||
, sendqueue("iwp_outbound_message")
|
||||
, recvqueue("iwp_inbound_message")
|
||||
{
|
||||
}
|
||||
|
||||
/// return true if both sides have the same state flags
|
||||
bool
|
||||
flags_agree(byte_t flags) const;
|
||||
|
||||
bool
|
||||
process_inbound_queue();
|
||||
|
||||
llarp_router *
|
||||
Router();
|
||||
|
||||
void
|
||||
clear();
|
||||
|
||||
bool
|
||||
inbound_frame_complete(uint64_t id);
|
||||
|
||||
void
|
||||
push_ackfor(uint64_t id, uint32_t bitmask);
|
||||
|
||||
bool
|
||||
got_xmit(frame_header hdr, size_t sz);
|
||||
|
||||
void
|
||||
alive();
|
||||
|
||||
bool
|
||||
got_frag(frame_header hdr, size_t sz);
|
||||
|
||||
bool
|
||||
got_acks(frame_header hdr, size_t sz);
|
||||
|
||||
// queue new outbound message
|
||||
void
|
||||
queue_tx(uint64_t id, transit_message *msg);
|
||||
|
||||
void
|
||||
retransmit(llarp_time_t now);
|
||||
|
||||
// get next frame to encrypt and transmit
|
||||
bool
|
||||
next_frame(llarp_buffer_t *buf);
|
||||
|
||||
void
|
||||
pop_next_frame();
|
||||
|
||||
bool
|
||||
process(byte_t *buf, size_t sz);
|
||||
};
|
|
@ -1,59 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "buffer.hpp"
|
||||
#include "llarp/time.h"
|
||||
#include "llarp/types.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct InboundMessage
|
||||
{
|
||||
uint64_t msgid;
|
||||
std::vector< byte_t > msg;
|
||||
llarp_time_t queued = 0;
|
||||
|
||||
InboundMessage(uint64_t id, const std::vector< byte_t > &m)
|
||||
: msgid(id), msg(m)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(const InboundMessage &other) const
|
||||
{
|
||||
// order in ascending order for codel queue
|
||||
return msgid < other.msgid;
|
||||
}
|
||||
|
||||
llarp_buffer_t
|
||||
Buffer()
|
||||
{
|
||||
return llarp::Buffer< decltype(msg) >(msg);
|
||||
}
|
||||
|
||||
struct GetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const InboundMessage *msg)
|
||||
{
|
||||
return msg->queued;
|
||||
}
|
||||
};
|
||||
|
||||
struct OrderCompare
|
||||
{
|
||||
bool
|
||||
operator()(const InboundMessage *left, const InboundMessage *right) const
|
||||
{
|
||||
return left->msgid < right->msgid;
|
||||
}
|
||||
};
|
||||
|
||||
struct PutTime
|
||||
{
|
||||
void
|
||||
operator()(InboundMessage *msg)
|
||||
{
|
||||
msg->queued = llarp_time_now_ms();
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,78 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <llarp/buffer.h>
|
||||
#include <llarp/time.h>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
struct sendbuf_t
|
||||
{
|
||||
sendbuf_t(size_t s) : sz(s)
|
||||
{
|
||||
_buf = new byte_t[s];
|
||||
}
|
||||
|
||||
~sendbuf_t()
|
||||
{
|
||||
if(_buf)
|
||||
delete[] _buf;
|
||||
}
|
||||
|
||||
size_t sz;
|
||||
|
||||
byte_t priority = 255;
|
||||
|
||||
size_t
|
||||
size() const
|
||||
{
|
||||
return sz;
|
||||
}
|
||||
|
||||
byte_t *
|
||||
data()
|
||||
{
|
||||
return _buf;
|
||||
}
|
||||
|
||||
llarp_buffer_t
|
||||
Buffer()
|
||||
{
|
||||
llarp_buffer_t buf;
|
||||
buf.base = _buf;
|
||||
buf.sz = sz;
|
||||
buf.cur = buf.base;
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct GetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const sendbuf_t *buf) const
|
||||
{
|
||||
return buf->timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
struct PutTime
|
||||
{
|
||||
void
|
||||
operator()(sendbuf_t *buf) const
|
||||
{
|
||||
buf->timestamp = llarp_time_now_ms();
|
||||
}
|
||||
};
|
||||
|
||||
struct Compare
|
||||
{
|
||||
bool
|
||||
operator()(const sendbuf_t *left, const sendbuf_t *right) const
|
||||
{
|
||||
return left->timestamp < right->timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
llarp_time_t timestamp = 0;
|
||||
|
||||
private:
|
||||
byte_t *_buf = nullptr;
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef LLARP_IWP_SENDQUEUE_HPP
|
||||
#define LLARP_IWP_SENDQUEUE_HPP
|
||||
#include <llarp/codel.hpp>
|
||||
#include <llarp/iwp/sendbuf.hpp>
|
||||
|
||||
typedef llarp::util::CoDelQueue<
|
||||
sendbuf_t, sendbuf_t::GetTime, sendbuf_t::PutTime, sendbuf_t::Compare,
|
||||
llarp::util::DummyMutex, llarp::util::DummyLock >
|
||||
sendqueue_t;
|
||||
|
||||
#endif
|
|
@ -1,170 +0,0 @@
|
|||
#pragma once
|
||||
#include <llarp/iwp.hpp>
|
||||
#include <llarp/threading.hpp>
|
||||
#include "llarp/iwp/establish_job.hpp"
|
||||
#include "router.hpp"
|
||||
#include "session.hpp"
|
||||
|
||||
#ifndef __linux__
|
||||
#ifdef saddr
|
||||
#undef saddr
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
struct llarp_link
|
||||
{
|
||||
typedef llarp::util::NullMutex mtx_t;
|
||||
typedef llarp::util::NullLock lock_t;
|
||||
|
||||
llarp_router *router;
|
||||
llarp_crypto *crypto;
|
||||
llarp_logic *logic;
|
||||
llarp_ev_loop *netloop;
|
||||
llarp_async_iwp *iwp;
|
||||
llarp_threadpool *worker;
|
||||
llarp_link *parent = nullptr;
|
||||
llarp_udp_io udp;
|
||||
llarp::Addr addr;
|
||||
std::string keyfile;
|
||||
uint32_t timeout_job_id;
|
||||
|
||||
const char *
|
||||
name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const char *m_name;
|
||||
|
||||
typedef std::unordered_map< llarp::Addr, llarp_link_session *,
|
||||
llarp::Addr::Hash >
|
||||
LinkMap_t;
|
||||
|
||||
LinkMap_t m_sessions;
|
||||
mtx_t m_sessions_Mutex;
|
||||
|
||||
typedef std::unordered_map< llarp::PubKey, llarp::Addr, llarp::PubKey::Hash >
|
||||
SessionMap_t;
|
||||
|
||||
SessionMap_t m_Connected;
|
||||
mtx_t m_Connected_Mutex;
|
||||
std::atomic< bool > pumpingLogic;
|
||||
|
||||
typedef std::unordered_map< llarp::Addr, llarp_link_session *,
|
||||
llarp::Addr::Hash >
|
||||
PendingSessionMap_t;
|
||||
PendingSessionMap_t m_PendingSessions;
|
||||
mtx_t m_PendingSessions_Mutex;
|
||||
|
||||
llarp::SecretKey seckey;
|
||||
|
||||
llarp_link(const llarp_iwp_args &args);
|
||||
|
||||
~llarp_link();
|
||||
|
||||
bool
|
||||
has_intro_from(const llarp::Addr &from);
|
||||
|
||||
void
|
||||
put_intro_from(llarp_link_session *s);
|
||||
|
||||
void
|
||||
remove_intro_from(const llarp::Addr &from);
|
||||
|
||||
// set that src address has identity pubkey
|
||||
void
|
||||
MapAddr(const llarp::Addr &src, const llarp::PubKey &identity);
|
||||
|
||||
/// does nothing if we have no session already established
|
||||
void
|
||||
KeepAliveSessionTo(const byte_t *pubkey);
|
||||
|
||||
/// does nothing if we have no session already established
|
||||
void
|
||||
CloseSessionTo(const byte_t *pubkey);
|
||||
|
||||
bool
|
||||
has_session_to(const byte_t *pubkey);
|
||||
|
||||
void
|
||||
TickSessions();
|
||||
|
||||
bool
|
||||
sendto(const byte_t *pubkey, llarp_buffer_t buf);
|
||||
|
||||
void
|
||||
UnmapAddr(const llarp::Addr &src);
|
||||
|
||||
llarp_link_session *
|
||||
create_session(const llarp::Addr &src);
|
||||
|
||||
bool
|
||||
has_session_via(const llarp::Addr &dst);
|
||||
|
||||
llarp_link_session *
|
||||
find_session(const llarp::Addr &addr);
|
||||
|
||||
void
|
||||
put_session(const llarp::Addr &src, llarp_link_session *impl);
|
||||
|
||||
void
|
||||
clear_sessions();
|
||||
|
||||
/// safe iterate sessions
|
||||
void
|
||||
iterate_sessions(std::function< bool(llarp_link_session *) > visitor);
|
||||
|
||||
static void
|
||||
handle_logic_pump(void *user);
|
||||
|
||||
void
|
||||
PumpLogic();
|
||||
|
||||
void
|
||||
RemoveSession(llarp_link_session *s);
|
||||
|
||||
const uint8_t *
|
||||
pubkey();
|
||||
|
||||
bool
|
||||
ensure_privkey();
|
||||
|
||||
bool
|
||||
keygen(const char *fname);
|
||||
|
||||
static void
|
||||
handle_cleanup_timer(void *l, uint64_t orig, uint64_t left);
|
||||
|
||||
// this is called in net threadpool
|
||||
static void
|
||||
handle_recvfrom(struct llarp_udp_io *udp, const struct sockaddr *saddr,
|
||||
const void *buf, ssize_t sz);
|
||||
|
||||
void
|
||||
cancel_timer();
|
||||
|
||||
void
|
||||
issue_cleanup_timer(uint64_t timeout);
|
||||
|
||||
void
|
||||
get_our_address(struct llarp_ai *addr);
|
||||
|
||||
static void
|
||||
after_recv(llarp_udp_io *udp);
|
||||
|
||||
bool
|
||||
configure(struct llarp_ev_loop *netloop, const char *ifname, int af,
|
||||
uint16_t port);
|
||||
|
||||
bool
|
||||
start_link(struct llarp_logic *pLogic);
|
||||
|
||||
bool
|
||||
stop_link();
|
||||
|
||||
bool
|
||||
try_establish(struct llarp_link_establish_job *job);
|
||||
};
|
|
@ -1,189 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <llarp/codel.hpp>
|
||||
#include "frame_state.hpp"
|
||||
#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"
|
||||
|
||||
struct llarp_udp_io;
|
||||
struct llarp_async_iwp;
|
||||
struct llarp_logic;
|
||||
struct llarp_link;
|
||||
struct transit_message;
|
||||
struct llarp_link_establish_job;
|
||||
|
||||
struct llarp_link_session
|
||||
{
|
||||
static constexpr llarp_time_t SESSION_TIMEOUT = 10000;
|
||||
static constexpr llarp_time_t KEEP_ALIVE_INTERVAL = SESSION_TIMEOUT / 4;
|
||||
static constexpr size_t MAX_PAD = 128;
|
||||
|
||||
llarp_link_session(llarp_link *l, const byte_t *seckey, const llarp::Addr &a);
|
||||
|
||||
~llarp_link_session();
|
||||
|
||||
void
|
||||
session_start();
|
||||
|
||||
bool sendto(llarp_buffer_t);
|
||||
|
||||
bool
|
||||
has_timed_out();
|
||||
|
||||
bool
|
||||
timedout(llarp_time_t now, llarp_time_t timeout = SESSION_TIMEOUT);
|
||||
|
||||
void
|
||||
close();
|
||||
|
||||
void
|
||||
session_established();
|
||||
|
||||
llarp_link *
|
||||
get_parent();
|
||||
llarp_rc *
|
||||
get_remote_router();
|
||||
|
||||
bool
|
||||
CheckRCValid();
|
||||
bool
|
||||
IsEstablished();
|
||||
void
|
||||
send_LIM();
|
||||
bool
|
||||
is_invalidated() const;
|
||||
|
||||
void
|
||||
done();
|
||||
|
||||
void
|
||||
pump();
|
||||
|
||||
void
|
||||
introduce(uint8_t *pub);
|
||||
|
||||
void
|
||||
intro_ack();
|
||||
|
||||
void
|
||||
on_intro_ack(const void *buf, size_t sz);
|
||||
|
||||
void
|
||||
on_intro(const void *buf, size_t sz);
|
||||
|
||||
void
|
||||
on_session_start(const void *buf, size_t sz);
|
||||
|
||||
void
|
||||
encrypt_frame_async_send(const void *buf, size_t sz);
|
||||
|
||||
// void send_keepalive(void *user);
|
||||
bool
|
||||
Tick(llarp_time_t now);
|
||||
|
||||
void
|
||||
keepalive();
|
||||
|
||||
void
|
||||
PumpCryptoOutbound();
|
||||
|
||||
// process inbound and outbound queues (logic thread)
|
||||
void
|
||||
TickLogic(llarp_time_t now);
|
||||
|
||||
// this is called from net thread
|
||||
void
|
||||
recv(const void *buf, size_t sz);
|
||||
|
||||
llarp_router *
|
||||
Router();
|
||||
|
||||
llarp_udp_io *udp = nullptr;
|
||||
llarp_crypto *crypto = nullptr;
|
||||
llarp_async_iwp *iwp = nullptr;
|
||||
|
||||
llarp_link *serv = nullptr;
|
||||
|
||||
llarp_rc *our_router = nullptr;
|
||||
llarp_rc remote_router;
|
||||
|
||||
llarp::SecretKey eph_seckey;
|
||||
llarp::PubKey remote;
|
||||
llarp::SharedSecret sessionkey;
|
||||
|
||||
llarp_link_establish_job *establish_job = nullptr;
|
||||
|
||||
llarp_time_t createdAt = 0;
|
||||
llarp_time_t lastKeepalive = 0;
|
||||
uint32_t establish_job_id = 0;
|
||||
uint32_t frames = 0;
|
||||
std::atomic< bool > working;
|
||||
|
||||
llarp::util::CoDelQueue< iwp_async_frame, FrameGetTime, FramePutTime,
|
||||
FrameCompareTime >
|
||||
outboundFrames;
|
||||
|
||||
llarp::util::CoDelQueue< iwp_async_frame, FrameGetTime, FramePutTime,
|
||||
FrameCompareTime >
|
||||
decryptedFrames;
|
||||
|
||||
llarp::Addr addr;
|
||||
iwp_async_intro intro;
|
||||
iwp_async_introack introack;
|
||||
iwp_async_session_start start;
|
||||
|
||||
/// timestamp last intro packet sent at
|
||||
llarp_time_t lastIntroSentAt = 0;
|
||||
uint32_t intro_resend_job_id = 0;
|
||||
|
||||
byte_t token[32];
|
||||
byte_t workbuf[MAX_PAD + 128];
|
||||
|
||||
enum State
|
||||
{
|
||||
eInitial,
|
||||
eIntroRecv,
|
||||
eIntroSent,
|
||||
eIntroAckSent,
|
||||
eIntroAckRecv,
|
||||
eSessionStartSent,
|
||||
eLIMSent,
|
||||
eEstablished,
|
||||
eTimeout
|
||||
};
|
||||
|
||||
State state;
|
||||
void
|
||||
EnterState(State st);
|
||||
|
||||
void
|
||||
add_outbound_message(uint64_t id, transit_message *msg);
|
||||
void
|
||||
EncryptOutboundFrames();
|
||||
|
||||
iwp_async_frame *
|
||||
alloc_frame(const void *buf, size_t sz);
|
||||
void
|
||||
decrypt_frame(const void *buf, size_t sz);
|
||||
|
||||
static void
|
||||
handle_frame_decrypt(iwp_async_frame *f);
|
||||
|
||||
static void
|
||||
handle_introack_timeout(void *user, uint64_t timeout, uint64_t left);
|
||||
|
||||
frame_state frame;
|
||||
};
|
||||
|
||||
struct llarp_link_session_iter
|
||||
{
|
||||
void *user;
|
||||
struct llarp_link *link;
|
||||
bool (*visit)(struct llarp_link_session_iter *, struct llarp_link_session *);
|
||||
};
|
|
@ -1,74 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "llarp/types.h"
|
||||
#include "sendbuf.hpp"
|
||||
#include "sendqueue.hpp"
|
||||
#include "xmit.hpp"
|
||||
|
||||
#include <bitset>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct transit_message
|
||||
{
|
||||
xmit msginfo;
|
||||
std::bitset< 32 > status = {};
|
||||
|
||||
typedef std::vector< byte_t > fragment_t;
|
||||
|
||||
std::unordered_map< byte_t, fragment_t > frags;
|
||||
fragment_t lastfrag;
|
||||
llarp_time_t lastAck = 0;
|
||||
llarp_time_t lastRetransmit = 0;
|
||||
llarp_time_t started;
|
||||
|
||||
void
|
||||
clear();
|
||||
|
||||
// calculate acked bitmask
|
||||
uint32_t
|
||||
get_bitmask() const;
|
||||
|
||||
// outbound
|
||||
transit_message(llarp_buffer_t buf, const byte_t *hash, uint64_t id,
|
||||
uint16_t mtu = 1024);
|
||||
|
||||
// inbound
|
||||
transit_message(const xmit &x);
|
||||
|
||||
/// ack packets based off a bitmask
|
||||
void
|
||||
ack(uint32_t bitmask);
|
||||
|
||||
bool
|
||||
should_send_ack(llarp_time_t now) const;
|
||||
|
||||
bool
|
||||
should_resend_frags(llarp_time_t now) const;
|
||||
|
||||
bool
|
||||
should_resend_xmit(llarp_time_t now) const;
|
||||
bool
|
||||
completed() const;
|
||||
|
||||
// template < typename T >
|
||||
void
|
||||
generate_xmit(sendqueue_t &queue, byte_t flags = 0);
|
||||
|
||||
// template < typename T >
|
||||
void
|
||||
retransmit_frags(sendqueue_t &queue, byte_t flags = 0);
|
||||
|
||||
bool
|
||||
reassemble(std::vector< byte_t > &buffer);
|
||||
|
||||
void
|
||||
put_message(llarp_buffer_t buf, const byte_t *hash, uint64_t id,
|
||||
uint16_t mtu = 1024);
|
||||
|
||||
void
|
||||
put_lastfrag(byte_t *buf, size_t sz);
|
||||
|
||||
bool
|
||||
put_frag(byte_t fragno, byte_t *buf);
|
||||
};
|
|
@ -1,43 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "llarp/buffer.h"
|
||||
|
||||
struct xmit
|
||||
{
|
||||
byte_t buffer[48];
|
||||
|
||||
xmit() = default;
|
||||
|
||||
xmit(byte_t *ptr);
|
||||
|
||||
xmit(const xmit &other);
|
||||
|
||||
void
|
||||
set_info(const byte_t *hash, uint64_t id, uint16_t fragsz, uint16_t lastsz,
|
||||
uint8_t numfrags, uint8_t flags = 0x01);
|
||||
|
||||
const byte_t *
|
||||
hash() const;
|
||||
|
||||
uint64_t
|
||||
msgid() const;
|
||||
|
||||
// size of each full fragment
|
||||
uint16_t
|
||||
fragsize() const;
|
||||
|
||||
// number of full fragments
|
||||
uint8_t
|
||||
numfrags() const;
|
||||
|
||||
// size of the entire message
|
||||
size_t
|
||||
totalsize() const;
|
||||
|
||||
// size of the last fragment
|
||||
uint16_t
|
||||
lastfrag() const;
|
||||
|
||||
uint8_t
|
||||
flags();
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef LLARP_LINK_CURVECP_HPP
|
||||
#define LLARP_LINK_CURVECP_HPP
|
||||
|
||||
#include <llarp/link_layer.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace curvecp
|
||||
{
|
||||
std::unique_ptr< ILinkLayer >
|
||||
NewServer(llarp_router* r);
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -0,0 +1,142 @@
|
|||
#ifndef LLARP_LINK_SERVER_HPP
|
||||
#define LLARP_LINK_SERVER_HPP
|
||||
#include <unordered_map>
|
||||
#include <llarp/threading.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/net.hpp>
|
||||
#include <llarp/ev.h>
|
||||
#include <llarp/link/session.hpp>
|
||||
#include <llarp/logic.h>
|
||||
#include <list>
|
||||
|
||||
struct llarp_router;
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct ILinkLayer
|
||||
{
|
||||
virtual ~ILinkLayer();
|
||||
|
||||
bool
|
||||
HasSessionTo(const PubKey& pk);
|
||||
|
||||
bool
|
||||
HasSessionVia(const Addr& addr);
|
||||
|
||||
static void
|
||||
udp_tick(llarp_udp_io* udp)
|
||||
{
|
||||
static_cast< ILinkLayer* >(udp->user)->Pump();
|
||||
}
|
||||
|
||||
static void
|
||||
udp_recv_from(llarp_udp_io* udp, const sockaddr* from, const void* buf,
|
||||
const ssize_t sz)
|
||||
{
|
||||
static_cast< ILinkLayer* >(udp->user)->RecvFrom(*from, buf, sz);
|
||||
}
|
||||
|
||||
bool
|
||||
Configure(llarp_ev_loop* loop, const std::string& ifname, int af,
|
||||
uint16_t port);
|
||||
|
||||
virtual ILinkSession*
|
||||
NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0;
|
||||
|
||||
virtual void
|
||||
Pump();
|
||||
|
||||
virtual void
|
||||
RecvFrom(const Addr& from, const void* buf, size_t sz) = 0;
|
||||
|
||||
bool
|
||||
PickAddress(const RouterContact& rc, AddressInfo& picked) const;
|
||||
|
||||
void
|
||||
TryEstablishTo(const RouterContact& rc);
|
||||
|
||||
bool
|
||||
Start(llarp_logic* l);
|
||||
|
||||
void
|
||||
Stop();
|
||||
|
||||
virtual const char*
|
||||
Name() const = 0;
|
||||
|
||||
void
|
||||
CloseSessionTo(const PubKey& remote);
|
||||
|
||||
void
|
||||
KeepAliveSessionTo(const PubKey& remote);
|
||||
|
||||
bool
|
||||
SendTo(const PubKey& remote, llarp_buffer_t buf);
|
||||
|
||||
bool
|
||||
GetOurAddressInfo(AddressInfo& addr) const;
|
||||
|
||||
void
|
||||
RemoveSessionVia(const Addr& addr);
|
||||
|
||||
virtual uint16_t
|
||||
Rank() const = 0;
|
||||
|
||||
virtual bool
|
||||
KeyGen(SecretKey&) = 0;
|
||||
|
||||
const byte_t*
|
||||
TransportPubKey() const;
|
||||
|
||||
const byte_t*
|
||||
TransportSecretKey() const;
|
||||
|
||||
bool
|
||||
EnsureKeys(const char* fpath);
|
||||
|
||||
void
|
||||
MapAddr(const PubKey& pk, ILinkSession* s);
|
||||
|
||||
virtual void
|
||||
Tick(llarp_time_t now)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
static void
|
||||
on_timer_tick(void* user, uint64_t orig, uint64_t left)
|
||||
{
|
||||
// timer cancelled
|
||||
if(left)
|
||||
return;
|
||||
static_cast< ILinkLayer* >(user)->OnTick(orig, llarp_time_now_ms());
|
||||
}
|
||||
|
||||
void
|
||||
OnTick(uint64_t interval, llarp_time_t now);
|
||||
|
||||
void
|
||||
ScheduleTick(uint64_t interval);
|
||||
|
||||
uint32_t tick_id;
|
||||
|
||||
protected:
|
||||
void
|
||||
PutSession(const Addr& addr, ILinkSession* s);
|
||||
|
||||
llarp_logic* m_Logic = nullptr;
|
||||
Addr m_ourAddr;
|
||||
llarp_udp_io m_udp;
|
||||
SecretKey m_SecretKey;
|
||||
|
||||
util::Mutex m_AuthedLinksMutex;
|
||||
std::unordered_multimap< PubKey, std::unique_ptr< ILinkSession >,
|
||||
PubKey::Hash >
|
||||
m_AuthedLinks;
|
||||
util::Mutex m_PendingMutex;
|
||||
std::list< std::unique_ptr< ILinkSession > > m_Pending;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef LLARP_LINK_SESSION_HPP
|
||||
#define LLARP_LINK_SESSION_HPP
|
||||
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/net.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct LinkIntroMessage;
|
||||
struct ILinkMessage;
|
||||
struct ILinkLayer;
|
||||
struct ILinkSession
|
||||
{
|
||||
virtual ~ILinkSession(){};
|
||||
|
||||
/// called every event loop tick
|
||||
std::function< void(void) > Pump;
|
||||
|
||||
/// called every timer tick
|
||||
std::function< void(llarp_time_t) > Tick;
|
||||
|
||||
/// send a message buffer to the remote endpoint
|
||||
std::function< bool(llarp_buffer_t) > SendMessageBuffer;
|
||||
|
||||
/// start the connection
|
||||
std::function< void(void) > Start;
|
||||
|
||||
/// send a keepalive to the remote endpoint
|
||||
std::function< bool(void) > SendKeepAlive;
|
||||
|
||||
/// send close message
|
||||
std::function< void(void) > SendClose;
|
||||
|
||||
/// return true if we are established
|
||||
std::function< bool(void) > IsEstablished;
|
||||
|
||||
/// return true if this session has timed out
|
||||
std::function< bool(llarp_time_t) > TimedOut;
|
||||
|
||||
/// get remote public identity key
|
||||
std::function< const PubKey &(void) > GetPubKey;
|
||||
/// get remote address
|
||||
std::function< const Addr &(void) > GetRemoteEndpoint;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef LLARP_LINK_UTP_HPP
|
||||
#define LLARP_LINK_UTP_HPP
|
||||
|
||||
#include <llarp/link_layer.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace utp
|
||||
{
|
||||
std::unique_ptr< ILinkLayer >
|
||||
NewServer(llarp_router* r);
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef LLARP_LINK_LAYER_HPP
|
||||
#define LLARP_LINK_LAYER_HPP
|
||||
#include <llarp/link/server.hpp>
|
||||
#include <llarp/link/session.hpp>
|
||||
constexpr size_t MAX_LINK_MSG_SIZE = 8192;
|
||||
#endif
|
|
@ -3,29 +3,36 @@
|
|||
|
||||
#include <llarp/bencode.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
#include <llarp/link/session.hpp>
|
||||
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
struct llarp_router;
|
||||
struct llarp_link_session;
|
||||
struct llarp_link_session_iter;
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct ILinkMessage;
|
||||
struct ILinkSession;
|
||||
|
||||
typedef std::queue< ILinkMessage* > SendQueue;
|
||||
|
||||
/// parsed link layer message
|
||||
struct ILinkMessage : public IBEncodeMessage
|
||||
{
|
||||
/// who did this message come from (rc.k)
|
||||
RouterID remote = {};
|
||||
/// who did this message come from or is going to
|
||||
ILinkSession* session;
|
||||
uint64_t version = 0;
|
||||
|
||||
ILinkMessage() = default;
|
||||
ILinkMessage(const RouterID& id);
|
||||
ILinkMessage() : ILinkMessage(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ILinkMessage(ILinkSession* from) : session(from)
|
||||
{
|
||||
}
|
||||
virtual ~ILinkMessage()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool
|
||||
HandleMessage(llarp_router* router) const = 0;
|
||||
|
@ -41,13 +48,17 @@ namespace llarp
|
|||
|
||||
/// start processig message from a link session
|
||||
bool
|
||||
ProcessFrom(llarp_link_session* from, llarp_buffer_t buf);
|
||||
ProcessFrom(ILinkSession* from, llarp_buffer_t buf);
|
||||
|
||||
/// called when the message is fully read
|
||||
/// return true when the message was accepted otherwise returns false
|
||||
bool
|
||||
MessageDone();
|
||||
|
||||
/// resets internal state
|
||||
void
|
||||
Reset();
|
||||
|
||||
private:
|
||||
RouterID
|
||||
GetCurrentFrom();
|
||||
|
@ -55,8 +66,8 @@ namespace llarp
|
|||
private:
|
||||
bool firstkey;
|
||||
llarp_router* router;
|
||||
llarp_link_session* from;
|
||||
ILinkMessage* msg = nullptr;
|
||||
ILinkSession* from = nullptr;
|
||||
std::unique_ptr< ILinkMessage > msg;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace llarp
|
|||
|
||||
template < typename T, size_t align = 128 >
|
||||
void
|
||||
DumpBuffer(const T &buff)
|
||||
DumpBufferHex(const T &buff)
|
||||
{
|
||||
size_t idx = 0;
|
||||
printf("buffer of size %zu\n", buff.sz);
|
||||
|
@ -51,7 +51,7 @@ namespace llarp
|
|||
|
||||
template < typename T, size_t align = 128 >
|
||||
void
|
||||
DumpBufferHex(const T &buff)
|
||||
DumpBuffer(const T &buff)
|
||||
{
|
||||
size_t idx = 0;
|
||||
printf("buffer of size %zu\n", buff.sz);
|
||||
|
@ -65,6 +65,10 @@ namespace llarp
|
|||
{
|
||||
printf("%c", buff.base[idx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
if(buff.base + idx == buff.cur)
|
||||
{
|
||||
printf("%c[0;0m", 27);
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
#include <llarp/messages/dht_immediate.hpp>
|
||||
#include <llarp/messages/link_intro.hpp>
|
||||
#include <llarp/messages/relay.hpp>
|
||||
#include <llarp/messages/relay_ack.hpp>
|
||||
#include <llarp/messages/relay_commit.hpp>
|
||||
|
||||
#include <llarp/messages/discard.hpp>
|
||||
#include <llarp/messages/path_confirm.hpp>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace llarp
|
|||
{
|
||||
struct DHTMessage : public IMessage
|
||||
{
|
||||
std::vector< llarp::dht::IMessage* > M;
|
||||
std::vector< std::unique_ptr< llarp::dht::IMessage > > M;
|
||||
uint64_t V = 0;
|
||||
|
||||
~DHTMessage();
|
||||
|
@ -28,4 +28,4 @@ namespace llarp
|
|||
} // namespace routing
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -8,13 +8,17 @@ namespace llarp
|
|||
{
|
||||
struct DHTImmeidateMessage : public ILinkMessage
|
||||
{
|
||||
DHTImmeidateMessage(const RouterID& from) : ILinkMessage(from)
|
||||
DHTImmeidateMessage(ILinkSession* parent) : ILinkMessage(parent)
|
||||
{
|
||||
}
|
||||
|
||||
DHTImmeidateMessage() : ILinkMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~DHTImmeidateMessage();
|
||||
|
||||
std::vector< llarp::dht::IMessage* > msgs;
|
||||
std::vector< std::unique_ptr< llarp::dht::IMessage > > msgs;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef LLARP_MESSAGES_DISCARD_HPP
|
||||
#define LLARP_MESSAGES_DISCARD_HPP
|
||||
#include <llarp/link_message.hpp>
|
||||
#include <llarp/bencode.hpp>
|
||||
namespace llarp
|
||||
{
|
||||
struct DiscardMessage : public ILinkMessage
|
||||
{
|
||||
/// who did this message come from or is going to
|
||||
|
||||
DiscardMessage() : ILinkMessage(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DiscardMessage(ILinkSession* from) : ILinkMessage(from)
|
||||
{
|
||||
}
|
||||
|
||||
~DiscardMessage()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
if(!bencode_start_dict(buf))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buf, "a", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buf, "x", 1))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
HandleMessage(llarp_router* router) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -1,17 +1,26 @@
|
|||
#ifndef LLARP_MESSAGES_LINK_INTRO_HPP
|
||||
#define LLARP_MESSAGES_LINK_INTRO_HPP
|
||||
#include <llarp/link_message.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
namespace llarp
|
||||
{
|
||||
struct ILinkSession;
|
||||
|
||||
struct LinkIntroMessage : public ILinkMessage
|
||||
{
|
||||
LinkIntroMessage(llarp_rc* rc) : ILinkMessage(), RC(rc)
|
||||
LinkIntroMessage() : ILinkMessage()
|
||||
{
|
||||
}
|
||||
|
||||
LinkIntroMessage(ILinkSession* s) : ILinkMessage(s)
|
||||
{
|
||||
}
|
||||
|
||||
~LinkIntroMessage();
|
||||
|
||||
llarp_rc* RC;
|
||||
RouterContact rc;
|
||||
|
||||
KeyExchangeNonce N;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace llarp
|
|||
TunnelNonce Y;
|
||||
|
||||
RelayUpstreamMessage();
|
||||
RelayUpstreamMessage(const RouterID& from);
|
||||
RelayUpstreamMessage(ILinkSession* from);
|
||||
~RelayUpstreamMessage();
|
||||
|
||||
bool
|
||||
|
@ -35,7 +35,7 @@ namespace llarp
|
|||
Encrypted X;
|
||||
TunnelNonce Y;
|
||||
RelayDownstreamMessage();
|
||||
RelayDownstreamMessage(const RouterID& from);
|
||||
RelayDownstreamMessage(ILinkSession* from);
|
||||
~RelayDownstreamMessage();
|
||||
|
||||
bool
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef LLARP_MESSAGES_RELAY_ACK_HPP
|
||||
#define LLARP_MESSAGES_RELAY_ACK_HPP
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/encrypted_frame.hpp>
|
||||
#include <llarp/link_message.hpp>
|
||||
#include <llarp/path_types.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct LR_AckRecord
|
||||
{
|
||||
uint64_t version = 0;
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const;
|
||||
|
||||
bool
|
||||
BDecode(llarp_buffer_t* buf);
|
||||
};
|
||||
|
||||
struct LR_AckMessage : public ILinkMessage
|
||||
{
|
||||
std::vector< EncryptedFrame > replies;
|
||||
uint64_t version = 0;
|
||||
|
||||
LR_AckMessage(const RouterID& from);
|
||||
|
||||
~LR_AckMessage();
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const;
|
||||
|
||||
bool
|
||||
HandleMessage(llarp_router* router) const;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -45,14 +45,13 @@ namespace llarp
|
|||
|
||||
struct LR_CommitMessage : public ILinkMessage
|
||||
{
|
||||
std::vector< EncryptedFrame > frames;
|
||||
uint64_t version;
|
||||
std::array< EncryptedFrame, 8 > frames;
|
||||
|
||||
LR_CommitMessage() : ILinkMessage()
|
||||
{
|
||||
}
|
||||
|
||||
LR_CommitMessage(const RouterID &from) : ILinkMessage(from)
|
||||
LR_CommitMessage(ILinkSession *from) : ILinkMessage(from)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef LLARP_NET_HPP
|
||||
#define LLARP_NET_HPP
|
||||
#include <llarp/address_info.h>
|
||||
#include <llarp/address_info.hpp>
|
||||
#include <llarp/net.h>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
@ -12,12 +12,21 @@
|
|||
bool
|
||||
operator==(const sockaddr& a, const sockaddr& b);
|
||||
|
||||
bool
|
||||
operator==(const sockaddr_in& a, const sockaddr_in& b);
|
||||
|
||||
bool
|
||||
operator==(const sockaddr_in6& a, const sockaddr_in6& b);
|
||||
|
||||
bool
|
||||
operator<(const sockaddr_in6& a, const sockaddr_in6& b);
|
||||
|
||||
bool
|
||||
operator<(const in6_addr& a, const in6_addr& b);
|
||||
|
||||
bool
|
||||
operator==(const in6_addr& a, const in6_addr& b);
|
||||
|
||||
struct privatesInUse
|
||||
{
|
||||
bool ten; // 16m ips
|
||||
|
@ -44,6 +53,16 @@ namespace llarp
|
|||
memcpy(&_addr4, &other._addr4, sizeof(sockaddr_in));
|
||||
}
|
||||
|
||||
void
|
||||
port(uint16_t port)
|
||||
{
|
||||
if(af() == AF_INET)
|
||||
{
|
||||
_addr4.sin_port = htons(port);
|
||||
}
|
||||
_addr.sin6_port = htons(port);
|
||||
}
|
||||
|
||||
in6_addr*
|
||||
addr6()
|
||||
{
|
||||
|
@ -87,7 +106,7 @@ namespace llarp
|
|||
ip[3] = four;
|
||||
}
|
||||
|
||||
Addr(const llarp_ai& other)
|
||||
Addr(const AddressInfo& other)
|
||||
{
|
||||
memcpy(addr6(), other.ip.s6_addr, 16);
|
||||
_addr.sin6_port = htons(other.port);
|
||||
|
@ -106,6 +125,42 @@ namespace llarp
|
|||
_addr.sin6_family = AF_INET6;
|
||||
}
|
||||
|
||||
Addr(const sockaddr_in& other)
|
||||
{
|
||||
llarp::Zero(&_addr, sizeof(sockaddr_in6));
|
||||
_addr.sin6_family = AF_INET;
|
||||
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
|
||||
uint16_t* port = &_addr.sin6_port;
|
||||
// SIIT
|
||||
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
|
||||
sizeof(in_addr));
|
||||
addrptr[11] = 0xff;
|
||||
addrptr[10] = 0xff;
|
||||
*port = ((sockaddr_in*)(&other))->sin_port;
|
||||
_addr4.sin_family = AF_INET;
|
||||
_addr4.sin_port = *port;
|
||||
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
|
||||
}
|
||||
|
||||
Addr(const sockaddr_in6& other)
|
||||
{
|
||||
memcpy(addr6(), other.sin6_addr.s6_addr, 16);
|
||||
_addr.sin6_port = htons(other.sin6_port);
|
||||
auto ptr = &_addr.sin6_addr.s6_addr[0];
|
||||
// TODO: detect SIIT better
|
||||
if(ptr[11] == 0xff && ptr[10] == 0xff && ptr[9] == 0 && ptr[8] == 0
|
||||
&& ptr[7] == 0 && ptr[6] == 0 && ptr[5] == 0 && ptr[4] == 0
|
||||
&& ptr[3] == 0 && ptr[2] == 0 && ptr[1] == 0 && ptr[0] == 0)
|
||||
{
|
||||
_addr4.sin_family = AF_INET;
|
||||
_addr4.sin_port = htons(other.sin6_port);
|
||||
_addr.sin6_family = AF_INET;
|
||||
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
|
||||
}
|
||||
else
|
||||
_addr.sin6_family = AF_INET6;
|
||||
}
|
||||
|
||||
Addr(const sockaddr& other)
|
||||
{
|
||||
llarp::Zero(&_addr, sizeof(sockaddr_in6));
|
||||
|
@ -240,6 +295,38 @@ namespace llarp
|
|||
&& port() == other.port();
|
||||
}
|
||||
|
||||
Addr&
|
||||
operator=(const sockaddr& other)
|
||||
{
|
||||
llarp::Zero(&_addr, sizeof(sockaddr_in6));
|
||||
_addr.sin6_family = other.sa_family;
|
||||
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
|
||||
uint16_t* port = &_addr.sin6_port;
|
||||
switch(other.sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
// SIIT
|
||||
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
|
||||
sizeof(in_addr));
|
||||
addrptr[11] = 0xff;
|
||||
addrptr[10] = 0xff;
|
||||
*port = ((sockaddr_in*)(&other))->sin_port;
|
||||
_addr4.sin_family = AF_INET;
|
||||
_addr4.sin_port = *port;
|
||||
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr.s6_addr,
|
||||
16);
|
||||
*port = ((sockaddr_in6*)(&other))->sin6_port;
|
||||
break;
|
||||
// TODO : sockaddr_ll
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
sameAddr(const Addr& other) const
|
||||
{
|
||||
|
@ -283,6 +370,15 @@ namespace llarp
|
|||
return byte1 == 192 && byte2 == 168;
|
||||
}
|
||||
|
||||
socklen_t
|
||||
SockLen() const
|
||||
{
|
||||
if(af() == AF_INET)
|
||||
return sizeof(sockaddr_in);
|
||||
else
|
||||
return sizeof(sockaddr_in6);
|
||||
}
|
||||
|
||||
bool
|
||||
isPrivate()
|
||||
{
|
||||
|
@ -306,16 +402,23 @@ namespace llarp
|
|||
{
|
||||
return a.port() ^ a.addr4()->s_addr;
|
||||
}
|
||||
uint8_t empty[16] = {0};
|
||||
static const uint8_t empty[16] = {0};
|
||||
return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
bool
|
||||
AllInterfaces(int af, Addr& addr);
|
||||
|
||||
/// get first network interface with public address
|
||||
bool
|
||||
GetBestNetIF(std::string& ifname, int af = AF_INET);
|
||||
|
||||
/// get network interface address for network interface with ifname
|
||||
bool
|
||||
GetIFAddr(const std::string& ifname, Addr& addr, int af = AF_INET);
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#ifndef LLARP_NODEDB_H
|
||||
#define LLARP_NODEDB_H
|
||||
#ifndef LLARP_NODEDB_HPP
|
||||
#define LLARP_NODEDB_HPP
|
||||
#include <llarp/common.h>
|
||||
#include <llarp/crypto.h>
|
||||
#include <llarp/router_contact.h>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
|
||||
/**
|
||||
* nodedb.h
|
||||
* nodedb.hpp
|
||||
*
|
||||
* persistent storage API for router contacts
|
||||
*/
|
||||
|
@ -39,7 +40,7 @@ llarp_nodedb_store_dir(struct llarp_nodedb *n, const char *dir);
|
|||
struct llarp_nodedb_iter
|
||||
{
|
||||
void *user;
|
||||
struct llarp_rc *rc;
|
||||
llarp::RouterContact *rc;
|
||||
size_t index;
|
||||
bool (*visit)(struct llarp_nodedb_iter *);
|
||||
};
|
||||
|
@ -48,15 +49,6 @@ struct llarp_nodedb_iter
|
|||
int
|
||||
llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i);
|
||||
|
||||
/// get a random rc that is loaded
|
||||
void
|
||||
llarp_nodedb_get_random_rc(struct llarp_nodedb *n, struct llarp_rc *result);
|
||||
|
||||
/// select a random rc at hop number N
|
||||
void
|
||||
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
|
||||
struct llarp_rc *result, size_t N);
|
||||
|
||||
/// return number of RC loaded
|
||||
size_t
|
||||
llarp_nodedb_num_loaded(struct llarp_nodedb *n);
|
||||
|
@ -68,11 +60,11 @@ llarp_nodedb_num_loaded(struct llarp_nodedb *n);
|
|||
returns true on success and false on error
|
||||
*/
|
||||
bool
|
||||
llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc);
|
||||
llarp_nodedb_put_rc(struct llarp_nodedb *n, const llarp::RouterContact &rc);
|
||||
|
||||
/// return a pointer to an already loaded RC or nullptr if it's not there
|
||||
struct llarp_rc *
|
||||
llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk);
|
||||
bool
|
||||
llarp_nodedb_get_rc(struct llarp_nodedb *n, const llarp::RouterID &pk,
|
||||
llarp::RouterContact &result);
|
||||
|
||||
/// struct for async rc verification
|
||||
struct llarp_async_verify_rc;
|
||||
|
@ -94,7 +86,7 @@ struct llarp_async_verify_rc
|
|||
struct llarp_threadpool *diskworker;
|
||||
|
||||
/// router contact
|
||||
struct llarp_rc rc;
|
||||
llarp::RouterContact rc;
|
||||
/// result
|
||||
bool valid;
|
||||
/// hook
|
||||
|
@ -125,9 +117,9 @@ struct llarp_async_load_rc
|
|||
/// disk worker threadpool
|
||||
struct llarp_threadpool *diskworker;
|
||||
/// target pubkey
|
||||
byte_t pubkey[PUBKEYSIZE];
|
||||
llarp::PubKey pubkey;
|
||||
/// router contact result
|
||||
struct llarp_rc rc;
|
||||
llarp::RouterContact result;
|
||||
/// set to true if we loaded the rc
|
||||
bool loaded;
|
||||
/// hook function called in logic thread
|
||||
|
@ -138,4 +130,9 @@ struct llarp_async_load_rc
|
|||
void
|
||||
llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job);
|
||||
|
||||
bool
|
||||
llarp_nodedb_select_random_hop(struct llarp_nodedb *n,
|
||||
const llarp::RouterContact &prev,
|
||||
llarp::RouterContact &result, size_t N);
|
||||
|
||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef LLARP_PATH_H
|
||||
#define LLARP_PATH_H
|
||||
|
||||
#include <llarp/router_contact.h>
|
||||
|
||||
#define MAXHOPS (8)
|
||||
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
|
||||
#define PATH_BUILD_TIMEOUT (10 * 1000)
|
||||
#define MESSAGE_PAD_SIZE (1024)
|
||||
|
||||
struct llarp_path_hop
|
||||
{
|
||||
struct llarp_rc router;
|
||||
byte_t nextHop[PUBKEYSIZE];
|
||||
byte_t sessionkey[SHAREDKEYSIZE];
|
||||
byte_t pathid[PATHIDSIZE];
|
||||
};
|
||||
|
||||
struct llarp_path_hops
|
||||
{
|
||||
struct llarp_path_hop hops[MAXHOPS];
|
||||
size_t numHops;
|
||||
};
|
||||
|
||||
void
|
||||
llarp_path_hops_free(struct llarp_path_hops* hops);
|
||||
|
||||
#endif
|
|
@ -1,6 +1,5 @@
|
|||
#ifndef LLARP_PATH_HPP
|
||||
#define LLARP_PATH_HPP
|
||||
#include <llarp/path.h>
|
||||
#include <llarp/router.h>
|
||||
#include <llarp/time.h>
|
||||
#include <llarp/aligned.hpp>
|
||||
|
@ -10,6 +9,7 @@
|
|||
#include <llarp/messages/relay_commit.hpp>
|
||||
#include <llarp/path_types.hpp>
|
||||
#include <llarp/pathset.hpp>
|
||||
#include <llarp/pathbuilder.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
#include <llarp/routing/handler.hpp>
|
||||
#include <llarp/routing/message.hpp>
|
||||
|
@ -22,6 +22,11 @@
|
|||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#define MAXHOPS (8)
|
||||
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
|
||||
#define PATH_BUILD_TIMEOUT (10 * 1000)
|
||||
#define MESSAGE_PAD_SIZE (1024)
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace path
|
||||
|
@ -193,7 +198,7 @@ namespace llarp
|
|||
/// path id
|
||||
PathID_t txID, rxID;
|
||||
// router contact of router
|
||||
llarp_rc router;
|
||||
RouterContact rc;
|
||||
// temp public encryption key
|
||||
SecretKey commkey;
|
||||
/// shared secret at this hop
|
||||
|
@ -226,7 +231,7 @@ namespace llarp
|
|||
llarp_time_t buildStarted;
|
||||
PathStatus status;
|
||||
|
||||
Path(llarp_path_hops* path);
|
||||
Path(const std::vector< RouterContact >& routers);
|
||||
|
||||
void
|
||||
SetBuildResultHook(BuildResultHookFunc func);
|
||||
|
@ -338,7 +343,7 @@ namespace llarp
|
|||
|
||||
/// track a path builder with this context
|
||||
void
|
||||
AddPathBuilder(llarp_pathbuilder_context* set);
|
||||
AddPathBuilder(Builder* set);
|
||||
|
||||
void
|
||||
AllowTransit();
|
||||
|
@ -371,7 +376,7 @@ namespace llarp
|
|||
|
||||
bool
|
||||
ForwardLRCM(const RouterID& nextHop,
|
||||
std::deque< EncryptedFrame >& frames);
|
||||
const std::array< EncryptedFrame, 8 >& frames);
|
||||
|
||||
bool
|
||||
HopIsUs(const PubKey& k) const;
|
||||
|
@ -386,7 +391,7 @@ namespace llarp
|
|||
AddOwnPath(PathSet* set, Path* p);
|
||||
|
||||
void
|
||||
RemovePathBuilder(llarp_pathbuilder_context* ctx);
|
||||
RemovePathBuilder(Builder* ctx);
|
||||
|
||||
void
|
||||
RemovePathSet(PathSet* set);
|
||||
|
@ -423,7 +428,7 @@ namespace llarp
|
|||
SyncTransitMap_t m_TransitPaths;
|
||||
SyncTransitMap_t m_Paths;
|
||||
SyncOwnedPathsMap_t m_OurPaths;
|
||||
std::list< llarp_pathbuilder_context* > m_PathBuilders;
|
||||
std::list< Builder* > m_PathBuilders;
|
||||
bool m_AllowTransit;
|
||||
};
|
||||
} // namespace path
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
#ifndef LLARP_PATHFINDER_H_
|
||||
#define LLARP_PATHFINDER_H_
|
||||
|
||||
#include <llarp/buffer.h>
|
||||
#include <llarp/path.h>
|
||||
|
||||
/**
|
||||
* path_base.h
|
||||
*
|
||||
* path api functions
|
||||
*/
|
||||
|
||||
/// forard declare
|
||||
struct llarp_router;
|
||||
struct llarp_dht_context;
|
||||
|
||||
// fwd declr
|
||||
struct llarp_pathbuilder_context;
|
||||
|
||||
/// alloc
|
||||
struct llarp_pathbuilder_context*
|
||||
llarp_pathbuilder_context_new(struct llarp_router* router,
|
||||
struct llarp_dht_context* dht, size_t numpaths,
|
||||
size_t defaultNumHops);
|
||||
/// dealloc
|
||||
void
|
||||
llarp_pathbuilder_context_free(struct llarp_pathbuilder_context* ctx);
|
||||
|
||||
// fwd declr
|
||||
struct llarp_pathbuild_job;
|
||||
|
||||
/// response callback
|
||||
typedef void (*llarp_pathbuilder_hook)(struct llarp_pathbuild_job*);
|
||||
// select hop function (user, nodedb, prevhop, result, hopnnumber) called in
|
||||
// logic thread
|
||||
typedef bool (*llarp_pathbuilder_select_hop_func)(void*, struct llarp_nodedb*,
|
||||
struct llarp_rc*,
|
||||
struct llarp_rc*, size_t);
|
||||
|
||||
// request struct
|
||||
struct llarp_pathbuild_job
|
||||
{
|
||||
// opaque pointer for user data
|
||||
void* user;
|
||||
// router context (set by llarp_pathbuilder_build_path)
|
||||
struct llarp_router* router;
|
||||
// context
|
||||
struct llarp_pathbuilder_context* context;
|
||||
// path hop selection
|
||||
llarp_pathbuilder_select_hop_func selectHop;
|
||||
// called when the path build started
|
||||
llarp_pathbuilder_hook pathBuildStarted;
|
||||
// path
|
||||
struct llarp_path_hops hops;
|
||||
};
|
||||
|
||||
/// request func
|
||||
// or find_path but thought pathfinder_find_path was a bit redundant
|
||||
void
|
||||
llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job);
|
||||
|
||||
#endif
|
|
@ -1,37 +1,41 @@
|
|||
#ifndef LLARP_PATHBUILDER_HPP_
|
||||
#define LLARP_PATHBUILDER_HPP_
|
||||
#include <llarp/pathbuilder.h>
|
||||
#include <llarp/router.h>
|
||||
#include <llarp/path.hpp>
|
||||
|
||||
#include <llarp/pathset.hpp>
|
||||
|
||||
struct llarp_pathbuilder_context : public llarp::path::PathSet
|
||||
namespace llarp
|
||||
{
|
||||
struct llarp_router* router;
|
||||
struct llarp_dht_context* dht;
|
||||
llarp::SecretKey enckey;
|
||||
size_t numHops;
|
||||
/// construct
|
||||
llarp_pathbuilder_context(llarp_router* p_router,
|
||||
struct llarp_dht_context* p_dht, size_t numPaths,
|
||||
size_t numHops);
|
||||
namespace path
|
||||
{
|
||||
struct Builder : public PathSet
|
||||
{
|
||||
struct llarp_router* router;
|
||||
struct llarp_dht_context* dht;
|
||||
llarp::SecretKey enckey;
|
||||
size_t numHops;
|
||||
/// construct
|
||||
Builder(llarp_router* p_router, struct llarp_dht_context* p_dht,
|
||||
size_t numPaths, size_t numHops);
|
||||
|
||||
virtual ~llarp_pathbuilder_context();
|
||||
virtual ~Builder();
|
||||
|
||||
virtual bool
|
||||
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
|
||||
virtual bool
|
||||
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
|
||||
size_t hop);
|
||||
|
||||
virtual bool
|
||||
ShouldBuildMore() const;
|
||||
virtual bool
|
||||
ShouldBuildMore() const;
|
||||
|
||||
void
|
||||
BuildOne();
|
||||
void
|
||||
BuildOne();
|
||||
|
||||
void
|
||||
ManualRebuild(size_t N);
|
||||
void
|
||||
ManualRebuild(size_t N);
|
||||
|
||||
virtual byte_t*
|
||||
GetTunnelEncryptionSecretKey();
|
||||
};
|
||||
virtual const byte_t*
|
||||
GetTunnelEncryptionSecretKey() const;
|
||||
};
|
||||
} // namespace path
|
||||
|
||||
} // namespace llarp
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <llarp/routing/message.hpp>
|
||||
#include <llarp/service/IntroSet.hpp>
|
||||
#include <llarp/service/lookup.hpp>
|
||||
#include <llarp/dht/messages/all.hpp>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
|
||||
|
@ -114,17 +115,9 @@ namespace llarp
|
|||
}
|
||||
|
||||
virtual bool
|
||||
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur,
|
||||
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
|
||||
size_t hop) = 0;
|
||||
|
||||
static bool
|
||||
SelectHopCallback(void* user, llarp_nodedb* db, llarp_rc* prev,
|
||||
llarp_rc* cur, size_t hopno)
|
||||
{
|
||||
PathSet* self = static_cast< PathSet* >(user);
|
||||
return self->SelectHop(db, prev, cur, hopno);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::pair< RouterID, PathID_t > PathInfo_t;
|
||||
typedef std::map< PathInfo_t, Path* > PathMap_t;
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
#include <llarp/config.h>
|
||||
#include <llarp/ev.h>
|
||||
#include <llarp/logic.h>
|
||||
#include <llarp/nodedb.h>
|
||||
#include <llarp/pathbuilder.h>
|
||||
#include <llarp/router_contact.h>
|
||||
#include <llarp/threadpool.h>
|
||||
#include <llarp/buffer.h>
|
||||
|
||||
struct llarp_nodedb;
|
||||
struct llarp_router;
|
||||
|
||||
bool
|
||||
|
@ -19,16 +18,6 @@ llarp_init_router(struct llarp_threadpool *worker,
|
|||
struct llarp_ev_loop *netloop, struct llarp_logic *logic);
|
||||
void
|
||||
llarp_free_router(struct llarp_router **router);
|
||||
|
||||
bool
|
||||
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote,
|
||||
uint16_t numretries);
|
||||
|
||||
/// override default path builder function (FFI)
|
||||
void
|
||||
llarp_router_override_path_selection(struct llarp_router *router,
|
||||
llarp_pathbuilder_select_hop_func func);
|
||||
|
||||
bool
|
||||
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf);
|
||||
|
||||
|
@ -38,15 +27,4 @@ llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb);
|
|||
void
|
||||
llarp_stop_router(struct llarp_router *router);
|
||||
|
||||
struct llarp_router_link_iter
|
||||
{
|
||||
void *user;
|
||||
bool (*visit)(struct llarp_router_link_iter *, struct llarp_router *,
|
||||
struct llarp_link *);
|
||||
};
|
||||
|
||||
void
|
||||
llarp_router_iterate_links(struct llarp_router *router,
|
||||
struct llarp_router_link_iter iter);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
#ifndef LLARP_RC_H
|
||||
#define LLARP_RC_H
|
||||
#include <llarp/address_info.h>
|
||||
#include <llarp/crypto.h>
|
||||
#include <llarp/exit_info.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
// forward declare
|
||||
struct llarp_alloc;
|
||||
struct llarp_rc;
|
||||
|
||||
#define MAX_RC_SIZE (1024)
|
||||
#define NICKLEN (32)
|
||||
|
||||
bool
|
||||
llarp_rc_bdecode(struct llarp_rc *rc, llarp_buffer_t *buf);
|
||||
bool
|
||||
llarp_rc_bencode(const struct llarp_rc *rc, llarp_buffer_t *buf);
|
||||
|
||||
struct llarp_rc
|
||||
{
|
||||
struct llarp_ai_list *addrs;
|
||||
// public encryption public key
|
||||
byte_t enckey[PUBKEYSIZE];
|
||||
// public signing public key
|
||||
byte_t pubkey[PUBKEYSIZE];
|
||||
struct llarp_xi_list *exits;
|
||||
byte_t signature[SIGSIZE];
|
||||
/// node nickname, yw kee
|
||||
byte_t nickname[NICKLEN];
|
||||
|
||||
uint64_t last_updated;
|
||||
|
||||
#ifdef __cplusplus
|
||||
bool
|
||||
BEncode(llarp_buffer_t *buf) const
|
||||
{
|
||||
return llarp_rc_bencode(this, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
BDecode(llarp_buffer_t *buf)
|
||||
{
|
||||
return llarp_rc_bdecode(this, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
HasNick() const
|
||||
{
|
||||
return nickname[0] != 0;
|
||||
}
|
||||
|
||||
std::string
|
||||
Nick() const
|
||||
{
|
||||
const char *nick = (const char *)nickname;
|
||||
return std::string(nick, strnlen(nick, sizeof(nickname)));
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
llarp_rc_free(struct llarp_rc *rc);
|
||||
|
||||
bool
|
||||
llarp_rc_new(struct llarp_rc *rc);
|
||||
|
||||
bool
|
||||
llarp_rc_verify_sig(struct llarp_crypto *crypto, struct llarp_rc *rc);
|
||||
|
||||
void
|
||||
llarp_rc_copy(struct llarp_rc *dst, const struct llarp_rc *src);
|
||||
|
||||
bool
|
||||
llarp_rc_is_public_router(const struct llarp_rc *const rc);
|
||||
|
||||
void
|
||||
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
|
||||
struct llarp_ai_list *addr);
|
||||
|
||||
bool
|
||||
llarp_rc_set_nickname(struct llarp_rc *rc, const char *name);
|
||||
|
||||
void
|
||||
llarp_rc_set_pubenckey(struct llarp_rc *rc, const uint8_t *pubenckey);
|
||||
|
||||
void
|
||||
llarp_rc_set_pubsigkey(struct llarp_rc *rc, const uint8_t *pubkey);
|
||||
|
||||
/// combo
|
||||
void
|
||||
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubenckey,
|
||||
const uint8_t *pubsigkey);
|
||||
|
||||
void
|
||||
llarp_rc_sign(struct llarp_crypto *crypto, const byte_t *seckey,
|
||||
struct llarp_rc *rc);
|
||||
|
||||
void
|
||||
llarp_rc_clear(struct llarp_rc *rc);
|
||||
|
||||
bool
|
||||
llarp_rc_addr_list_iter(struct llarp_ai_list_iter *iter, struct llarp_ai *ai);
|
||||
|
||||
bool
|
||||
llarp_rc_read(const char *fpath, struct llarp_rc *result);
|
||||
|
||||
bool
|
||||
llarp_rc_write(struct llarp_rc *rc, const char *our_rc_file);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,95 @@
|
|||
#ifndef LLARP_RC_HPP
|
||||
#define LLARP_RC_HPP
|
||||
#include <llarp/address_info.hpp>
|
||||
#include <llarp/crypto.h>
|
||||
#include <llarp/bencode.hpp>
|
||||
#include <llarp/exit_info.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define MAX_RC_SIZE (1024)
|
||||
#define NICKLEN (32)
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct RouterContact : public IBEncodeMessage
|
||||
{
|
||||
RouterContact() : IBEncodeMessage()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
RouterContact(const RouterContact &other)
|
||||
: addrs(other.addrs)
|
||||
, enckey(other.enckey)
|
||||
, pubkey(other.pubkey)
|
||||
, exits(other.exits)
|
||||
, signature(other.signature)
|
||||
, nickname(other.nickname)
|
||||
, last_updated(other.last_updated)
|
||||
|
||||
{
|
||||
version = other.version;
|
||||
}
|
||||
|
||||
// advertised addresses
|
||||
std::vector< AddressInfo > addrs = {};
|
||||
// public encryption public key
|
||||
llarp::PubKey enckey;
|
||||
// public signing public key
|
||||
llarp::PubKey pubkey;
|
||||
// advertised exits
|
||||
std::vector< ExitInfo > exits = {};
|
||||
// signature
|
||||
llarp::Signature signature;
|
||||
/// node nickname, yw kee
|
||||
llarp::AlignedBuffer< NICKLEN > nickname;
|
||||
|
||||
uint64_t last_updated;
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t *buf) const;
|
||||
|
||||
void
|
||||
Clear();
|
||||
|
||||
bool
|
||||
BDecode(llarp_buffer_t *buf)
|
||||
{
|
||||
Clear();
|
||||
return IBEncodeMessage::BDecode(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t k, llarp_buffer_t *buf);
|
||||
|
||||
RouterContact &
|
||||
operator=(const RouterContact &other);
|
||||
|
||||
bool
|
||||
HasNick() const;
|
||||
|
||||
std::string
|
||||
Nick() const;
|
||||
|
||||
bool
|
||||
IsPublicRouter() const;
|
||||
|
||||
void
|
||||
SetNick(const std::string &nick);
|
||||
|
||||
bool
|
||||
VerifySignature(llarp_crypto *crypto) const;
|
||||
|
||||
bool
|
||||
Sign(llarp_crypto *crypto, const llarp::SecretKey &secret);
|
||||
|
||||
bool
|
||||
Read(const char *fname);
|
||||
|
||||
bool
|
||||
Write(const char *fname) const;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -18,7 +18,8 @@ namespace llarp
|
|||
public:
|
||||
ServiceInfo() = default;
|
||||
|
||||
ServiceInfo(const ServiceInfo&& other)
|
||||
ServiceInfo(ServiceInfo&& other) = delete;
|
||||
/*
|
||||
{
|
||||
enckey = std::move(other.enckey);
|
||||
signkey = std::move(other.signkey);
|
||||
|
@ -26,14 +27,15 @@ namespace llarp
|
|||
vanity = std::move(other.vanity);
|
||||
m_CachedAddr = std::move(other.m_CachedAddr);
|
||||
}
|
||||
*/
|
||||
|
||||
ServiceInfo(const ServiceInfo& other)
|
||||
: enckey(other.enckey)
|
||||
, signkey(other.signkey)
|
||||
, vanity(other.vanity)
|
||||
, m_CachedAddr(other.m_CachedAddr)
|
||||
{
|
||||
enckey = other.enckey;
|
||||
signkey = other.signkey;
|
||||
version = other.version;
|
||||
vanity = other.vanity;
|
||||
m_CachedAddr = other.m_CachedAddr;
|
||||
version = other.version;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -137,4 +139,4 @@ namespace llarp
|
|||
} // namespace service
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
#include <llarp/service/Identity.hpp>
|
||||
#include <llarp/service/handler.hpp>
|
||||
#include <llarp/service/protocol.hpp>
|
||||
#include <llarp/path.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace service
|
||||
{
|
||||
struct Endpoint : public llarp_pathbuilder_context,
|
||||
struct Endpoint : public path::Builder,
|
||||
public ILookupHolder,
|
||||
public IDataHandler
|
||||
{
|
||||
|
@ -145,7 +146,7 @@ namespace llarp
|
|||
typedef std::queue< PendingBuffer > PendingBufferQueue;
|
||||
|
||||
/// context needed to initiate an outbound hidden service session
|
||||
struct OutboundContext : public llarp_pathbuilder_context
|
||||
struct OutboundContext : public path::Builder
|
||||
{
|
||||
OutboundContext(const IntroSet& introSet, Endpoint* parent);
|
||||
~OutboundContext();
|
||||
|
@ -176,7 +177,8 @@ namespace llarp
|
|||
HandlePathBuilt(path::Path* path);
|
||||
|
||||
bool
|
||||
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
|
||||
SelectHop(llarp_nodedb* db, const RouterContact& prev,
|
||||
RouterContact& cur, size_t hop);
|
||||
|
||||
bool
|
||||
HandleHiddenServiceFrame(const ProtocolFrame* frame);
|
||||
|
|
|
@ -67,4 +67,4 @@ namespace llarp
|
|||
} // namespace service
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UTP_H__
|
||||
#define __UTP_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "utp_types.h"
|
||||
|
||||
typedef struct UTPSocket utp_socket;
|
||||
typedef struct struct_utp_context utp_context;
|
||||
|
||||
enum
|
||||
{
|
||||
UTP_UDP_DONTFRAG = 2, // Used to be a #define as UDP_IP_DONTFRAG
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
// socket has reveived syn-ack (notification only for outgoing connection
|
||||
// completion) this implies writability
|
||||
UTP_STATE_CONNECT = 1,
|
||||
|
||||
// socket is able to send more data
|
||||
UTP_STATE_WRITABLE = 2,
|
||||
|
||||
// connection closed
|
||||
UTP_STATE_EOF = 3,
|
||||
|
||||
// socket is being destroyed, meaning all data has been sent if possible.
|
||||
// it is not valid to refer to the socket after this state change occurs
|
||||
UTP_STATE_DESTROYING = 4,
|
||||
};
|
||||
|
||||
extern const char *utp_state_names[];
|
||||
|
||||
// Errors codes that can be passed to UTP_ON_ERROR callback
|
||||
enum
|
||||
{
|
||||
UTP_ECONNREFUSED = 0,
|
||||
UTP_ECONNRESET,
|
||||
UTP_ETIMEDOUT,
|
||||
};
|
||||
|
||||
extern const char *utp_error_code_names[];
|
||||
|
||||
enum
|
||||
{
|
||||
// callback names
|
||||
UTP_ON_FIREWALL = 0,
|
||||
UTP_ON_ACCEPT,
|
||||
UTP_ON_CONNECT,
|
||||
UTP_ON_ERROR,
|
||||
UTP_ON_READ,
|
||||
UTP_ON_OVERHEAD_STATISTICS,
|
||||
UTP_ON_STATE_CHANGE,
|
||||
UTP_GET_READ_BUFFER_SIZE,
|
||||
UTP_ON_DELAY_SAMPLE,
|
||||
UTP_GET_UDP_MTU,
|
||||
UTP_GET_UDP_OVERHEAD,
|
||||
UTP_GET_MILLISECONDS,
|
||||
UTP_GET_MICROSECONDS,
|
||||
UTP_GET_RANDOM,
|
||||
UTP_LOG,
|
||||
UTP_SENDTO,
|
||||
|
||||
// context and socket options that may be set/queried
|
||||
UTP_LOG_NORMAL,
|
||||
UTP_LOG_MTU,
|
||||
UTP_LOG_DEBUG,
|
||||
UTP_SNDBUF,
|
||||
UTP_RCVBUF,
|
||||
UTP_TARGET_DELAY,
|
||||
|
||||
UTP_ARRAY_SIZE, // must be last
|
||||
};
|
||||
|
||||
extern const char *utp_callback_names[];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
utp_context *context;
|
||||
utp_socket *socket;
|
||||
size_t len;
|
||||
uint32 flags;
|
||||
int callback_type;
|
||||
const byte *buf;
|
||||
|
||||
union {
|
||||
const struct sockaddr *address;
|
||||
int send;
|
||||
int sample_ms;
|
||||
int error_code;
|
||||
int state;
|
||||
};
|
||||
|
||||
union {
|
||||
socklen_t address_len;
|
||||
int type;
|
||||
};
|
||||
} utp_callback_arguments;
|
||||
|
||||
typedef uint64
|
||||
utp_callback_t(utp_callback_arguments *);
|
||||
|
||||
// Returned by utp_get_context_stats()
|
||||
typedef struct
|
||||
{
|
||||
uint32 _nraw_recv[5]; // total packets recieved less than 300/600/1200/MTU
|
||||
// bytes fpr all connections (context-wide)
|
||||
uint32 _nraw_send[5]; // total packets sent less than 300/600/1200/MTU
|
||||
// bytes for all connections (context-wide)
|
||||
} utp_context_stats;
|
||||
|
||||
// Returned by utp_get_stats()
|
||||
typedef struct
|
||||
{
|
||||
uint64 nbytes_recv; // total bytes received
|
||||
uint64 nbytes_xmit; // total bytes transmitted
|
||||
uint32 rexmit; // retransmit counter
|
||||
uint32 fastrexmit; // fast retransmit counter
|
||||
uint32 nxmit; // transmit counter
|
||||
uint32 nrecv; // receive counter (total)
|
||||
uint32 nduprecv; // duplicate receive counter
|
||||
uint32 mtu_guess; // Best guess at MTU
|
||||
} utp_socket_stats;
|
||||
|
||||
#define UTP_IOV_MAX 1024
|
||||
|
||||
// For utp_writev, to writes data from multiple buffers
|
||||
struct utp_iovec
|
||||
{
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
|
||||
// Public Functions
|
||||
utp_context *
|
||||
utp_init(int version);
|
||||
void
|
||||
utp_destroy(utp_context *ctx);
|
||||
void
|
||||
utp_set_callback(utp_context *ctx, int callback_name, utp_callback_t *proc);
|
||||
void *
|
||||
utp_context_set_userdata(utp_context *ctx, void *userdata);
|
||||
void *
|
||||
utp_context_get_userdata(utp_context *ctx);
|
||||
int
|
||||
utp_context_set_option(utp_context *ctx, int opt, int val);
|
||||
int
|
||||
utp_context_get_option(utp_context *ctx, int opt);
|
||||
int
|
||||
utp_process_udp(utp_context *ctx, const byte *buf, size_t len,
|
||||
const struct sockaddr *to, socklen_t tolen);
|
||||
int
|
||||
utp_process_icmp_error(utp_context *ctx, const byte *buffer, size_t len,
|
||||
const struct sockaddr *to, socklen_t tolen);
|
||||
int
|
||||
utp_process_icmp_fragmentation(utp_context *ctx, const byte *buffer,
|
||||
size_t len, const struct sockaddr *to,
|
||||
socklen_t tolen, uint16 next_hop_mtu);
|
||||
void
|
||||
utp_check_timeouts(utp_context *ctx);
|
||||
void
|
||||
utp_issue_deferred_acks(utp_context *ctx);
|
||||
utp_context_stats *
|
||||
utp_get_context_stats(utp_context *ctx);
|
||||
utp_socket *
|
||||
utp_create_socket(utp_context *ctx);
|
||||
void *
|
||||
utp_set_userdata(utp_socket *s, void *userdata);
|
||||
void *
|
||||
utp_get_userdata(utp_socket *s);
|
||||
int
|
||||
utp_setsockopt(utp_socket *s, int opt, int val);
|
||||
int
|
||||
utp_getsockopt(utp_socket *s, int opt);
|
||||
int
|
||||
utp_connect(utp_socket *s, const struct sockaddr *to, socklen_t tolen);
|
||||
ssize_t
|
||||
utp_write(utp_socket *s, void *buf, size_t count);
|
||||
ssize_t
|
||||
utp_writev(utp_socket *s, struct utp_iovec *iovec, size_t num_iovecs);
|
||||
int
|
||||
utp_getpeername(utp_socket *s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
void
|
||||
utp_read_drained(utp_socket *s);
|
||||
int
|
||||
utp_get_delays(utp_socket *s, uint32 *ours, uint32 *theirs, uint32 *age);
|
||||
utp_socket_stats *
|
||||
utp_get_stats(utp_socket *s);
|
||||
utp_context *
|
||||
utp_get_context(utp_socket *s);
|
||||
void
|
||||
utp_shutdown(utp_socket *s, int how);
|
||||
void
|
||||
utp_close(utp_socket *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__UTP_H__
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UTP_TYPES_H__
|
||||
#define __UTP_TYPES_H__
|
||||
|
||||
// Allow libutp consumers or prerequisites to override PACKED_ATTRIBUTE
|
||||
#ifndef PACKED_ATTRIBUTE
|
||||
#if defined BROKEN_GCC_STRUCTURE_PACKING && defined __GNUC__
|
||||
// Used for gcc tool chains accepting but not supporting pragma pack
|
||||
// See http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
|
||||
#define PACKED_ATTRIBUTE __attribute__((__packed__))
|
||||
#else
|
||||
#define PACKED_ATTRIBUTE
|
||||
#endif // defined BROKEN_GCC_STRUCTURE_PACKING && defined __GNUC__
|
||||
#endif // ndef PACKED_ATTRIBUTE
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ALIGNED_ATTRIBUTE(x) __attribute__((aligned(x)))
|
||||
#else
|
||||
#define ALIGNED_ATTRIBUTE(x)
|
||||
#endif
|
||||
|
||||
// hash.cpp needs socket definitions, which is why this networking specific
|
||||
// code is inclued in utypes.h
|
||||
#ifdef WIN32
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#define IP_OPT_DONTFRAG IP_DONTFRAGMENT
|
||||
#define SHUT_RD SD_RECEIVE
|
||||
#define SHUT_WR SD_SEND
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef IP_DONTFRAG
|
||||
#define IP_OPT_DONTFRAG IP_DONTFRAG
|
||||
#elif defined IP_DONTFRAGMENT
|
||||
#define IP_OPT_DONTFRAG IP_DONTFRAGMENT
|
||||
#else
|
||||
//#warning "I don't know how to set DF bit on this system"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <BaseTsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
|
||||
#ifdef POSIX
|
||||
typedef struct sockaddr_storage SOCKADDR_STORAGE;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define I64u "%I64u"
|
||||
#else
|
||||
#define I64u "%Lu"
|
||||
#endif
|
||||
|
||||
// standard types
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed char int8;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed short int16;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed int int32;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 uint64;
|
||||
typedef signed __int64 int64;
|
||||
#else
|
||||
typedef unsigned long long uint64;
|
||||
typedef long long int64;
|
||||
#endif
|
||||
|
||||
/* compile-time assert */
|
||||
#ifndef CASSERT
|
||||
#define CASSERT(exp, name) typedef int is_not_##name[(exp) ? 1 : -1];
|
||||
#endif
|
||||
|
||||
CASSERT(8 == sizeof(uint64), sizeof_uint64_is_8)
|
||||
CASSERT(8 == sizeof(int64), sizeof_int64_is_8)
|
||||
|
||||
#ifndef INT64_MAX
|
||||
#define INT64_MAX 0x7fffffffffffffffLL
|
||||
#endif
|
||||
|
||||
// always ANSI
|
||||
typedef const char* cstr;
|
||||
typedef char* str;
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef uint8 bool;
|
||||
#endif
|
||||
|
||||
#endif //__UTP_TYPES_H__
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -0,0 +1,48 @@
|
|||
OBJS = utp_internal.o utp_utils.o utp_hash.o utp_callbacks.o utp_api.o utp_packedsockaddr.o
|
||||
CFLAGS = -Wall -DPOSIX -g -fno-exceptions $(OPT)
|
||||
OPT ?= -O3
|
||||
CXXFLAGS = $(CFLAGS) -fPIC -fno-rtti
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
|
||||
CXXFLAGS += -Wno-sign-compare
|
||||
CXXFLAGS += -fpermissive
|
||||
|
||||
# Uncomment to enable utp_get_stats(), and a few extra sanity checks
|
||||
#CFLAGS += -D_DEBUG
|
||||
|
||||
# Uncomment to enable debug logging
|
||||
#CFLAGS += -DUTP_DEBUG_LOGGING
|
||||
|
||||
# Dynamically determine if librt is available. If so, assume we need to link
|
||||
# against it for clock_gettime(2). This is required for clean builds on OSX;
|
||||
# see <https://github.com/bittorrent/libutp/issues/1> for more. This should
|
||||
# probably be ported to CMake at some point, but is suitable for now.
|
||||
lrt := $(shell echo 'int main() {}' | $(CC) -xc -o /dev/null - -lrt >/dev/null 2>&1; echo $$?)
|
||||
ifeq ($(strip $(lrt)),0)
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
all: libutp.so libutp.a ucat ucat-static
|
||||
|
||||
libutp.so: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o libutp.so -shared $(OBJS)
|
||||
|
||||
libutp.a: $(OBJS)
|
||||
ar rvs libutp.a $(OBJS)
|
||||
|
||||
ucat: ucat.o libutp.so
|
||||
$(CC) $(CFLAGS) -o ucat ucat.o -L. -lutp $(LDFLAGS)
|
||||
|
||||
ucat-static: ucat.o libutp.a
|
||||
$(CXX) $(CXXFLAGS) -o ucat-static ucat.o libutp.a $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f *.o libutp.so libutp.a ucat ucat-static
|
||||
|
||||
tags: $(shell ls *.cpp *.h)
|
||||
rm -f tags
|
||||
ctags *.cpp *.h
|
||||
|
||||
anyway: clean all
|
||||
.PHONY: clean all anyway
|
|
@ -0,0 +1,68 @@
|
|||
# libutp - The uTorrent Transport Protocol library.
|
||||
Copyright (c) 2010 BitTorrent, Inc.
|
||||
|
||||
uTP is a TCP-like implementation of [LEDBAT][ledbat] documented as a BitTorrent
|
||||
extension in [BEP-29][bep29]. uTP provides reliable, ordered delivery
|
||||
while maintaining minimum extra delay. It is implemented on top of UDP to be
|
||||
cross-platform and functional today. As a result, uTP is the primary transport
|
||||
for uTorrent peer-to-peer connections.
|
||||
|
||||
uTP is written in C++, but the external interface is strictly C (ANSI C89).
|
||||
|
||||
## The Interface
|
||||
|
||||
The uTP socket interface is a bit different from the Berkeley socket API to
|
||||
avoid the need for our own select() implementation, and to make it easier to
|
||||
write event-based code with minimal buffering.
|
||||
|
||||
When you create a uTP socket, you register a set of callbacks. Most notably, the
|
||||
on_read callback is a reactive callback which occurs when bytes arrive off the
|
||||
network. The write side of the socket is proactive, and you call UTP_Write to
|
||||
indicate the number of bytes you wish to write. As packets are created, the
|
||||
on_write callback is called for each packet, so you can fill the buffers with
|
||||
data.
|
||||
|
||||
The libutp interface is not thread-safe. It was designed for use in a
|
||||
single-threaded asyncronous context, although with proper synchronization
|
||||
it may be used from a multi-threaded environment as well.
|
||||
|
||||
See utp.h for more details and other API documentation.
|
||||
|
||||
## Example
|
||||
|
||||
See ucat.c. Build with:
|
||||
|
||||
make ucat
|
||||
|
||||
## Building
|
||||
|
||||
uTP has been known to build on Windows with MSVC and on linux and OS X with gcc.
|
||||
On Windows, use the MSVC project files (utp.sln, and friends). On other platforms,
|
||||
building the shared library is as simple as:
|
||||
|
||||
make
|
||||
|
||||
To build one of the examples, which will statically link in everything it needs
|
||||
from libutp:
|
||||
|
||||
cd utp_test && make
|
||||
|
||||
## Packaging and API
|
||||
|
||||
The libutp API is considered unstable, and probably always will be. We encourage
|
||||
you to test with the version of libutp you have, and be mindful when upgrading.
|
||||
For this reason, it is probably also a good idea to bundle libutp with your
|
||||
application.
|
||||
|
||||
## License
|
||||
|
||||
libutp is released under the [MIT][lic] license.
|
||||
|
||||
## Related Work
|
||||
|
||||
Research and analysis of congestion control mechanisms can be found [here.][survey]
|
||||
|
||||
[ledbat]: http://datatracker.ietf.org/wg/ledbat/charter/
|
||||
[bep29]: http://www.bittorrent.org/beps/bep_0029.html
|
||||
[lic]: http://www.opensource.org/licenses/mit-license.php
|
||||
[survey]: http://datatracker.ietf.org/doc/draft-ietf-ledbat-survey/
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "libutp_inet_ntop.h"
|
||||
|
||||
|
||||
//######################################################################
|
||||
const char *libutp::inet_ntop(int af, const void *src, char *dest, size_t length)
|
||||
{
|
||||
if (af != AF_INET && af != AF_INET6)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE address;
|
||||
DWORD address_length;
|
||||
|
||||
if (af == AF_INET)
|
||||
{
|
||||
address_length = sizeof(sockaddr_in);
|
||||
sockaddr_in* ipv4_address = (sockaddr_in*)(&address);
|
||||
ipv4_address->sin_family = AF_INET;
|
||||
ipv4_address->sin_port = 0;
|
||||
memcpy(&ipv4_address->sin_addr, src, sizeof(in_addr));
|
||||
}
|
||||
else // AF_INET6
|
||||
{
|
||||
address_length = sizeof(sockaddr_in6);
|
||||
sockaddr_in6* ipv6_address = (sockaddr_in6*)(&address);
|
||||
ipv6_address->sin6_family = AF_INET6;
|
||||
ipv6_address->sin6_port = 0;
|
||||
ipv6_address->sin6_flowinfo = 0;
|
||||
// hmmm
|
||||
ipv6_address->sin6_scope_id = 0;
|
||||
memcpy(&ipv6_address->sin6_addr, src, sizeof(in6_addr));
|
||||
}
|
||||
|
||||
DWORD string_length = (DWORD)(length);
|
||||
int result;
|
||||
result = WSAAddressToStringA((sockaddr*)(&address),
|
||||
address_length, 0, dest,
|
||||
&string_length);
|
||||
|
||||
// one common reason for this to fail is that ipv6 is not installed
|
||||
|
||||
return result == SOCKET_ERROR ? NULL : dest;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
int libutp::inet_pton(int af, const char* src, void* dest)
|
||||
{
|
||||
if (af != AF_INET && af != AF_INET6)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE address;
|
||||
int address_length = sizeof(SOCKADDR_STORAGE);
|
||||
int result = WSAStringToAddressA((char*)(src), af, 0,
|
||||
(sockaddr*)(&address),
|
||||
&address_length);
|
||||
|
||||
if (af == AF_INET)
|
||||
{
|
||||
if (result != SOCKET_ERROR)
|
||||
{
|
||||
sockaddr_in* ipv4_address =(sockaddr_in*)(&address);
|
||||
memcpy(dest, &ipv4_address->sin_addr, sizeof(in_addr));
|
||||
}
|
||||
else if (strcmp(src, "255.255.255.255") == 0)
|
||||
{
|
||||
((in_addr*)(dest))->s_addr = INADDR_NONE;
|
||||
}
|
||||
}
|
||||
else // AF_INET6
|
||||
{
|
||||
if (result != SOCKET_ERROR)
|
||||
{
|
||||
sockaddr_in6* ipv6_address = (sockaddr_in6*)(&address);
|
||||
memcpy(dest, &ipv6_address->sin6_addr, sizeof(in6_addr));
|
||||
}
|
||||
}
|
||||
|
||||
return result == SOCKET_ERROR ? -1 : 1;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#ifndef LIBUTP_INET_NTOP_H
|
||||
#define LIBUTP_INET_NTOP_H
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// About us linking the system inet_pton and inet_ntop symbols:
|
||||
// 1) These symbols are usually defined on POSIX systems
|
||||
// 2) They are not defined on Windows versions earlier than Vista
|
||||
// Defined in:
|
||||
// ut_utils/src/sockaddr.cpp
|
||||
// libutp/win32_inet_ntop.obj
|
||||
//
|
||||
// When we drop support for XP we can just #include <ws2tcpip.h>, and use the system functions
|
||||
// For now, we will always use our functions on windows, on all builds
|
||||
// The reason is: we would like the debug build to behave as much as the release build as possible
|
||||
// It is much better to catch a problem in the debug build, than to link the system version
|
||||
// in debug, and our version int he wild.
|
||||
|
||||
#if defined(_WIN32_WINNT)
|
||||
#if _WIN32_WINNT >= 0x600 // Win32, post-XP
|
||||
#include <ws2tcpip.h> // for inet_ntop, inet_pton
|
||||
#define INET_NTOP inet_ntop
|
||||
#define INET_PTON inet_pton
|
||||
#else
|
||||
#define INET_NTOP libutp::inet_ntop // Win32, pre-XP: Use ours
|
||||
#define INET_PTON libutp::inet_pton
|
||||
#endif
|
||||
#else // not WIN32
|
||||
#include <arpa/inet.h> // for inet_ntop, inet_pton
|
||||
#define INET_NTOP inet_ntop
|
||||
#define INET_PTON inet_pton
|
||||
#endif
|
||||
|
||||
//######################################################################
|
||||
//######################################################################
|
||||
namespace libutp {
|
||||
|
||||
|
||||
//######################################################################
|
||||
const char *inet_ntop(int af, const void *src, char *dest, size_t length);
|
||||
|
||||
//######################################################################
|
||||
int inet_pton(int af, const char* src, void* dest);
|
||||
|
||||
|
||||
} //namespace libutp
|
||||
|
||||
#endif // LIBUTP_INET_NTOP_H
|
|
@ -0,0 +1,288 @@
|
|||
import os, sys, time
|
||||
|
||||
# usage: parse_log.py log-file [socket-index to focus on]
|
||||
|
||||
|
||||
socket_filter = None
|
||||
if len(sys.argv) >= 3:
|
||||
socket_filter = sys.argv[2].strip()
|
||||
|
||||
if socket_filter == None:
|
||||
print "scanning for socket with the most packets"
|
||||
file = open(sys.argv[1], 'rb')
|
||||
|
||||
sockets = {}
|
||||
|
||||
for l in file:
|
||||
if not 'our_delay' in l: continue
|
||||
|
||||
try:
|
||||
a = l.strip().split(" ")
|
||||
socket_index = a[1][:-1]
|
||||
except:
|
||||
continue
|
||||
|
||||
# msvc's runtime library doesn't prefix pointers
|
||||
# with '0x'
|
||||
# if socket_index[:2] != '0x':
|
||||
# continue
|
||||
|
||||
if socket_index in sockets:
|
||||
sockets[socket_index] += 1
|
||||
else:
|
||||
sockets[socket_index] = 1
|
||||
|
||||
items = sockets.items()
|
||||
items.sort(lambda x, y: y[1] - x[1])
|
||||
|
||||
count = 0
|
||||
for i in items:
|
||||
print '%s: %d' % (i[0], i[1])
|
||||
count += 1
|
||||
if count > 5: break
|
||||
|
||||
file.close()
|
||||
socket_filter = items[0][0]
|
||||
print '\nfocusing on socket %s' % socket_filter
|
||||
|
||||
file = open(sys.argv[1], 'rb')
|
||||
out_file = 'utp.out%s' % socket_filter;
|
||||
out = open(out_file, 'wb')
|
||||
|
||||
delay_samples = 'dots lc rgb "blue"'
|
||||
delay_base = 'steps lw 2 lc rgb "purple"'
|
||||
target_delay = 'steps lw 2 lc rgb "red"'
|
||||
off_target = 'dots lc rgb "blue"'
|
||||
cwnd = 'steps lc rgb "green"'
|
||||
window_size = 'steps lc rgb "sea-green"'
|
||||
rtt = 'lines lc rgb "light-blue"'
|
||||
|
||||
metrics = {
|
||||
'our_delay':['our delay (ms)', 'x1y2', delay_samples],
|
||||
'upload_rate':['send rate (B/s)', 'x1y1', 'lines'],
|
||||
'max_window':['cwnd (B)', 'x1y1', cwnd],
|
||||
'target_delay':['target delay (ms)', 'x1y2', target_delay],
|
||||
'cur_window':['bytes in-flight (B)', 'x1y1', window_size],
|
||||
'cur_window_packets':['number of packets in-flight', 'x1y2', 'steps'],
|
||||
'packet_size':['current packet size (B)', 'x1y2', 'steps'],
|
||||
'rtt':['rtt (ms)', 'x1y2', rtt],
|
||||
'off_target':['off-target (ms)', 'x1y2', off_target],
|
||||
'delay_sum':['delay sum (ms)', 'x1y2', 'steps'],
|
||||
'their_delay':['their delay (ms)', 'x1y2', delay_samples],
|
||||
'get_microseconds':['clock (us)', 'x1y1', 'steps'],
|
||||
'wnduser':['advertised window size (B)', 'x1y1', 'steps'],
|
||||
|
||||
'delay_base':['delay base (us)', 'x1y1', delay_base],
|
||||
'their_delay_base':['their delay base (us)', 'x1y1', delay_base],
|
||||
'their_actual_delay':['their actual delay (us)', 'x1y1', delay_samples],
|
||||
'actual_delay':['actual_delay (us)', 'x1y1', delay_samples]
|
||||
}
|
||||
|
||||
histogram_quantization = 1
|
||||
socket_index = None
|
||||
|
||||
columns = []
|
||||
|
||||
begin = None
|
||||
|
||||
title = "-"
|
||||
packet_loss = 0
|
||||
packet_timeout = 0
|
||||
|
||||
delay_histogram = {}
|
||||
window_size = {'0': 0, '1': 0}
|
||||
|
||||
# [35301484] 0x00ec1190: actual_delay:1021583 our_delay:102 their_delay:-1021345 off_target:297 max_window:2687 upload_rate:18942 delay_base:1021481154 delay_sum:-1021242 target_delay:400 acked_bytes:1441 cur_window:2882 scaled_gain:2.432
|
||||
|
||||
counter = 0
|
||||
|
||||
print "reading log file"
|
||||
|
||||
for l in file:
|
||||
if "UTP_Connect" in l:
|
||||
title = l[:-2]
|
||||
if socket_filter != None:
|
||||
title += ' socket: %s' % socket_filter
|
||||
else:
|
||||
title += ' sum of all sockets'
|
||||
continue
|
||||
|
||||
try:
|
||||
a = l.strip().split(" ")
|
||||
t = a[0][1:-1]
|
||||
socket_index = a[1][:-1]
|
||||
except:
|
||||
continue
|
||||
# if socket_index[:2] != '0x':
|
||||
# continue
|
||||
|
||||
if socket_filter != None and socket_index != socket_filter:
|
||||
continue
|
||||
|
||||
counter += 1
|
||||
if (counter % 300 == 0):
|
||||
print "\r%d " % counter,
|
||||
|
||||
if "lost." in l:
|
||||
packet_loss = packet_loss + 1
|
||||
continue
|
||||
if "Packet timeout" in l:
|
||||
packet_timeout = packet_timeout + 1
|
||||
continue
|
||||
if "our_delay:" not in l:
|
||||
continue
|
||||
|
||||
# used for Logf timestamps
|
||||
# t, m = t.split(".")
|
||||
# t = time.strptime(t, "%H:%M:%S")
|
||||
# t = list(t)
|
||||
# t[0] += 107
|
||||
# t = tuple(t)
|
||||
# m = float(m)
|
||||
# m /= 1000.0
|
||||
# t = time.mktime(t) + m
|
||||
|
||||
# used for tick count timestamps
|
||||
t = int(t)
|
||||
|
||||
if begin is None:
|
||||
begin = t
|
||||
t = t - begin
|
||||
# print time. Convert from milliseconds to seconds
|
||||
print >>out, '%f\t' % (float(t)/1000.),
|
||||
|
||||
#if t > 200000:
|
||||
# break
|
||||
|
||||
fill_columns = not columns
|
||||
for i in a[2:]:
|
||||
try:
|
||||
n, v = i.split(':')
|
||||
except:
|
||||
continue
|
||||
v = float(v)
|
||||
if n == "our_delay":
|
||||
bucket = v / histogram_quantization
|
||||
delay_histogram[bucket] = 1 + delay_histogram.get(bucket, 0)
|
||||
if not n in metrics: continue
|
||||
if fill_columns:
|
||||
columns.append(n)
|
||||
if n == "max_window":
|
||||
window_size[socket_index] = v
|
||||
print >>out, '%f\t' % int(reduce(lambda a,b: a+b, window_size.values())),
|
||||
else:
|
||||
print >>out, '%f\t' % v,
|
||||
print >>out, float(packet_loss * 8000), float(packet_timeout * 8000)
|
||||
packet_loss = 0
|
||||
packet_timeout = 0
|
||||
|
||||
out.close()
|
||||
|
||||
out = open('%s.histogram' % out_file, 'wb')
|
||||
for d,f in delay_histogram.iteritems():
|
||||
print >>out, float(d*histogram_quantization) + histogram_quantization / 2, f
|
||||
out.close()
|
||||
|
||||
|
||||
plot = [
|
||||
{
|
||||
'data': ['upload_rate', 'max_window', 'cur_window', 'wnduser', 'cur_window_packets', 'packet_size', 'rtt'],
|
||||
'title': 'send-packet-size',
|
||||
'y1': 'Bytes',
|
||||
'y2': 'Time (ms)'
|
||||
},
|
||||
{
|
||||
'data': ['our_delay', 'max_window', 'target_delay', 'cur_window', 'wnduser', 'cur_window_packets'],
|
||||
'title': 'uploading',
|
||||
'y1': 'Bytes',
|
||||
'y2': 'Time (ms)'
|
||||
},
|
||||
{
|
||||
'data': ['our_delay', 'max_window', 'target_delay', 'cur_window', 'cur_window_packets'],
|
||||
'title': 'uploading_packets',
|
||||
'y1': 'Bytes',
|
||||
'y2': 'Time (ms)'
|
||||
},
|
||||
{
|
||||
'data': ['get_microseconds'],
|
||||
'title': 'timer',
|
||||
'y1': 'Time microseconds',
|
||||
'y2': 'Time (ms)'
|
||||
},
|
||||
{
|
||||
'data': ['their_delay', 'target_delay', 'rtt'],
|
||||
'title': 'their_delay',
|
||||
'y1': '',
|
||||
'y2': 'Time (ms)'
|
||||
},
|
||||
{
|
||||
'data': ['their_actual_delay','their_delay_base'],
|
||||
'title': 'their_delay_base',
|
||||
'y1': 'Time (us)',
|
||||
'y2': ''
|
||||
},
|
||||
{
|
||||
'data': ['our_delay', 'target_delay', 'rtt'],
|
||||
'title': 'our-delay',
|
||||
'y1': '',
|
||||
'y2': 'Time (ms)'
|
||||
},
|
||||
{
|
||||
'data': ['actual_delay', 'delay_base'],
|
||||
'title': 'our_delay_base',
|
||||
'y1': 'Time (us)',
|
||||
'y2': ''
|
||||
}
|
||||
]
|
||||
|
||||
out = open('utp.gnuplot', 'w+')
|
||||
|
||||
files = ''
|
||||
|
||||
#print >>out, 'set xtics 0, 20'
|
||||
print >>out, "set term png size 1280,800"
|
||||
print >>out, 'set output "%s.delays.png"' % out_file
|
||||
print >>out, 'set xrange [0:250]'
|
||||
print >>out, 'set xlabel "delay (ms)"'
|
||||
print >>out, 'set boxwidth 1'
|
||||
print >>out, 'set style fill solid'
|
||||
print >>out, 'set ylabel "number of packets"'
|
||||
print >>out, 'plot "%s.histogram" using 1:2 with boxes' % out_file
|
||||
|
||||
print >>out, "set style data steps"
|
||||
#print >>out, "set yrange [0:*]"
|
||||
print >>out, "set y2range [*:*]"
|
||||
files += out_file + '.delays.png '
|
||||
#set hidden3d
|
||||
#set title "Peer bandwidth distribution"
|
||||
#set xlabel "Ratio"
|
||||
|
||||
for p in plot:
|
||||
print >>out, 'set title "%s %s"' % (p['title'], title)
|
||||
print >>out, 'set xlabel "time (s)"'
|
||||
print >>out, 'set ylabel "%s"' % p['y1']
|
||||
print >>out, "set tics nomirror"
|
||||
print >>out, 'set y2tics'
|
||||
print >>out, 'set y2label "%s"' % p['y2']
|
||||
print >>out, 'set xrange [0:*]'
|
||||
print >>out, "set key box"
|
||||
print >>out, "set term png size 1280,800"
|
||||
print >>out, 'set output "%s-%s.png"' % (out_file, p['title'])
|
||||
files += '%s-%s.png ' % (out_file, p['title'])
|
||||
|
||||
comma = ''
|
||||
print >>out, "plot",
|
||||
|
||||
for c in p['data']:
|
||||
if not c in metrics: continue
|
||||
i = columns.index(c)
|
||||
print >>out, '%s"%s" using 1:%d title "%s-%s" axes %s with %s' % (comma, out_file, i + 2, metrics[c][0], metrics[c][1], metrics[c][1], metrics[c][2]),
|
||||
comma = ', '
|
||||
print >>out, ''
|
||||
|
||||
out.close()
|
||||
|
||||
os.system("gnuplot utp.gnuplot")
|
||||
|
||||
os.system("open %s" % files)
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
// vim:set ts=4 sw=4 ai:
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "utp_internal.h"
|
||||
#include "utp_utils.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
const char * utp_callback_names[] = {
|
||||
"UTP_ON_FIREWALL",
|
||||
"UTP_ON_ACCEPT",
|
||||
"UTP_ON_CONNECT",
|
||||
"UTP_ON_ERROR",
|
||||
"UTP_ON_READ",
|
||||
"UTP_ON_OVERHEAD_STATISTICS",
|
||||
"UTP_ON_STATE_CHANGE",
|
||||
"UTP_GET_READ_BUFFER_SIZE",
|
||||
"UTP_ON_DELAY_SAMPLE",
|
||||
"UTP_GET_UDP_MTU",
|
||||
"UTP_GET_UDP_OVERHEAD",
|
||||
"UTP_GET_MILLISECONDS",
|
||||
"UTP_GET_MICROSECONDS",
|
||||
"UTP_GET_RANDOM",
|
||||
"UTP_LOG",
|
||||
"UTP_SENDTO",
|
||||
};
|
||||
|
||||
const char * utp_error_code_names[] = {
|
||||
"UTP_ECONNREFUSED",
|
||||
"UTP_ECONNRESET",
|
||||
"UTP_ETIMEDOUT",
|
||||
};
|
||||
|
||||
const char *utp_state_names[] = {
|
||||
NULL,
|
||||
"UTP_STATE_CONNECT",
|
||||
"UTP_STATE_WRITABLE",
|
||||
"UTP_STATE_EOF",
|
||||
"UTP_STATE_DESTROYING",
|
||||
};
|
||||
|
||||
struct_utp_context::struct_utp_context()
|
||||
: userdata(NULL)
|
||||
, current_ms(0)
|
||||
, last_utp_socket(NULL)
|
||||
, log_normal(false)
|
||||
, log_mtu(false)
|
||||
, log_debug(false)
|
||||
{
|
||||
memset(&context_stats, 0, sizeof(context_stats));
|
||||
memset(callbacks, 0, sizeof(callbacks));
|
||||
target_delay = CCONTROL_TARGET;
|
||||
utp_sockets = new UTPSocketHT;
|
||||
|
||||
callbacks[UTP_GET_UDP_MTU] = &utp_default_get_udp_mtu;
|
||||
callbacks[UTP_GET_UDP_OVERHEAD] = &utp_default_get_udp_overhead;
|
||||
callbacks[UTP_GET_MILLISECONDS] = &utp_default_get_milliseconds;
|
||||
callbacks[UTP_GET_MICROSECONDS] = &utp_default_get_microseconds;
|
||||
callbacks[UTP_GET_RANDOM] = &utp_default_get_random;
|
||||
|
||||
// 1 MB of receive buffer (i.e. max bandwidth delay product)
|
||||
// means that from a peer with 200 ms RTT, we cannot receive
|
||||
// faster than 5 MB/s
|
||||
// from a peer with 10 ms RTT, we cannot receive faster than
|
||||
// 100 MB/s. This is assumed to be good enough, since bandwidth
|
||||
// often is proportional to RTT anyway
|
||||
// when setting a download rate limit, all sockets should have
|
||||
// their receive buffer set much lower, to say 60 kiB or so
|
||||
opt_rcvbuf = opt_sndbuf = 1024 * 1024;
|
||||
last_check = 0;
|
||||
}
|
||||
|
||||
struct_utp_context::~struct_utp_context() {
|
||||
delete this->utp_sockets;
|
||||
}
|
||||
|
||||
utp_context* utp_init (int version)
|
||||
{
|
||||
assert(version == 2);
|
||||
if (version != 2)
|
||||
return NULL;
|
||||
utp_context *ctx = new utp_context;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void utp_destroy(utp_context *ctx) {
|
||||
assert(ctx);
|
||||
if (ctx) delete ctx;
|
||||
}
|
||||
|
||||
void utp_set_callback(utp_context *ctx, int callback_name, utp_callback_t *proc) {
|
||||
assert(ctx);
|
||||
if (ctx) ctx->callbacks[callback_name] = proc;
|
||||
}
|
||||
|
||||
void* utp_context_set_userdata(utp_context *ctx, void *userdata) {
|
||||
assert(ctx);
|
||||
if (ctx) ctx->userdata = userdata;
|
||||
return ctx ? ctx->userdata : NULL;
|
||||
}
|
||||
|
||||
void* utp_context_get_userdata(utp_context *ctx) {
|
||||
assert(ctx);
|
||||
return ctx ? ctx->userdata : NULL;
|
||||
}
|
||||
|
||||
utp_context_stats* utp_get_context_stats(utp_context *ctx) {
|
||||
assert(ctx);
|
||||
return ctx ? &ctx->context_stats : NULL;
|
||||
}
|
||||
|
||||
ssize_t utp_write(utp_socket *socket, void *buf, size_t len) {
|
||||
struct utp_iovec iovec = { buf, len };
|
||||
return utp_writev(socket, &iovec, 1);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
// vim:set ts=4 sw=4 ai:
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "utp_callbacks.h"
|
||||
|
||||
int utp_call_on_firewall(utp_context *ctx, const struct sockaddr *address, socklen_t address_len)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_ON_FIREWALL]) return 0;
|
||||
args.callback_type = UTP_ON_FIREWALL;
|
||||
args.context = ctx;
|
||||
args.socket = NULL;
|
||||
args.address = address;
|
||||
args.address_len = address_len;
|
||||
return (int)ctx->callbacks[UTP_ON_FIREWALL](&args);
|
||||
}
|
||||
|
||||
void utp_call_on_accept(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_ON_ACCEPT]) return;
|
||||
args.callback_type = UTP_ON_ACCEPT;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.address = address;
|
||||
args.address_len = address_len;
|
||||
ctx->callbacks[UTP_ON_ACCEPT](&args);
|
||||
}
|
||||
|
||||
void utp_call_on_connect(utp_context *ctx, utp_socket *socket)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_ON_CONNECT]) return;
|
||||
args.callback_type = UTP_ON_CONNECT;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
ctx->callbacks[UTP_ON_CONNECT](&args);
|
||||
}
|
||||
|
||||
void utp_call_on_error(utp_context *ctx, utp_socket *socket, int error_code)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_ON_ERROR]) return;
|
||||
args.callback_type = UTP_ON_ERROR;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.error_code = error_code;
|
||||
ctx->callbacks[UTP_ON_ERROR](&args);
|
||||
}
|
||||
|
||||
void utp_call_on_read(utp_context *ctx, utp_socket *socket, const byte *buf, size_t len)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_ON_READ]) return;
|
||||
args.callback_type = UTP_ON_READ;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.buf = buf;
|
||||
args.len = len;
|
||||
ctx->callbacks[UTP_ON_READ](&args);
|
||||
}
|
||||
|
||||
void utp_call_on_overhead_statistics(utp_context *ctx, utp_socket *socket, int send, size_t len, int type)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_ON_OVERHEAD_STATISTICS]) return;
|
||||
args.callback_type = UTP_ON_OVERHEAD_STATISTICS;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.send = send;
|
||||
args.len = len;
|
||||
args.type = type;
|
||||
ctx->callbacks[UTP_ON_OVERHEAD_STATISTICS](&args);
|
||||
}
|
||||
|
||||
void utp_call_on_delay_sample(utp_context *ctx, utp_socket *socket, int sample_ms)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_ON_DELAY_SAMPLE]) return;
|
||||
args.callback_type = UTP_ON_DELAY_SAMPLE;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.sample_ms = sample_ms;
|
||||
ctx->callbacks[UTP_ON_DELAY_SAMPLE](&args);
|
||||
}
|
||||
|
||||
void utp_call_on_state_change(utp_context *ctx, utp_socket *socket, int state)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_ON_STATE_CHANGE]) return;
|
||||
args.callback_type = UTP_ON_STATE_CHANGE;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.state = state;
|
||||
ctx->callbacks[UTP_ON_STATE_CHANGE](&args);
|
||||
}
|
||||
|
||||
uint16 utp_call_get_udp_mtu(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_GET_UDP_MTU]) return 0;
|
||||
args.callback_type = UTP_GET_UDP_MTU;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.address = address;
|
||||
args.address_len = address_len;
|
||||
return (uint16)ctx->callbacks[UTP_GET_UDP_MTU](&args);
|
||||
}
|
||||
|
||||
uint16 utp_call_get_udp_overhead(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_GET_UDP_OVERHEAD]) return 0;
|
||||
args.callback_type = UTP_GET_UDP_OVERHEAD;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.address = address;
|
||||
args.address_len = address_len;
|
||||
return (uint16)ctx->callbacks[UTP_GET_UDP_OVERHEAD](&args);
|
||||
}
|
||||
|
||||
uint64 utp_call_get_milliseconds(utp_context *ctx, utp_socket *socket)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_GET_MILLISECONDS]) return 0;
|
||||
args.callback_type = UTP_GET_MILLISECONDS;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
return ctx->callbacks[UTP_GET_MILLISECONDS](&args);
|
||||
}
|
||||
|
||||
uint64 utp_call_get_microseconds(utp_context *ctx, utp_socket *socket)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_GET_MICROSECONDS]) return 0;
|
||||
args.callback_type = UTP_GET_MICROSECONDS;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
return ctx->callbacks[UTP_GET_MICROSECONDS](&args);
|
||||
}
|
||||
|
||||
uint32 utp_call_get_random(utp_context *ctx, utp_socket *socket)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_GET_RANDOM]) return 0;
|
||||
args.callback_type = UTP_GET_RANDOM;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
return (uint32)ctx->callbacks[UTP_GET_RANDOM](&args);
|
||||
}
|
||||
|
||||
size_t utp_call_get_read_buffer_size(utp_context *ctx, utp_socket *socket)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_GET_READ_BUFFER_SIZE]) return 0;
|
||||
args.callback_type = UTP_GET_READ_BUFFER_SIZE;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
return (size_t)ctx->callbacks[UTP_GET_READ_BUFFER_SIZE](&args);
|
||||
}
|
||||
|
||||
void utp_call_log(utp_context *ctx, utp_socket *socket, const byte *buf)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_LOG]) return;
|
||||
args.callback_type = UTP_LOG;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.buf = buf;
|
||||
ctx->callbacks[UTP_LOG](&args);
|
||||
}
|
||||
|
||||
void utp_call_sendto(utp_context *ctx, utp_socket *socket, const byte *buf, size_t len, const struct sockaddr *address, socklen_t address_len, uint32 flags)
|
||||
{
|
||||
utp_callback_arguments args;
|
||||
if (!ctx->callbacks[UTP_SENDTO]) return;
|
||||
args.callback_type = UTP_SENDTO;
|
||||
args.context = ctx;
|
||||
args.socket = socket;
|
||||
args.buf = buf;
|
||||
args.len = len;
|
||||
args.address = address;
|
||||
args.address_len = address_len;
|
||||
args.flags = flags;
|
||||
ctx->callbacks[UTP_SENDTO](&args);
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UTP_CALLBACKS_H__
|
||||
#define __UTP_CALLBACKS_H__
|
||||
|
||||
#include "utp.h"
|
||||
#include "utp_internal.h"
|
||||
|
||||
// Generated by running: grep ^[a-z] utp_callbacks.cpp | sed 's/$/;/'
|
||||
int utp_call_on_firewall(utp_context *ctx, const struct sockaddr *address, socklen_t address_len);
|
||||
void utp_call_on_accept(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
|
||||
void utp_call_on_connect(utp_context *ctx, utp_socket *s);
|
||||
void utp_call_on_error(utp_context *ctx, utp_socket *s, int error_code);
|
||||
void utp_call_on_read(utp_context *ctx, utp_socket *s, const byte *buf, size_t len);
|
||||
void utp_call_on_overhead_statistics(utp_context *ctx, utp_socket *s, int send, size_t len, int type);
|
||||
void utp_call_on_delay_sample(utp_context *ctx, utp_socket *s, int sample_ms);
|
||||
void utp_call_on_state_change(utp_context *ctx, utp_socket *s, int state);
|
||||
uint16 utp_call_get_udp_mtu(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
|
||||
uint16 utp_call_get_udp_overhead(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
|
||||
uint64 utp_call_get_milliseconds(utp_context *ctx, utp_socket *s);
|
||||
uint64 utp_call_get_microseconds(utp_context *ctx, utp_socket *s);
|
||||
uint32 utp_call_get_random(utp_context *ctx, utp_socket *s);
|
||||
size_t utp_call_get_read_buffer_size(utp_context *ctx, utp_socket *s);
|
||||
void utp_call_log(utp_context *ctx, utp_socket *s, const byte *buf);
|
||||
void utp_call_sendto(utp_context *ctx, utp_socket *s, const byte *buf, size_t len, const struct sockaddr *address, socklen_t address_len, uint32 flags);
|
||||
|
||||
#endif // __UTP_CALLBACKS_H__
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "utp_hash.h"
|
||||
#include "utp_types.h"
|
||||
|
||||
#define LIBUTP_HASH_UNUSED ((utp_link_t)-1)
|
||||
|
||||
#ifdef STRICT_ALIGN
|
||||
inline uint32 Read32(const void *p)
|
||||
{
|
||||
uint32 tmp;
|
||||
memcpy(&tmp, p, sizeof tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#else
|
||||
inline uint32 Read32(const void *p) { return *(uint32*)p; }
|
||||
#endif
|
||||
|
||||
|
||||
// Get the amount of memory required for the hash parameters and the bucket set
|
||||
// Waste a space for an unused bucket in order to ensure the following managed memory have 32-bit aligned addresses
|
||||
// TODO: make this 64-bit clean
|
||||
#define BASE_SIZE(bc) (sizeof(utp_hash_t) + sizeof(utp_link_t) * ((bc) + 1))
|
||||
|
||||
// Get a pointer to the base of the structure array managed by the hash table
|
||||
#define get_bep(h) ((byte*)(h)) + BASE_SIZE((h)->N)
|
||||
|
||||
// Get the address of the information associated with a specific structure in the array,
|
||||
// given the address of the base of the structure.
|
||||
// This assumes a utp_link_t link member is at the end of the structure.
|
||||
// Given compilers filling out the memory to a 32-bit clean value, this may mean that
|
||||
// the location named in the structure may not be the location actually used by the hash table,
|
||||
// since the compiler may have padded the end of the structure with 2 bytes after the utp_link_t member.
|
||||
// TODO: this macro should not require that the variable pointing at the hash table be named 'hash'
|
||||
#define ptr_to_link(p) (utp_link_t *) (((byte *) (p)) + hash->E - sizeof(utp_link_t))
|
||||
|
||||
// Calculate how much to allocate for a hash table with bucket count, total size, and structure count
|
||||
// TODO: make this 64-bit clean
|
||||
#define ALLOCATION_SIZE(bc, ts, sc) (BASE_SIZE((bc)) + (ts) * (sc))
|
||||
|
||||
utp_hash_t *utp_hash_create(int N, int key_size, int total_size, int initial, utp_hash_compute_t hashfun, utp_hash_equal_t compfun)
|
||||
{
|
||||
// Must have odd number of hash buckets (prime number is best)
|
||||
assert(N % 2);
|
||||
// Ensure structures will be at aligned memory addresses
|
||||
// TODO: make this 64-bit clean
|
||||
assert(0 == (total_size % 4));
|
||||
|
||||
int size = ALLOCATION_SIZE(N, total_size, initial);
|
||||
utp_hash_t *hash = (utp_hash_t *) malloc( size );
|
||||
memset( hash, 0, size );
|
||||
|
||||
for (int i = 0; i < N + 1; ++i)
|
||||
hash->inits[i] = LIBUTP_HASH_UNUSED;
|
||||
hash->N = N;
|
||||
hash->K = key_size;
|
||||
hash->E = total_size;
|
||||
hash->hash_compute = hashfun;
|
||||
hash->hash_equal = compfun;
|
||||
hash->allocated = initial;
|
||||
hash->count = 0;
|
||||
hash->used = 0;
|
||||
hash->free = LIBUTP_HASH_UNUSED;
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint utp_hash_mem(const void *keyp, size_t keysize)
|
||||
{
|
||||
uint hash = 0;
|
||||
uint n = keysize;
|
||||
while (n >= 4) {
|
||||
hash ^= Read32(keyp);
|
||||
keyp = (byte*)keyp + sizeof(uint32);
|
||||
hash = (hash << 13) | (hash >> 19);
|
||||
n -= 4;
|
||||
}
|
||||
while (n != 0) {
|
||||
hash ^= *(byte*)keyp;
|
||||
keyp = (byte*)keyp + sizeof(byte);
|
||||
hash = (hash << 8) | (hash >> 24);
|
||||
n--;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint utp_hash_mkidx(utp_hash_t *hash, const void *keyp)
|
||||
{
|
||||
// Generate a key from the hash
|
||||
return hash->hash_compute(keyp, hash->K) % hash->N;
|
||||
}
|
||||
|
||||
static inline bool compare(byte *a, byte *b,int n)
|
||||
{
|
||||
assert(n >= 4);
|
||||
if (Read32(a) != Read32(b)) return false;
|
||||
return memcmp(a+4, b+4, n-4) == 0;
|
||||
}
|
||||
|
||||
#define COMPARE(h,k1,k2,ks) (((h)->hash_equal) ? (h)->hash_equal((void*)k1,(void*)k2,ks) : compare(k1,k2,ks))
|
||||
|
||||
// Look-up a key in the hash table.
|
||||
// Returns NULL if not found
|
||||
void *utp_hash_lookup(utp_hash_t *hash, const void *key)
|
||||
{
|
||||
utp_link_t idx = utp_hash_mkidx(hash, key);
|
||||
|
||||
// base pointer
|
||||
byte *bep = get_bep(hash);
|
||||
|
||||
utp_link_t cur = hash->inits[idx];
|
||||
while (cur != LIBUTP_HASH_UNUSED) {
|
||||
byte *key2 = bep + (cur * hash->E);
|
||||
if (COMPARE(hash, (byte*)key, key2, hash->K))
|
||||
return key2;
|
||||
cur = *ptr_to_link(key2);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add a new element to the hash table.
|
||||
// Returns a pointer to the new element.
|
||||
// This assumes the element is not already present!
|
||||
void *utp_hash_add(utp_hash_t **hashp, const void *key)
|
||||
{
|
||||
//Allocate a new entry
|
||||
byte *elemp;
|
||||
utp_link_t elem;
|
||||
utp_hash_t *hash = *hashp;
|
||||
utp_link_t idx = utp_hash_mkidx(hash, key);
|
||||
|
||||
if ((elem=hash->free) == LIBUTP_HASH_UNUSED) {
|
||||
utp_link_t all = hash->allocated;
|
||||
if (hash->used == all) {
|
||||
utp_hash_t *nhash;
|
||||
if (all <= (LIBUTP_HASH_UNUSED/2)) {
|
||||
all *= 2;
|
||||
} else if (all != LIBUTP_HASH_UNUSED) {
|
||||
all = LIBUTP_HASH_UNUSED;
|
||||
} else {
|
||||
// too many items! can't grow!
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
// otherwise need to allocate.
|
||||
nhash = (utp_hash_t*)realloc(hash, ALLOCATION_SIZE(hash->N, hash->E, all));
|
||||
if (!nhash) {
|
||||
// out of memory (or too big to allocate)
|
||||
assert(nhash);
|
||||
return NULL;
|
||||
}
|
||||
hash = *hashp = nhash;
|
||||
hash->allocated = all;
|
||||
}
|
||||
|
||||
elem = hash->used++;
|
||||
elemp = get_bep(hash) + elem * hash->E;
|
||||
} else {
|
||||
elemp = get_bep(hash) + elem * hash->E;
|
||||
hash->free = *ptr_to_link(elemp);
|
||||
}
|
||||
|
||||
*ptr_to_link(elemp) = hash->inits[idx];
|
||||
hash->inits[idx] = elem;
|
||||
hash->count++;
|
||||
|
||||
// copy key into it
|
||||
memcpy(elemp, key, hash->K);
|
||||
return elemp;
|
||||
}
|
||||
|
||||
// Delete an element from the utp_hash_t
|
||||
// Returns a pointer to the already deleted element.
|
||||
void *utp_hash_del(utp_hash_t *hash, const void *key)
|
||||
{
|
||||
utp_link_t idx = utp_hash_mkidx(hash, key);
|
||||
|
||||
// base pointer
|
||||
byte *bep = get_bep(hash);
|
||||
|
||||
utp_link_t *curp = &hash->inits[idx];
|
||||
utp_link_t cur;
|
||||
while ((cur=*curp) != LIBUTP_HASH_UNUSED) {
|
||||
byte *key2 = bep + (cur * hash->E);
|
||||
if (COMPARE(hash,(byte*)key,(byte*)key2, hash->K )) {
|
||||
// found an item that matched. unlink it
|
||||
*curp = *ptr_to_link(key2);
|
||||
// Insert into freelist
|
||||
*ptr_to_link(key2) = hash->free;
|
||||
hash->free = cur;
|
||||
hash->count--;
|
||||
return key2;
|
||||
}
|
||||
curp = ptr_to_link(key2);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *utp_hash_iterate(utp_hash_t *hash, utp_hash_iterator_t *iter)
|
||||
{
|
||||
utp_link_t elem;
|
||||
|
||||
if ((elem=iter->elem) == LIBUTP_HASH_UNUSED) {
|
||||
// Find a bucket with an element
|
||||
utp_link_t buck = iter->bucket + 1;
|
||||
for(;;) {
|
||||
if (buck >= hash->N)
|
||||
return NULL;
|
||||
if ((elem = hash->inits[buck]) != LIBUTP_HASH_UNUSED)
|
||||
break;
|
||||
buck++;
|
||||
}
|
||||
iter->bucket = buck;
|
||||
}
|
||||
|
||||
byte *elemp = get_bep(hash) + (elem * hash->E);
|
||||
iter->elem = *ptr_to_link(elemp);
|
||||
return elemp;
|
||||
}
|
||||
|
||||
void utp_hash_free_mem(utp_hash_t* hash)
|
||||
{
|
||||
free(hash);
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UTP_HASH_H__
|
||||
#define __UTP_HASH_H__
|
||||
|
||||
#include <string.h> // memset
|
||||
#include <stdlib.h> // malloc
|
||||
|
||||
#include "utp_types.h"
|
||||
#include "utp_templates.h"
|
||||
|
||||
// TODO: make utp_link_t a template parameter to HashTable
|
||||
typedef uint32 utp_link_t;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Silence the warning about the C99-compliant zero-length array at the end of the structure
|
||||
#pragma warning (disable: 4200)
|
||||
#endif
|
||||
|
||||
typedef uint32 (*utp_hash_compute_t)(const void *keyp, size_t keysize);
|
||||
typedef uint (*utp_hash_equal_t)(const void *key_a, const void *key_b, size_t keysize);
|
||||
|
||||
// In memory the HashTable is laid out as follows:
|
||||
// ---------------------------- low
|
||||
// | hash table data members |
|
||||
// ---------------------------- _
|
||||
// | indices | ^
|
||||
// | . | | utp_link_t indices into the key-values.
|
||||
// | . | .
|
||||
// ---------------------------- - <----- bep
|
||||
// | keys and values | each key-value pair has size total_size
|
||||
// | . |
|
||||
// | . |
|
||||
// ---------------------------- high
|
||||
//
|
||||
// The code depends on the ability of the compiler to pad the length
|
||||
// of the hash table data members structure to
|
||||
// a length divisible by 32-bits with no remainder.
|
||||
//
|
||||
// Since the number of hash buckets (indices) should be odd, the code
|
||||
// asserts this and adds one to the hash bucket count to ensure that the
|
||||
// following key-value pairs array starts on a 32-bit boundary.
|
||||
//
|
||||
// The key-value pairs array should start on a 32-bit boundary, otherwise
|
||||
// processors like the ARM will silently mangle 32-bit data in these structures
|
||||
// (e.g., turning 0xABCD into 0XCDAB when moving a value from memory to register
|
||||
// when the memory address is 16 bits offset from a 32-bit boundary),
|
||||
// also, the value will be stored at an address two bytes lower than the address
|
||||
// value would ordinarily indicate.
|
||||
//
|
||||
// The key-value pair is of type T. The first field in T must
|
||||
// be the key, i.e., the first K bytes of T contains the key.
|
||||
// total_size = sizeof(T) and thus sizeof(T) >= sizeof(K)
|
||||
//
|
||||
// N is the number of buckets.
|
||||
//
|
||||
struct utp_hash_t {
|
||||
utp_link_t N;
|
||||
byte K;
|
||||
byte E;
|
||||
size_t count;
|
||||
utp_hash_compute_t hash_compute;
|
||||
utp_hash_equal_t hash_equal;
|
||||
utp_link_t allocated;
|
||||
utp_link_t used;
|
||||
utp_link_t free;
|
||||
utp_link_t inits[0];
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (default: 4200)
|
||||
#endif
|
||||
|
||||
struct utp_hash_iterator_t {
|
||||
utp_link_t bucket;
|
||||
utp_link_t elem;
|
||||
|
||||
utp_hash_iterator_t() : bucket(0xffffffff), elem(0xffffffff) {}
|
||||
};
|
||||
|
||||
uint utp_hash_mem(const void *keyp, size_t keysize);
|
||||
uint utp_hash_comp(const void *key_a, const void *key_b, size_t keysize);
|
||||
|
||||
utp_hash_t *utp_hash_create(int N, int key_size, int total_size, int initial, utp_hash_compute_t hashfun = utp_hash_mem, utp_hash_equal_t eqfun = NULL);
|
||||
void *utp_hash_lookup(utp_hash_t *hash, const void *key);
|
||||
void *utp_hash_add(utp_hash_t **hashp, const void *key);
|
||||
void *utp_hash_del(utp_hash_t *hash, const void *key);
|
||||
|
||||
void *utp_hash_iterate(utp_hash_t *hash, utp_hash_iterator_t *iter);
|
||||
void utp_hash_free_mem(utp_hash_t *hash);
|
||||
|
||||
/*
|
||||
This HashTable requires that T have at least sizeof(K)+sizeof(utp_link_t) bytes.
|
||||
Usually done like this:
|
||||
|
||||
struct K {
|
||||
int whatever;
|
||||
};
|
||||
|
||||
struct T {
|
||||
K wtf;
|
||||
utp_link_t link; // also wtf
|
||||
};
|
||||
*/
|
||||
|
||||
template<typename K, typename T> class utpHashTable {
|
||||
utp_hash_t *hash;
|
||||
public:
|
||||
static uint compare(const void *k1, const void *k2, size_t ks) {
|
||||
return *((K*)k1) == *((K*)k2);
|
||||
}
|
||||
static uint32 compute_hash(const void *k, size_t ks) {
|
||||
return ((K*)k)->compute_hash();
|
||||
}
|
||||
void Init() { hash = NULL; }
|
||||
bool Allocated() { return (hash != NULL); }
|
||||
void Free() { utp_hash_free_mem(hash); hash = NULL; }
|
||||
void Create(int N, int initial) { hash = utp_hash_create(N, sizeof(K), sizeof(T), initial, &compute_hash, &compare); }
|
||||
T *Lookup(const K &key) { return (T*)utp_hash_lookup(hash, &key); }
|
||||
T *Add(const K &key) { return (T*)utp_hash_add(&hash, &key); }
|
||||
T *Delete(const K &key) { return (T*)utp_hash_del(hash, &key); }
|
||||
T *Iterate(utp_hash_iterator_t &iterator) { return (T*)utp_hash_iterate(hash, &iterator); }
|
||||
size_t GetCount() { return hash->count; }
|
||||
};
|
||||
|
||||
#endif //__UTP_HASH_H__
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UTP_INTERNAL_H__
|
||||
#define __UTP_INTERNAL_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "utp.h"
|
||||
#include "utp_callbacks.h"
|
||||
#include "utp_templates.h"
|
||||
#include "utp_hash.h"
|
||||
#include "utp_hash.h"
|
||||
#include "utp_packedsockaddr.h"
|
||||
|
||||
/* These originally lived in utp_config.h */
|
||||
#define CCONTROL_TARGET (100 * 1000) // us
|
||||
|
||||
enum bandwidth_type_t {
|
||||
payload_bandwidth, connect_overhead,
|
||||
close_overhead, ack_overhead,
|
||||
header_overhead, retransmit_overhead
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _MSC_VER
|
||||
#include "libutp_inet_ntop.h"
|
||||
#endif
|
||||
|
||||
// newer versions of MSVC define these in errno.h
|
||||
#ifndef ECONNRESET
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#define EMSGSIZE WSAEMSGSIZE
|
||||
#define ECONNREFUSED WSAECONNREFUSED
|
||||
#define ETIMEDOUT WSAETIMEDOUT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct PACKED_ATTRIBUTE RST_Info {
|
||||
PackedSockAddr addr;
|
||||
uint32 connid;
|
||||
uint16 ack_nr;
|
||||
uint64 timestamp;
|
||||
};
|
||||
|
||||
// It's really important that we don't have duplicate keys in the hash table.
|
||||
// If we do, we'll eventually crash. if we try to remove the second instance
|
||||
// of the key, we'll accidentally remove the first instead. then later,
|
||||
// checkTimeouts will try to access the second one's already freed memory.
|
||||
void UTP_FreeAll(struct UTPSocketHT *utp_sockets);
|
||||
|
||||
struct UTPSocketKey {
|
||||
PackedSockAddr addr;
|
||||
uint32 recv_id; // "conn_seed", "conn_id"
|
||||
|
||||
UTPSocketKey(const PackedSockAddr& _addr, uint32 _recv_id) {
|
||||
memset(this, 0, sizeof(*this));
|
||||
addr = _addr;
|
||||
recv_id = _recv_id;
|
||||
}
|
||||
|
||||
bool operator == (const UTPSocketKey &other) const {
|
||||
return recv_id == other.recv_id && addr == other.addr;
|
||||
}
|
||||
|
||||
uint32 compute_hash() const {
|
||||
return recv_id ^ addr.compute_hash();
|
||||
}
|
||||
};
|
||||
|
||||
struct UTPSocketKeyData {
|
||||
UTPSocketKey key;
|
||||
UTPSocket *socket;
|
||||
utp_link_t link;
|
||||
};
|
||||
|
||||
#define UTP_SOCKET_BUCKETS 79
|
||||
#define UTP_SOCKET_INIT 15
|
||||
|
||||
struct UTPSocketHT : utpHashTable<UTPSocketKey, UTPSocketKeyData> {
|
||||
UTPSocketHT() {
|
||||
const int buckets = UTP_SOCKET_BUCKETS;
|
||||
const int initial = UTP_SOCKET_INIT;
|
||||
this->Create(buckets, initial);
|
||||
}
|
||||
~UTPSocketHT() {
|
||||
UTP_FreeAll(this);
|
||||
this->Free();
|
||||
}
|
||||
};
|
||||
|
||||
struct struct_utp_context {
|
||||
void *userdata;
|
||||
utp_callback_t* callbacks[UTP_ARRAY_SIZE];
|
||||
|
||||
uint64 current_ms;
|
||||
utp_context_stats context_stats;
|
||||
UTPSocket *last_utp_socket;
|
||||
Array<UTPSocket*> ack_sockets;
|
||||
Array<RST_Info> rst_info;
|
||||
UTPSocketHT *utp_sockets;
|
||||
size_t target_delay;
|
||||
size_t opt_sndbuf;
|
||||
size_t opt_rcvbuf;
|
||||
uint64 last_check;
|
||||
|
||||
struct_utp_context();
|
||||
~struct_utp_context();
|
||||
|
||||
void log(int level, utp_socket *socket, char const *fmt, ...);
|
||||
void log_unchecked(utp_socket *socket, char const *fmt, ...);
|
||||
bool would_log(int level);
|
||||
|
||||
bool log_normal:1; // log normal events?
|
||||
bool log_mtu:1; // log MTU related events?
|
||||
bool log_debug:1; // log debugging events? (Must also compile with UTP_DEBUG_LOGGING defined)
|
||||
};
|
||||
|
||||
#endif //__UTP_INTERNAL_H__
|
|
@ -0,0 +1,139 @@
|
|||
// vim:set ts=4 sw=4 ai:
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "utp_types.h"
|
||||
#include "utp_hash.h"
|
||||
#include "utp_packedsockaddr.h"
|
||||
|
||||
#include "libutp_inet_ntop.h"
|
||||
|
||||
byte PackedSockAddr::get_family() const
|
||||
{
|
||||
#if defined(__sh__)
|
||||
return ((_sin6d[0] == 0) && (_sin6d[1] == 0) && (_sin6d[2] == htonl(0xffff)) != 0) ?
|
||||
AF_INET : AF_INET6;
|
||||
#else
|
||||
return (IN6_IS_ADDR_V4MAPPED(&_in._in6addr) != 0) ? AF_INET : AF_INET6;
|
||||
#endif // defined(__sh__)
|
||||
}
|
||||
|
||||
bool PackedSockAddr::operator==(const PackedSockAddr& rhs) const
|
||||
{
|
||||
if (&rhs == this)
|
||||
return true;
|
||||
if (_port != rhs._port)
|
||||
return false;
|
||||
return memcmp(_sin6, rhs._sin6, sizeof(_sin6)) == 0;
|
||||
}
|
||||
|
||||
bool PackedSockAddr::operator!=(const PackedSockAddr& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
uint32 PackedSockAddr::compute_hash() const {
|
||||
return utp_hash_mem(&_in, sizeof(_in)) ^ _port;
|
||||
}
|
||||
|
||||
void PackedSockAddr::set(const SOCKADDR_STORAGE* sa, socklen_t len)
|
||||
{
|
||||
if (sa->ss_family == AF_INET) {
|
||||
assert(len >= sizeof(sockaddr_in));
|
||||
const sockaddr_in *sin = (sockaddr_in*)sa;
|
||||
_sin6w[0] = 0;
|
||||
_sin6w[1] = 0;
|
||||
_sin6w[2] = 0;
|
||||
_sin6w[3] = 0;
|
||||
_sin6w[4] = 0;
|
||||
_sin6w[5] = 0xffff;
|
||||
_sin4 = sin->sin_addr.s_addr;
|
||||
_port = ntohs(sin->sin_port);
|
||||
} else {
|
||||
assert(len >= sizeof(sockaddr_in6));
|
||||
const sockaddr_in6 *sin6 = (sockaddr_in6*)sa;
|
||||
_in._in6addr = sin6->sin6_addr;
|
||||
_port = ntohs(sin6->sin6_port);
|
||||
}
|
||||
}
|
||||
|
||||
PackedSockAddr::PackedSockAddr(const SOCKADDR_STORAGE* sa, socklen_t len)
|
||||
{
|
||||
set(sa, len);
|
||||
}
|
||||
|
||||
PackedSockAddr::PackedSockAddr(void)
|
||||
{
|
||||
SOCKADDR_STORAGE sa;
|
||||
socklen_t len = sizeof(SOCKADDR_STORAGE);
|
||||
memset(&sa, 0, len);
|
||||
sa.ss_family = AF_INET;
|
||||
set(&sa, len);
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE PackedSockAddr::get_sockaddr_storage(socklen_t *len = NULL) const
|
||||
{
|
||||
SOCKADDR_STORAGE sa;
|
||||
const byte family = get_family();
|
||||
if (family == AF_INET) {
|
||||
sockaddr_in *sin = (sockaddr_in*)&sa;
|
||||
if (len) *len = sizeof(sockaddr_in);
|
||||
memset(sin, 0, sizeof(sockaddr_in));
|
||||
sin->sin_family = family;
|
||||
sin->sin_port = htons(_port);
|
||||
sin->sin_addr.s_addr = _sin4;
|
||||
} else {
|
||||
sockaddr_in6 *sin6 = (sockaddr_in6*)&sa;
|
||||
memset(sin6, 0, sizeof(sockaddr_in6));
|
||||
if (len) *len = sizeof(sockaddr_in6);
|
||||
sin6->sin6_family = family;
|
||||
sin6->sin6_addr = _in._in6addr;
|
||||
sin6->sin6_port = htons(_port);
|
||||
}
|
||||
return sa;
|
||||
}
|
||||
|
||||
// #define addrfmt(x, s) x.fmt(s, sizeof(s))
|
||||
cstr PackedSockAddr::fmt(str s, size_t len) const
|
||||
{
|
||||
memset(s, 0, len);
|
||||
const byte family = get_family();
|
||||
str i;
|
||||
if (family == AF_INET) {
|
||||
INET_NTOP(family, (uint32*)&_sin4, s, len);
|
||||
i = s;
|
||||
while (*++i) {}
|
||||
} else {
|
||||
i = s;
|
||||
*i++ = '[';
|
||||
INET_NTOP(family, (in6_addr*)&_in._in6addr, i, len-1);
|
||||
while (*++i) {}
|
||||
*i++ = ']';
|
||||
}
|
||||
snprintf(i, len - (i-s), ":%u", _port);
|
||||
return s;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UTP_PACKEDSOCKADDR_H__
|
||||
#define __UTP_PACKEDSOCKADDR_H__
|
||||
|
||||
#include "utp_types.h"
|
||||
|
||||
struct PACKED_ATTRIBUTE PackedSockAddr {
|
||||
// The values are always stored here in network byte order
|
||||
union {
|
||||
byte _in6[16]; // IPv6
|
||||
uint16 _in6w[8]; // IPv6, word based (for convenience)
|
||||
uint32 _in6d[4]; // Dword access
|
||||
in6_addr _in6addr; // For convenience
|
||||
} _in;
|
||||
|
||||
// Host byte order
|
||||
uint16 _port;
|
||||
|
||||
#define _sin4 _in._in6d[3] // IPv4 is stored where it goes if mapped
|
||||
|
||||
#define _sin6 _in._in6
|
||||
#define _sin6w _in._in6w
|
||||
#define _sin6d _in._in6d
|
||||
|
||||
byte get_family() const;
|
||||
bool operator==(const PackedSockAddr& rhs) const;
|
||||
bool operator!=(const PackedSockAddr& rhs) const;
|
||||
void set(const SOCKADDR_STORAGE* sa, socklen_t len);
|
||||
|
||||
PackedSockAddr(const SOCKADDR_STORAGE* sa, socklen_t len);
|
||||
PackedSockAddr(void);
|
||||
|
||||
SOCKADDR_STORAGE get_sockaddr_storage(socklen_t *len) const;
|
||||
cstr fmt(str s, size_t len) const;
|
||||
|
||||
uint32 compute_hash() const;
|
||||
} ALIGNED_ATTRIBUTE(4);
|
||||
|
||||
#endif //__UTP_PACKEDSOCKADDR_H__
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __TEMPLATES_H__
|
||||
#define __TEMPLATES_H__
|
||||
|
||||
#include "utp_types.h"
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(POSIX)
|
||||
/* Allow over-writing FORCEINLINE from makefile because gcc 3.4.4 for buffalo
|
||||
doesn't seem to support __attribute__((always_inline)) in -O0 build
|
||||
(strangely, it works in -Os build) */
|
||||
#ifndef FORCEINLINE
|
||||
// The always_inline attribute asks gcc to inline the function even if no optimization is being requested.
|
||||
// This macro should be used exclusive-or with the inline directive (use one or the other but not both)
|
||||
// since Microsoft uses __forceinline to also mean inline,
|
||||
// and this code is following a Microsoft compatibility model.
|
||||
// Just setting the attribute without also specifying the inline directive apparently won't inline the function,
|
||||
// as evidenced by multiply-defined symbols found at link time.
|
||||
#define FORCEINLINE inline __attribute__((always_inline))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Utility templates
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
template <typename T> static inline T min(T a, T b) { if (a < b) return a; return b; }
|
||||
template <typename T> static inline T max(T a, T b) { if (a > b) return a; return b; }
|
||||
|
||||
template <typename T> static inline T min(T a, T b, T c) { return min(min(a,b),c); }
|
||||
template <typename T> static inline T max(T a, T b, T c) { return max(max(a,b),c); }
|
||||
template <typename T> static inline T clamp(T v, T mi, T ma)
|
||||
{
|
||||
if (v > ma) v = ma;
|
||||
if (v < mi) v = mi;
|
||||
return v;
|
||||
}
|
||||
|
||||
#if (defined(__SVR4) && defined(__sun))
|
||||
#pragma pack(1)
|
||||
#else
|
||||
#pragma pack(push,1)
|
||||
#endif
|
||||
|
||||
|
||||
namespace aux
|
||||
{
|
||||
FORCEINLINE uint16 host_to_network(uint16 i) { return htons(i); }
|
||||
FORCEINLINE uint32 host_to_network(uint32 i) { return htonl(i); }
|
||||
FORCEINLINE int32 host_to_network(int32 i) { return htonl(i); }
|
||||
FORCEINLINE uint16 network_to_host(uint16 i) { return ntohs(i); }
|
||||
FORCEINLINE uint32 network_to_host(uint32 i) { return ntohl(i); }
|
||||
FORCEINLINE int32 network_to_host(int32 i) { return ntohl(i); }
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct PACKED_ATTRIBUTE big_endian
|
||||
{
|
||||
T operator=(T i) { m_integer = aux::host_to_network(i); return i; }
|
||||
operator T() const { return aux::network_to_host(m_integer); }
|
||||
private:
|
||||
T m_integer;
|
||||
};
|
||||
|
||||
typedef big_endian<int32> int32_big;
|
||||
typedef big_endian<uint32> uint32_big;
|
||||
typedef big_endian<uint16> uint16_big;
|
||||
|
||||
#if (defined(__SVR4) && defined(__sun))
|
||||
#pragma pack(0)
|
||||
#else
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); }
|
||||
|
||||
typedef int SortCompareProc(const void *, const void *);
|
||||
|
||||
template<typename T> static FORCEINLINE void QuickSortT(T *base, size_t num, int (*comp)(const T *, const T *)) { qsort(base, num, sizeof(T), (SortCompareProc*)comp); }
|
||||
|
||||
|
||||
// WARNING: The template parameter MUST be a POD type!
|
||||
template <typename T, size_t minsize = 16> class Array {
|
||||
protected:
|
||||
T *mem;
|
||||
size_t alloc,count;
|
||||
|
||||
public:
|
||||
Array(size_t init) { Init(init); }
|
||||
Array() { Init(); }
|
||||
~Array() { Free(); }
|
||||
|
||||
void inline Init() { mem = NULL; alloc = count = 0; }
|
||||
void inline Init(size_t init) { Init(); if (init) Resize(init); }
|
||||
size_t inline GetCount() const { return count; }
|
||||
size_t inline GetAlloc() const { return alloc; }
|
||||
void inline SetCount(size_t c) { count = c; }
|
||||
|
||||
inline T& operator[](size_t offset) { assert(offset ==0 || offset<alloc); return mem[offset]; }
|
||||
inline const T& operator[](size_t offset) const { assert(offset ==0 || offset<alloc); return mem[offset]; }
|
||||
|
||||
void inline Resize(size_t a) {
|
||||
if (a == 0) { free(mem); Init(); }
|
||||
else { mem = (T*)realloc(mem, (alloc=a) * sizeof(T)); }
|
||||
}
|
||||
|
||||
void Grow() { Resize(::max<size_t>(minsize, alloc * 2)); }
|
||||
|
||||
inline size_t Append(const T &t) {
|
||||
if (count >= alloc) Grow();
|
||||
size_t r=count++;
|
||||
mem[r] = t;
|
||||
return r;
|
||||
}
|
||||
|
||||
T inline &Append() {
|
||||
if (count >= alloc) Grow();
|
||||
return mem[count++];
|
||||
}
|
||||
|
||||
void inline Compact() {
|
||||
Resize(count);
|
||||
}
|
||||
|
||||
void inline Free() {
|
||||
free(mem);
|
||||
Init();
|
||||
}
|
||||
|
||||
void inline Clear() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
bool inline MoveUpLast(size_t index) {
|
||||
assert(index < count);
|
||||
size_t c = --count;
|
||||
if (index != c) {
|
||||
mem[index] = mem[c];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool inline MoveUpLastExist(const T &v) {
|
||||
return MoveUpLast(LookupElementExist(v));
|
||||
}
|
||||
|
||||
size_t inline LookupElement(const T &v) const {
|
||||
for(size_t i = 0; i != count; i++)
|
||||
if (mem[i] == v)
|
||||
return i;
|
||||
return (size_t) -1;
|
||||
}
|
||||
|
||||
bool inline HasElement(const T &v) const {
|
||||
return LookupElement(v) != -1;
|
||||
}
|
||||
|
||||
typedef int SortCompareProc(const T *a, const T *b);
|
||||
|
||||
void Sort(SortCompareProc* proc, size_t start, size_t end) {
|
||||
QuickSortT(&mem[start], end - start, proc);
|
||||
}
|
||||
|
||||
void Sort(SortCompareProc* proc, size_t start) {
|
||||
Sort(proc, start, count);
|
||||
}
|
||||
|
||||
void Sort(SortCompareProc* proc) {
|
||||
Sort(proc, 0, count);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //__TEMPLATES_H__
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "utp.h"
|
||||
#include "utp_types.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else //!WIN32
|
||||
#include <time.h>
|
||||
#include <sys/time.h> // Linux needs both time.h and sys/time.h
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#include "utp_utils.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
typedef ULONGLONG (WINAPI GetTickCount64Proc)(void);
|
||||
static GetTickCount64Proc *pt2GetTickCount64;
|
||||
static GetTickCount64Proc *pt2RealGetTickCount;
|
||||
|
||||
static uint64 startPerformanceCounter;
|
||||
static uint64 startGetTickCount;
|
||||
// MSVC 6 standard doesn't like division with uint64s
|
||||
static double counterPerMicrosecond;
|
||||
|
||||
static uint64 UTGetTickCount64()
|
||||
{
|
||||
if (pt2GetTickCount64) {
|
||||
return pt2GetTickCount64();
|
||||
}
|
||||
if (pt2RealGetTickCount) {
|
||||
uint64 v = pt2RealGetTickCount();
|
||||
// fix return value from GetTickCount
|
||||
return (DWORD)v | ((v >> 0x18) & 0xFFFFFFFF00000000);
|
||||
}
|
||||
return (uint64)GetTickCount();
|
||||
}
|
||||
|
||||
static void Time_Initialize()
|
||||
{
|
||||
HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
|
||||
pt2GetTickCount64 = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount64");
|
||||
// not a typo. GetTickCount actually returns 64 bits
|
||||
pt2RealGetTickCount = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount");
|
||||
|
||||
uint64 frequency;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&startPerformanceCounter);
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
|
||||
counterPerMicrosecond = (double)frequency / 1000000.0f;
|
||||
startGetTickCount = UTGetTickCount64();
|
||||
}
|
||||
|
||||
static int64 abs64(int64 x) { return x < 0 ? -x : x; }
|
||||
|
||||
static uint64 __GetMicroseconds()
|
||||
{
|
||||
static bool time_init = false;
|
||||
if (!time_init) {
|
||||
time_init = true;
|
||||
Time_Initialize();
|
||||
}
|
||||
|
||||
uint64 counter;
|
||||
uint64 tick;
|
||||
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &counter);
|
||||
tick = UTGetTickCount64();
|
||||
|
||||
// unfortunately, QueryPerformanceCounter is not guaranteed
|
||||
// to be monotonic. Make it so.
|
||||
int64 ret = (int64)(((int64)counter - (int64)startPerformanceCounter) / counterPerMicrosecond);
|
||||
// if the QPC clock leaps more than one second off GetTickCount64()
|
||||
// something is seriously fishy. Adjust QPC to stay monotonic
|
||||
int64 tick_diff = tick - startGetTickCount;
|
||||
if (abs64(ret / 100000 - tick_diff / 100) > 10) {
|
||||
startPerformanceCounter -= (uint64)((int64)(tick_diff * 1000 - ret) * counterPerMicrosecond);
|
||||
ret = (int64)((counter - startPerformanceCounter) / counterPerMicrosecond);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint64 UTP_GetMilliseconds()
|
||||
{
|
||||
return GetTickCount();
|
||||
}
|
||||
|
||||
#else //!WIN32
|
||||
|
||||
static inline uint64 UTP_GetMicroseconds(void);
|
||||
static inline uint64 UTP_GetMilliseconds()
|
||||
{
|
||||
return UTP_GetMicroseconds() / 1000;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
static uint64 __GetMicroseconds()
|
||||
{
|
||||
// http://developer.apple.com/mac/library/qa/qa2004/qa1398.html
|
||||
// http://www.macresearch.org/tutorial_performance_and_time
|
||||
static mach_timebase_info_data_t sTimebaseInfo;
|
||||
static uint64_t start_tick = 0;
|
||||
uint64_t tick;
|
||||
// Returns a counter in some fraction of a nanoseconds
|
||||
tick = mach_absolute_time();
|
||||
if (sTimebaseInfo.denom == 0) {
|
||||
// Get the timer ratio to convert mach_absolute_time to nanoseconds
|
||||
mach_timebase_info(&sTimebaseInfo);
|
||||
start_tick = tick;
|
||||
}
|
||||
// Calculate the elapsed time, convert it to microseconds and return it.
|
||||
return ((tick - start_tick) * sTimebaseInfo.numer) / (sTimebaseInfo.denom * 1000);
|
||||
}
|
||||
|
||||
#else // !__APPLE__
|
||||
|
||||
#if ! (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC))
|
||||
#warning "Using non-monotonic function gettimeofday() in UTP_GetMicroseconds()"
|
||||
#endif
|
||||
|
||||
/* Unfortunately, #ifdef CLOCK_MONOTONIC is not enough to make sure that
|
||||
POSIX clocks work -- we could be running a recent libc with an ancient
|
||||
kernel (think OpenWRT). -- jch */
|
||||
|
||||
static uint64_t __GetMicroseconds()
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC)
|
||||
static int have_posix_clocks = -1;
|
||||
int rc;
|
||||
|
||||
if (have_posix_clocks < 0) {
|
||||
struct timespec ts;
|
||||
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
if (rc < 0) {
|
||||
have_posix_clocks = 0;
|
||||
} else {
|
||||
have_posix_clocks = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (have_posix_clocks) {
|
||||
struct timespec ts;
|
||||
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return uint64(ts.tv_sec) * 1000000 + uint64(ts.tv_nsec) / 1000;
|
||||
}
|
||||
#endif
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
return uint64(tv.tv_sec) * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
#endif //!__APPLE__
|
||||
|
||||
#endif //!WIN32
|
||||
|
||||
/*
|
||||
* Whew. Okay. After that #ifdef maze above, we now know we have a working
|
||||
* __GetMicroseconds() implementation on all platforms.
|
||||
*
|
||||
* Because there are a number of assertions in libutp that will cause a crash
|
||||
* if monotonic time isn't monotonic, now apply some safety checks. While in
|
||||
* principle we're already protecting ourselves in cases where non-monotonic
|
||||
* time is likely to happen, this protects all versions.
|
||||
*/
|
||||
|
||||
static inline uint64 UTP_GetMicroseconds()
|
||||
{
|
||||
static uint64 offset = 0, previous = 0;
|
||||
|
||||
uint64 now = __GetMicroseconds() + offset;
|
||||
if (previous > now) {
|
||||
/* Eek! */
|
||||
offset += previous - now;
|
||||
now = previous;
|
||||
}
|
||||
previous = now;
|
||||
return now;
|
||||
}
|
||||
|
||||
#define ETHERNET_MTU 1500
|
||||
#define IPV4_HEADER_SIZE 20
|
||||
#define IPV6_HEADER_SIZE 40
|
||||
#define UDP_HEADER_SIZE 8
|
||||
#define GRE_HEADER_SIZE 24
|
||||
#define PPPOE_HEADER_SIZE 8
|
||||
#define MPPE_HEADER_SIZE 2
|
||||
// packets have been observed in the wild that were fragmented
|
||||
// with a payload of 1416 for the first fragment
|
||||
// There are reports of routers that have MTU sizes as small as 1392
|
||||
#define FUDGE_HEADER_SIZE 36
|
||||
#define TEREDO_MTU 1280
|
||||
|
||||
#define UDP_IPV4_OVERHEAD (IPV4_HEADER_SIZE + UDP_HEADER_SIZE)
|
||||
#define UDP_IPV6_OVERHEAD (IPV6_HEADER_SIZE + UDP_HEADER_SIZE)
|
||||
#define UDP_TEREDO_OVERHEAD (UDP_IPV4_OVERHEAD + UDP_IPV6_OVERHEAD)
|
||||
|
||||
#define UDP_IPV4_MTU (ETHERNET_MTU - IPV4_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
|
||||
#define UDP_IPV6_MTU (ETHERNET_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
|
||||
#define UDP_TEREDO_MTU (TEREDO_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE)
|
||||
|
||||
uint64 utp_default_get_udp_mtu(utp_callback_arguments *args) {
|
||||
// Since we don't know the local address of the interface,
|
||||
// be conservative and assume all IPv6 connections are Teredo.
|
||||
return (args->address->sa_family == AF_INET6) ? UDP_TEREDO_MTU : UDP_IPV4_MTU;
|
||||
}
|
||||
|
||||
uint64 utp_default_get_udp_overhead(utp_callback_arguments *args) {
|
||||
// Since we don't know the local address of the interface,
|
||||
// be conservative and assume all IPv6 connections are Teredo.
|
||||
return (args->address->sa_family == AF_INET6) ? UDP_TEREDO_OVERHEAD : UDP_IPV4_OVERHEAD;
|
||||
}
|
||||
|
||||
uint64 utp_default_get_random(utp_callback_arguments *args) {
|
||||
return rand();
|
||||
}
|
||||
|
||||
uint64 utp_default_get_milliseconds(utp_callback_arguments *args) {
|
||||
return UTP_GetMilliseconds();
|
||||
}
|
||||
|
||||
uint64 utp_default_get_microseconds(utp_callback_arguments *args) {
|
||||
return UTP_GetMicroseconds();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 BitTorrent, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
uint64 utp_default_get_udp_mtu(utp_callback_arguments *args);
|
||||
uint64 utp_default_get_udp_overhead(utp_callback_arguments *args);
|
||||
uint64 utp_default_get_random(utp_callback_arguments *args);
|
||||
uint64 utp_default_get_milliseconds(utp_callback_arguments *args);
|
||||
uint64 utp_default_get_microseconds(utp_callback_arguments *args);
|
|
@ -1,276 +1,169 @@
|
|||
#include "address_info.hpp"
|
||||
#include <llarp/address_info.hpp>
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <llarp/bencode.h>
|
||||
#include <llarp/mem.h>
|
||||
#include <llarp/string.h>
|
||||
#include <llarp/net.hpp>
|
||||
|
||||
static bool
|
||||
llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
|
||||
namespace llarp
|
||||
{
|
||||
uint64_t i;
|
||||
char tmp[128] = {0};
|
||||
|
||||
llarp_buffer_t strbuf;
|
||||
llarp_ai *ai = static_cast< llarp_ai * >(r->user);
|
||||
|
||||
// done
|
||||
if(!key)
|
||||
return true;
|
||||
|
||||
// rank
|
||||
if(llarp_buffer_eq(*key, "c"))
|
||||
AddressInfo::~AddressInfo()
|
||||
{
|
||||
if(!bencode_read_integer(r->buffer, &i))
|
||||
return false;
|
||||
|
||||
if(i > 65536 || i <= 0)
|
||||
return false;
|
||||
|
||||
ai->rank = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
// dialect
|
||||
if(llarp_buffer_eq(*key, "d"))
|
||||
AddressInfo &
|
||||
AddressInfo::operator=(const AddressInfo &other)
|
||||
{
|
||||
if(!bencode_read_string(r->buffer, &strbuf))
|
||||
return false;
|
||||
|
||||
if(strbuf.sz >= sizeof(ai->dialect))
|
||||
return false;
|
||||
|
||||
memcpy(ai->dialect, strbuf.base, strbuf.sz);
|
||||
ai->dialect[strbuf.sz] = 0;
|
||||
return true;
|
||||
rank = other.rank;
|
||||
dialect = other.dialect;
|
||||
pubkey = other.pubkey;
|
||||
memcpy(ip.s6_addr, other.ip.s6_addr, 16);
|
||||
port = other.port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// encryption public key
|
||||
if(llarp_buffer_eq(*key, "e"))
|
||||
bool
|
||||
AddressInfo::operator==(const AddressInfo &other) const
|
||||
{
|
||||
if(!bencode_read_string(r->buffer, &strbuf))
|
||||
return false;
|
||||
|
||||
if(strbuf.sz != PUBKEYSIZE)
|
||||
return false;
|
||||
|
||||
memcpy(ai->enc_key, strbuf.base, PUBKEYSIZE);
|
||||
return true;
|
||||
// we don't care about rank
|
||||
return pubkey == other.pubkey && port == other.port
|
||||
&& dialect == other.dialect && ip == other.ip;
|
||||
}
|
||||
|
||||
// ip address
|
||||
if(llarp_buffer_eq(*key, "i"))
|
||||
bool
|
||||
AddressInfo::operator<(const AddressInfo &other) const
|
||||
{
|
||||
if(!bencode_read_string(r->buffer, &strbuf))
|
||||
return rank < other.rank || ip < other.ip || port < other.port;
|
||||
}
|
||||
|
||||
bool
|
||||
AddressInfo::DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf)
|
||||
{
|
||||
uint64_t i;
|
||||
char tmp[128] = {0};
|
||||
|
||||
llarp_buffer_t strbuf;
|
||||
|
||||
// rank
|
||||
if(llarp_buffer_eq(key, "c"))
|
||||
{
|
||||
if(!bencode_read_integer(buf, &i))
|
||||
return false;
|
||||
|
||||
if(i > 65536 || i <= 0)
|
||||
return false;
|
||||
|
||||
rank = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
// dialect
|
||||
if(llarp_buffer_eq(key, "d"))
|
||||
{
|
||||
if(!bencode_read_string(buf, &strbuf))
|
||||
return false;
|
||||
if(strbuf.sz > sizeof(tmp))
|
||||
return false;
|
||||
memcpy(tmp, strbuf.base, strbuf.sz);
|
||||
tmp[strbuf.sz] = 0;
|
||||
dialect = std::string(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
// encryption public key
|
||||
if(llarp_buffer_eq(key, "e"))
|
||||
{
|
||||
if(!bencode_read_string(buf, &strbuf))
|
||||
return false;
|
||||
|
||||
if(strbuf.sz != PUBKEYSIZE)
|
||||
return false;
|
||||
|
||||
pubkey = strbuf.base;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ip address
|
||||
if(llarp_buffer_eq(key, "i"))
|
||||
{
|
||||
if(!bencode_read_string(buf, &strbuf))
|
||||
return false;
|
||||
|
||||
if(strbuf.sz >= sizeof(tmp))
|
||||
return false;
|
||||
|
||||
memcpy(tmp, strbuf.base, strbuf.sz);
|
||||
tmp[strbuf.sz] = 0;
|
||||
return inet_pton(AF_INET6, tmp, &ip.s6_addr[0]) == 1;
|
||||
}
|
||||
|
||||
// port
|
||||
if(llarp_buffer_eq(key, "p"))
|
||||
{
|
||||
if(!bencode_read_integer(buf, &i))
|
||||
return false;
|
||||
|
||||
if(i > 65536 || i <= 0)
|
||||
return false;
|
||||
|
||||
port = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
// version
|
||||
if(llarp_buffer_eq(key, "v"))
|
||||
{
|
||||
if(!bencode_read_integer(buf, &i))
|
||||
return false;
|
||||
return i == LLARP_PROTO_VERSION;
|
||||
}
|
||||
|
||||
// bad key
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
AddressInfo::BEncode(llarp_buffer_t *buff) const
|
||||
{
|
||||
char ipbuff[128] = {0};
|
||||
const char *ipstr;
|
||||
if(!bencode_start_dict(buff))
|
||||
return false;
|
||||
/* rank */
|
||||
if(!bencode_write_bytestring(buff, "c", 1))
|
||||
return false;
|
||||
if(!bencode_write_uint64(buff, rank))
|
||||
return false;
|
||||
/* dialect */
|
||||
if(!bencode_write_bytestring(buff, "d", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, dialect.c_str(), dialect.size()))
|
||||
return false;
|
||||
/* encryption key */
|
||||
if(!bencode_write_bytestring(buff, "e", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, pubkey, PUBKEYSIZE))
|
||||
return false;
|
||||
/** ip */
|
||||
ipstr = inet_ntop(AF_INET6, &ip, ipbuff, sizeof(ipbuff));
|
||||
if(!ipstr)
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, "i", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, ipstr, strnlen(ipstr, sizeof(ipbuff))))
|
||||
return false;
|
||||
/** port */
|
||||
if(!bencode_write_bytestring(buff, "p", 1))
|
||||
return false;
|
||||
if(!bencode_write_uint64(buff, port))
|
||||
return false;
|
||||
|
||||
if(strbuf.sz >= sizeof(tmp))
|
||||
/** version */
|
||||
if(!bencode_write_version_entry(buff))
|
||||
return false;
|
||||
|
||||
memcpy(tmp, strbuf.base, strbuf.sz);
|
||||
tmp[strbuf.sz] = 0;
|
||||
return inet_pton(AF_INET6, tmp, &ai->ip.s6_addr[0]) == 1;
|
||||
/** end */
|
||||
return bencode_end(buff);
|
||||
}
|
||||
|
||||
// port
|
||||
if(llarp_buffer_eq(*key, "p"))
|
||||
{
|
||||
if(!bencode_read_integer(r->buffer, &i))
|
||||
return false;
|
||||
|
||||
if(i > 65536 || i <= 0)
|
||||
return false;
|
||||
|
||||
ai->port = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
// version
|
||||
if(llarp_buffer_eq(*key, "v"))
|
||||
{
|
||||
if(!bencode_read_integer(r->buffer, &i))
|
||||
return false;
|
||||
return i == LLARP_PROTO_VERSION;
|
||||
}
|
||||
|
||||
// bad key
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
llarp_ai_list_bdecode_item(struct list_reader *r, bool more)
|
||||
{
|
||||
if(!more)
|
||||
return true;
|
||||
llarp_ai_list *l = static_cast< llarp_ai_list * >(r->user);
|
||||
llarp_ai ai;
|
||||
|
||||
if(!llarp_ai_bdecode(&ai, r->buffer))
|
||||
return false;
|
||||
|
||||
llarp_ai_list_pushback(l, &ai);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
llarp_ai_list_iter_bencode(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
|
||||
{
|
||||
return llarp_ai_bencode(ai, static_cast< llarp_buffer_t * >(iter->user));
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
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};
|
||||
#endif
|
||||
return bencode_read_dict(buff, &reader);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_ai_bencode(struct llarp_ai *ai, llarp_buffer_t *buff)
|
||||
{
|
||||
char ipbuff[128] = {0};
|
||||
const char *ipstr;
|
||||
if(!bencode_start_dict(buff))
|
||||
return false;
|
||||
/* rank */
|
||||
if(!bencode_write_bytestring(buff, "c", 1))
|
||||
return false;
|
||||
if(!bencode_write_uint64(buff, ai->rank))
|
||||
return false;
|
||||
/* dialect */
|
||||
if(!bencode_write_bytestring(buff, "d", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, ai->dialect,
|
||||
strnlen(ai->dialect, sizeof(ai->dialect))))
|
||||
return false;
|
||||
/* encryption key */
|
||||
if(!bencode_write_bytestring(buff, "e", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, ai->enc_key, PUBKEYSIZE))
|
||||
return false;
|
||||
/** ip */
|
||||
ipstr = inet_ntop(AF_INET6, &ai->ip, ipbuff, sizeof(ipbuff));
|
||||
if(!ipstr)
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, "i", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, ipstr, strnlen(ipstr, sizeof(ipbuff))))
|
||||
return false;
|
||||
/** port */
|
||||
if(!bencode_write_bytestring(buff, "p", 1))
|
||||
return false;
|
||||
if(!bencode_write_uint64(buff, ai->port))
|
||||
return false;
|
||||
|
||||
/** version */
|
||||
if(!bencode_write_version_entry(buff))
|
||||
return false;
|
||||
/** end */
|
||||
return bencode_end(buff);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff)
|
||||
{
|
||||
if(!bencode_start_list(buff))
|
||||
return false;
|
||||
#ifndef _MSC_VER
|
||||
struct llarp_ai_list_iter ai_itr = {
|
||||
.user = buff, .list = nullptr, .visit = &llarp_ai_list_iter_bencode};
|
||||
#else
|
||||
struct llarp_ai_list_iter ai_itr = {buff, nullptr,
|
||||
&llarp_ai_list_iter_bencode};
|
||||
#endif
|
||||
llarp_ai_list_iterate(l, &ai_itr);
|
||||
return bencode_end(buff);
|
||||
}
|
||||
|
||||
struct llarp_ai_list *
|
||||
llarp_ai_list_new()
|
||||
{
|
||||
return new llarp_ai_list;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_ai_list_free(struct llarp_ai_list *l)
|
||||
{
|
||||
if(l)
|
||||
{
|
||||
l->list.clear();
|
||||
delete l;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
llarp_ai_copy(struct llarp_ai *dst, struct llarp_ai *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(struct llarp_ai));
|
||||
}
|
||||
|
||||
void
|
||||
llarp_ai_list_copy(struct llarp_ai_list *dst, struct llarp_ai_list *src)
|
||||
{
|
||||
dst->list.clear();
|
||||
for(auto &itr : src->list)
|
||||
dst->list.emplace_back(itr);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_ai_list_pushback(struct llarp_ai_list *l, struct llarp_ai *ai)
|
||||
{
|
||||
l->list.push_back(*ai);
|
||||
}
|
||||
|
||||
size_t
|
||||
llarp_ai_list_size(struct llarp_ai_list *l)
|
||||
{
|
||||
if(l)
|
||||
{
|
||||
return l->list.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_ai_list_iterate(struct llarp_ai_list *l, struct llarp_ai_list_iter *itr)
|
||||
{
|
||||
itr->list = l;
|
||||
for(auto &ai : l->list)
|
||||
if(!itr->visit(itr, &ai))
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_ai_list_index(struct llarp_ai_list *l, ssize_t idx, struct llarp_ai *dst)
|
||||
{
|
||||
// TODO: implement negative indexes
|
||||
if(idx < 0)
|
||||
return false;
|
||||
|
||||
size_t i = idx;
|
||||
|
||||
if(l->list.size() > i)
|
||||
{
|
||||
llarp_ai_copy(dst, &l->list[i]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
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};
|
||||
#endif
|
||||
return bencode_read_list(buff, &r);
|
||||
}
|
||||
} // namespace llarp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <llarp/bencode.h>
|
||||
#include "logger.hpp"
|
||||
#include <llarp/logger.hpp>
|
||||
|
||||
bool
|
||||
bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz)
|
||||
|
@ -114,10 +114,14 @@ bencode_read_dict(llarp_buffer_t* buff, struct dict_reader* r)
|
|||
return false;
|
||||
}
|
||||
|
||||
if(*r->buffer->cur != 'e') // make sure we're at dictionary end
|
||||
if(*r->buffer->cur != 'e')
|
||||
{
|
||||
llarp::LogWarn("reading dict not ending on 'e'");
|
||||
// make sure we're at dictionary end
|
||||
return false;
|
||||
}
|
||||
r->buffer->cur++;
|
||||
return r->on_key(r, 0);
|
||||
return r->on_key(r, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef ssize_t
|
||||
#define ssize_t long
|
||||
#endif
|
||||
|
||||
size_t
|
||||
llarp_buffer_size_left(llarp_buffer_t buff)
|
||||
{
|
||||
|
@ -100,6 +101,7 @@ llarp_buffer_put_uint32(llarp_buffer_t* buf, uint32_t i)
|
|||
buf->cur += sizeof(uint32_t);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_buffer_read_uint16(llarp_buffer_t* buf, uint16_t* i)
|
||||
{
|
||||
|
@ -110,6 +112,16 @@ llarp_buffer_read_uint16(llarp_buffer_t* buf, uint16_t* i)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_buffer_read_uint32(llarp_buffer_t* buf, uint32_t* i)
|
||||
{
|
||||
if(llarp_buffer_size_left(*buf) < sizeof(uint32_t))
|
||||
return false;
|
||||
*i = bufbe32toh(buf->cur);
|
||||
buf->cur += sizeof(uint32_t);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_buffer_put_uint32(llarp_buffer_t* buf, uint32_t* i)
|
||||
{
|
||||
|
@ -118,4 +130,4 @@ llarp_buffer_put_uint32(llarp_buffer_t* buf, uint32_t* i)
|
|||
*i = bufbe32toh(buf->cur);
|
||||
buf->cur += sizeof(uint32_t);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace llarp
|
|||
int
|
||||
Context::LoadDatabase()
|
||||
{
|
||||
llarp_crypto_libsodium_init(&crypto);
|
||||
llarp_crypto_init(&crypto);
|
||||
nodedb = llarp_nodedb_new(&crypto);
|
||||
if(!nodedb_dir[0])
|
||||
{
|
||||
|
@ -131,15 +131,19 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
Context::PutDatabase(struct llarp_rc *rc)
|
||||
Context::PutDatabase(struct llarp::RouterContact *rc)
|
||||
{
|
||||
return llarp_nodedb_put_rc(nodedb, rc);
|
||||
// FIXME
|
||||
//return llarp_nodedb_put_rc(nodedb, rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct llarp_rc *
|
||||
llarp::RouterContact *
|
||||
Context::GetDatabase(const byte_t *pk)
|
||||
{
|
||||
return llarp_nodedb_get_rc(nodedb, pk);
|
||||
// FIXME
|
||||
//return llarp_nodedb_get_rc(nodedb, pk);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -349,96 +353,6 @@ extern "C"
|
|||
llarp_logic_stop_timer(ptr->ctx->router->logic);
|
||||
}
|
||||
|
||||
int
|
||||
llarp_main_loadDatabase(struct llarp_main *ptr)
|
||||
{
|
||||
return ptr->ctx->LoadDatabase();
|
||||
}
|
||||
|
||||
int
|
||||
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i)
|
||||
{
|
||||
return ptr->ctx->IterateDatabase(i);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc)
|
||||
{
|
||||
return ptr->ctx->PutDatabase(rc);
|
||||
}
|
||||
|
||||
struct llarp_rc *
|
||||
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_main_queryDHT_RC(struct llarp_main *ptr,
|
||||
struct llarp_router_lookup_job *job)
|
||||
|
@ -461,6 +375,100 @@ extern "C"
|
|||
delete ptr;
|
||||
}
|
||||
|
||||
int
|
||||
llarp_main_loadDatabase(struct llarp_main *ptr)
|
||||
{
|
||||
return ptr->ctx->LoadDatabase();
|
||||
}
|
||||
|
||||
int
|
||||
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i)
|
||||
{
|
||||
return ptr->ctx->IterateDatabase(i);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_main_putDatabase(struct llarp_main *ptr, llarp::RouterContact *rc)
|
||||
{
|
||||
return ptr->ctx->PutDatabase(rc);
|
||||
}
|
||||
|
||||
llarp::RouterContact *
|
||||
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk)
|
||||
{
|
||||
return ptr->ctx->GetDatabase(pk);
|
||||
}
|
||||
|
||||
llarp::RouterContact *
|
||||
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::RouterContact *rc = new llarp::RouterContact;
|
||||
//llarp_rc_new(rc);
|
||||
llarp::LogInfo("FIXME: Loading ", ptr->ctx->conatctFile);
|
||||
// FIXME
|
||||
/*
|
||||
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::Info("checkOnline - check ", left);
|
||||
if(left)
|
||||
return;
|
||||
struct check_online_request *request =
|
||||
static_cast< struct check_online_request * >(u);
|
||||
// llarp::Debug("checkOnline - running");
|
||||
// llarp::Info("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::Info("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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
llarp_main_queryDHT(struct check_online_request *request)
|
||||
{
|
||||
// llarp::Info("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);
|
||||
}
|
||||
|
||||
const char *
|
||||
handleBaseCmdLineArgs(int argc, char *argv[])
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <llarp/crypto_async.h>
|
||||
#include <llarp/mem.h>
|
||||
#include <llarp/router_contact.h>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <string.h>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
|
@ -17,22 +17,6 @@ struct llarp_async_iwp
|
|||
|
||||
namespace iwp
|
||||
{
|
||||
void
|
||||
inform_keygen(void *user)
|
||||
{
|
||||
iwp_async_keygen *keygen = static_cast< iwp_async_keygen * >(user);
|
||||
keygen->hook(keygen);
|
||||
}
|
||||
|
||||
void
|
||||
keygen(void *user)
|
||||
{
|
||||
iwp_async_keygen *keygen = static_cast< iwp_async_keygen * >(user);
|
||||
keygen->iwp->crypto->encryption_keygen(keygen->keybuf);
|
||||
keygen->hook(keygen);
|
||||
// llarp_logic_queue_job(keygen->iwp->logic, job);
|
||||
}
|
||||
|
||||
void
|
||||
inform_intro(void *user)
|
||||
{
|
||||
|
@ -67,7 +51,7 @@ namespace iwp
|
|||
|
||||
llarp::SymmNonce n;
|
||||
// copy nonce
|
||||
memcpy(n, intro->nonce, 24);
|
||||
memcpy(n, intro->nonce, 32); // was 24 bytes
|
||||
char ftmpN[68] = {0};
|
||||
const char *hexN =
|
||||
llarp::HexEncode< llarp::SymmNonce, decltype(ftmpN) >(n, ftmpN);
|
||||
|
@ -85,6 +69,9 @@ namespace iwp
|
|||
llarp::HexEncode< llarp::ShortHash, decltype(ftmpEk) >(e_k, ftmpEk);
|
||||
llarp::LogDebug("gen_intro e_k ", hexEk, " used ", strlen(hexEk));
|
||||
|
||||
// put nonce
|
||||
memcpy(intro->buf + 32, intro->nonce, 32);
|
||||
|
||||
// e = SE(a.k, e_k, n[0:24])
|
||||
memcpy(intro->buf + 64, llarp::seckey_topublic(intro->secretkey), 32);
|
||||
|
||||
|
@ -145,7 +132,10 @@ namespace iwp
|
|||
buf.base = intro->remote_pubkey;
|
||||
buf.cur = buf.base;
|
||||
buf.sz = 32;
|
||||
memcpy(intro->remote_pubkey, intro->buf + 64, 32);
|
||||
|
||||
// was using remote_pubkey directly (use buffer wrapper? directly?)
|
||||
//memcpy(intro->remote_pubkey, intro->buf + 64, 32);
|
||||
memcpy(buf.base, intro->buf + 64, 32);
|
||||
|
||||
crypto->xchacha20(buf, e_K, intro->nonce);
|
||||
llarp::LogInfo("handshake from ", llarp::RouterID(intro->remote_pubkey));
|
||||
|
@ -174,6 +164,7 @@ namespace iwp
|
|||
{
|
||||
llarp::LogWarn("intro HMAC failure");
|
||||
// hmac fail
|
||||
delete[] intro->buf;
|
||||
intro->buf = nullptr;
|
||||
}
|
||||
// inform result
|
||||
|
@ -197,13 +188,13 @@ namespace iwp
|
|||
llarp::ShortHash digest;
|
||||
llarp::SharedSecret sharedkey;
|
||||
|
||||
auto hmac = introack->buf;
|
||||
auto body = introack->buf + 32;
|
||||
auto pubkey = introack->remote_pubkey;
|
||||
auto secretkey = introack->secretkey;
|
||||
auto nonce = introack->buf + 32;
|
||||
auto token = introack->buf + 64;
|
||||
size_t bodysz = introack->sz - 32;
|
||||
auto hmac = introack->buf;
|
||||
auto body = introack->buf + 32;
|
||||
const auto pubkey = introack->remote_pubkey;
|
||||
auto secretkey = introack->secretkey;
|
||||
auto nonce = introack->buf + 32;
|
||||
auto token = introack->buf + 64;
|
||||
size_t bodysz = introack->sz - 32;
|
||||
llarp_buffer_t buf;
|
||||
buf.base = body;
|
||||
buf.cur = body;
|
||||
|
@ -238,10 +229,10 @@ namespace iwp
|
|||
{
|
||||
iwp_async_introack *introack = static_cast< iwp_async_introack * >(user);
|
||||
llarp::SharedSecret sharedkey;
|
||||
auto crypto = introack->iwp->crypto;
|
||||
auto pubkey = introack->remote_pubkey;
|
||||
auto secretkey = introack->secretkey;
|
||||
auto nonce = introack->nonce;
|
||||
auto crypto = introack->iwp->crypto;
|
||||
const auto pubkey = introack->remote_pubkey;
|
||||
auto secretkey = introack->secretkey;
|
||||
auto nonce = introack->nonce;
|
||||
// S = TKE(a.k, b.k, n)
|
||||
crypto->transport_dh_server(sharedkey, pubkey, secretkey, nonce);
|
||||
|
||||
|
@ -284,11 +275,11 @@ namespace iwp
|
|||
auto encrypt = crypto->xchacha20;
|
||||
|
||||
// auto logic = session->iwp->logic;
|
||||
auto a_sK = session->secretkey;
|
||||
auto b_K = session->remote_pubkey;
|
||||
auto N = session->nonce;
|
||||
auto token = session->token;
|
||||
auto K = session->sessionkey;
|
||||
auto a_sK = session->secretkey;
|
||||
const auto b_K = session->remote_pubkey;
|
||||
auto N = session->nonce;
|
||||
auto token = session->token;
|
||||
auto K = session->sessionkey;
|
||||
|
||||
llarp::SharedSecret e_K;
|
||||
llarp::ShortHash T;
|
||||
|
@ -317,7 +308,7 @@ namespace iwp
|
|||
buf.sz = session->sz - 32;
|
||||
hmac(session->buf, buf, e_K);
|
||||
// session->hook(session);
|
||||
llarp_logic_queue_job(logic, {user, &inform_session_start});
|
||||
llarp_logic_queue_job(logic, {session, &inform_session_start});
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -386,7 +377,7 @@ namespace iwp
|
|||
else // hmac fail
|
||||
session->buf = nullptr;
|
||||
// session->hook(session);
|
||||
llarp_logic_queue_job(logic, {user, &inform_session_start});
|
||||
llarp_logic_queue_job(logic, {session, &inform_session_start});
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -417,14 +408,6 @@ namespace iwp
|
|||
}
|
||||
} // namespace iwp
|
||||
|
||||
void
|
||||
iwp_call_async_keygen(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_keygen *keygen)
|
||||
{
|
||||
keygen->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {keygen, &iwp::keygen});
|
||||
}
|
||||
|
||||
bool
|
||||
iwp_decrypt_frame(struct iwp_async_frame *frame)
|
||||
{
|
||||
|
|
|
@ -193,7 +193,7 @@ namespace llarp
|
|||
} // namespace llarp
|
||||
|
||||
void
|
||||
llarp_crypto_libsodium_init(struct llarp_crypto *c)
|
||||
llarp_crypto_init(struct llarp_crypto *c)
|
||||
{
|
||||
assert(sodium_init() != -1);
|
||||
char *avx2 = getenv("AVX2_FORCE_DISABLE");
|
||||
|
@ -229,4 +229,4 @@ llarp_randint()
|
|||
uint64_t i;
|
||||
randombytes((byte_t *)&i, sizeof(i));
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,6 @@ llarp_dht_context_free(struct llarp_dht_context *ctx)
|
|||
delete ctx;
|
||||
}
|
||||
|
||||
void
|
||||
__llarp_dht_put_peer(struct llarp_dht_context *ctx, struct llarp_rc *rc)
|
||||
|
||||
{
|
||||
llarp::dht::RCNode n(rc);
|
||||
llarp::LogDebug("Adding ", n.ID, " to DHT");
|
||||
ctx->impl.nodes->PutNode(n);
|
||||
}
|
||||
|
||||
void
|
||||
__llarp_dht_remove_peer(struct llarp_dht_context *ctx, const byte_t *id)
|
||||
{
|
||||
|
@ -45,7 +36,7 @@ llarp_dht_allow_transit(llarp_dht_context *ctx)
|
|||
void
|
||||
llarp_dht_context_start(struct llarp_dht_context *ctx, const byte_t *key)
|
||||
{
|
||||
ctx->impl.Init(key, ctx->parent);
|
||||
ctx->impl.Init(key, ctx->parent, 20000);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -54,8 +45,11 @@ llarp_dht_lookup_router(struct llarp_dht_context *ctx,
|
|||
{
|
||||
job->dht = ctx;
|
||||
job->found = false;
|
||||
// TODO: check for reuse
|
||||
llarp_rc_clear(&job->result);
|
||||
job->result.Clear();
|
||||
//llarp_rc_clear(&job->result);
|
||||
llarp::LogError("implement me llarp_dht_lookup_router");
|
||||
/*
|
||||
llarp_logic_queue_job(ctx->parent->logic,
|
||||
{job, &llarp::dht::Context::queue_router_lookup});
|
||||
*/
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,8 +8,8 @@ namespace llarp
|
|||
struct MessageDecoder
|
||||
{
|
||||
const Key_t &From;
|
||||
std::unique_ptr< IMessage > msg;
|
||||
bool firstKey = true;
|
||||
IMessage *msg = nullptr;
|
||||
bool relayed = false;
|
||||
|
||||
MessageDecoder(const Key_t &from) : From(from)
|
||||
|
@ -37,32 +37,33 @@ namespace llarp
|
|||
return false;
|
||||
llarp::LogInfo("Handle DHT message ", *strbuf.base,
|
||||
" relayed=", dec->relayed);
|
||||
IMessage *msg;
|
||||
switch(*strbuf.base)
|
||||
{
|
||||
case 'F':
|
||||
dec->msg = new FindIntroMessage(dec->From, dec->relayed);
|
||||
msg = new FindIntroMessage(dec->From, dec->relayed);
|
||||
break;
|
||||
case 'R':
|
||||
if(dec->relayed)
|
||||
dec->msg = new RelayedFindRouterMessage(dec->From);
|
||||
msg = new RelayedFindRouterMessage(dec->From);
|
||||
else
|
||||
dec->msg = new FindRouterMessage(dec->From);
|
||||
msg = new FindRouterMessage(dec->From);
|
||||
break;
|
||||
case 'S':
|
||||
dec->msg = new GotRouterMessage(dec->From, dec->relayed);
|
||||
msg = new GotRouterMessage(dec->From, dec->relayed);
|
||||
break;
|
||||
case 'I':
|
||||
dec->msg = new PublishIntroMessage();
|
||||
msg = new PublishIntroMessage();
|
||||
break;
|
||||
case 'G':
|
||||
if(dec->relayed)
|
||||
{
|
||||
dec->msg = new RelayedGotIntroMessage();
|
||||
msg = new RelayedGotIntroMessage();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dec->msg = new GotIntroMessage(dec->From);
|
||||
msg = new GotIntroMessage(dec->From);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -70,6 +71,7 @@ namespace llarp
|
|||
// bad msg type
|
||||
return false;
|
||||
}
|
||||
dec->msg = std::unique_ptr< IMessage >(msg);
|
||||
dec->firstKey = false;
|
||||
return dec->msg != nullptr;
|
||||
}
|
||||
|
@ -78,7 +80,7 @@ namespace llarp
|
|||
}
|
||||
};
|
||||
|
||||
IMessage *
|
||||
std::unique_ptr< IMessage >
|
||||
DecodeMesssage(const Key_t &from, llarp_buffer_t *buf, bool relayed)
|
||||
{
|
||||
MessageDecoder dec(from);
|
||||
|
@ -86,26 +88,20 @@ namespace llarp
|
|||
dict_reader r;
|
||||
r.user = &dec;
|
||||
r.on_key = &MessageDecoder::on_key;
|
||||
if(bencode_read_dict(buf, &r))
|
||||
{
|
||||
return dec.msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dec.msg)
|
||||
delete dec.msg;
|
||||
if(!bencode_read_dict(buf, &r))
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr< IMessage >(std::move(dec.msg));
|
||||
}
|
||||
|
||||
struct ListDecoder
|
||||
{
|
||||
ListDecoder(const Key_t &from, std::vector< IMessage * > &list)
|
||||
ListDecoder(const Key_t &from,
|
||||
std::vector< std::unique_ptr< IMessage > > &list)
|
||||
: From(from), l(list){};
|
||||
|
||||
bool relayed = false;
|
||||
const Key_t &From;
|
||||
std::vector< IMessage * > &l;
|
||||
std::vector< std::unique_ptr< IMessage > > &l;
|
||||
|
||||
static bool
|
||||
on_item(list_reader *r, bool has)
|
||||
|
@ -116,7 +112,7 @@ namespace llarp
|
|||
auto msg = DecodeMesssage(dec->From, r->buffer, dec->relayed);
|
||||
if(msg)
|
||||
{
|
||||
dec->l.push_back(msg);
|
||||
dec->l.emplace_back(std::move(msg));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -125,8 +121,9 @@ namespace llarp
|
|||
};
|
||||
|
||||
bool
|
||||
DecodeMesssageList(const Key_t &from, llarp_buffer_t *buf,
|
||||
std::vector< IMessage * > &list, bool relayed)
|
||||
DecodeMesssageList(Key_t from, llarp_buffer_t *buf,
|
||||
std::vector< std::unique_ptr< IMessage > > &list,
|
||||
bool relayed)
|
||||
{
|
||||
ListDecoder dec(from, list);
|
||||
dec.relayed = relayed;
|
||||
|
@ -136,4 +133,4 @@ namespace llarp
|
|||
return bencode_read_list(buf, &r);
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
} // namespace llarp
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue