├── bench ├── README.md ├── xkad_bench1 │ ├── clean.sh │ ├── online │ │ ├── ssh.sh │ │ ├── ansible_stop.sh │ │ ├── ansible_uptime.sh │ │ ├── scp.sh │ │ ├── ansible_deploy.sh │ │ ├── ansible_run2.sh │ │ ├── ansible_show.sh │ │ ├── deploy.sh │ │ ├── run1.sh │ │ ├── run2fg.sh │ │ ├── ansible_collect.sh │ │ ├── run2.sh │ │ ├── bridge_deploy.sh │ │ ├── node.pem │ │ └── bridge.pem │ ├── stop.sh │ ├── show.sh │ ├── run2fg.sh │ ├── run1.sh │ ├── deploy.sh │ └── run2.sh ├── CMakeLists.txt ├── node.proto ├── util.h ├── main.cc └── util.cc ├── demo ├── conf │ └── demo.conf ├── CMakeLists.txt └── xkaddemo.xcodeproj │ ├── xcuserdata │ └── imac.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist │ └── xcshareddata │ └── xcschemes │ └── xkaddemo.xcscheme ├── proto ├── ledger.proto └── kadmlia.proto ├── tests ├── CMakeLists.txt ├── lcov.sh ├── test_routing_table_heartbeat.cc ├── test_heartbeat_state.cc ├── test_node_info.cc ├── test_client_node_manager.cc ├── test_dynamic_xip_manager.cc ├── test_nat_handshake_manager.cc ├── test_main.cc ├── test_node_detection_manager.cc ├── test_bootstrap_cache.cc ├── node_mgr.h ├── test_local_node_info.cc ├── test_bootstrap_cache_helper.cc ├── test_kad_message_handler.cc ├── test_routing_table2.cc ├── test_nat_manager.cc ├── test_callback_manager.cc ├── node_mgr.cc └── test_routing_utils.cc ├── xkad.xcodeproj └── xcuserdata │ └── imac.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── CMakeLists.txt ├── nat_detect ├── nat_defines.h ├── nat_detect │ └── nat_defines.h ├── nat_manager_intf.h ├── nat_handshake_manager.h └── nat_manager.h ├── gossip ├── rumor_filter.h ├── rumor_def.h ├── rumor_message_manager.h └── rumor_handler.h ├── src ├── nodeid_utils.cc ├── rumor_filter.cc ├── heartbeat_manager.cc ├── rumor_message_manager.cc ├── client_node_manager.cc ├── dynamic_xip_manager.cc ├── node_info.cc ├── local_node_info.cc ├── heartbeat_state.cc ├── bootstrap_cache.cc ├── callback_manager.cc ├── nat_handshake_manager.cc ├── node_detection_manager.cc ├── routing_utils.cc ├── rumor_handler.cc └── kad_message_handler.cc ├── routing_table ├── nodeid_utils.h ├── heartbeat_state.h ├── heartbeat_manager.h ├── dynamic_xip_manager.h ├── client_node_manager.h ├── node_detection_manager.h ├── routing_table_heartbeat.h ├── nat_detect_manager.h ├── node_info.h ├── bootstrap_cache.h ├── callback_manager.h ├── kad_message_handler.h ├── bootstrap_cache_helper.h ├── local_node_info.h └── routing_utils.h └── README.md /bench/README.md: -------------------------------------------------------------------------------- 1 | # brief 2 | single routing table 3 | with command line 4 | -------------------------------------------------------------------------------- /bench/xkad_bench1/clean.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | rm -rf log 4 | rm -rf core.* 5 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/ssh.sh: -------------------------------------------------------------------------------- 1 | ssh -p 1022 -i /root/blueshi/xkad_bench1/online/node.pem root@$1 2 | -------------------------------------------------------------------------------- /demo/conf/demo.conf: -------------------------------------------------------------------------------- 1 | [node] 2 | local_ip=127.0.0.1 3 | local_port=8900 4 | first_node=true 5 | public_endpoints=127.0.0.1:8900 6 | country=US 7 | -------------------------------------------------------------------------------- /bench/xkad_bench1/stop.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # kill -9 `ps -ef | grep xkad_bench | awk '{print $2}'` 4 | killall xkad_bench || echo "no such processes" 5 | -------------------------------------------------------------------------------- /bench/xkad_bench1/show.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | ps -ef | grep xkad_bench | grep -v grep | grep -v 'show.sh' 4 | /usr/sbin/lsof -nPi | grep xkad_ben 5 | uptime 6 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/ansible_stop.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # stop 4 | ansible -i /root/blueshi/blue_hosts m_bg -m shell -a "cd /root/blueshi/xkad_bench1 && sh stop.sh" 5 | -------------------------------------------------------------------------------- /bench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | aux_source_directory(./ SRC) 3 | add_executable(xkad_bench ${SRC}) 4 | add_dependencies(xkad_bench xkad) 5 | target_link_libraries(xkad_bench xkad) 6 | -------------------------------------------------------------------------------- /bench/xkad_bench1/run2fg.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | rm -rf log2 4 | mkdir -p log2 5 | 6 | # foreground 7 | ./xkad_bench -a 127.0.0.1 -l 8822 -L log2/8822.log -i 1 -p 127.0.0.1:8833 8 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/ansible_uptime.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # collect fg 4 | ansible -i /root/blueshi/blue_hosts m_fg -m shell -a "uptime" 5 | 6 | # collect bg 7 | ansible -i /root/blueshi/blue_hosts m_bg -m shell -a "uptime" 8 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/scp.sh: -------------------------------------------------------------------------------- 1 | # scp -P 1022 -i node.pem topuser@$1:/root/blueshi/xkad_bench1/log.tgz ~/pub/xudp_core/$1_log.tgz 2 | scp -P 1022 -i xkad_bench1/online/node.pem topuser@$1:/root/blueshi/xkad_bench1/log.tgz /root/blueshi/log_collect/$1_log.tgz 3 | -------------------------------------------------------------------------------- /proto/ledger.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package top.kadmlia.pb; 3 | 4 | message PbBootstrapEndpoint { 5 | string ip = 1; 6 | uint32 port = 2; 7 | } 8 | 9 | message PbBootstrapCache { 10 | repeated PbBootstrapEndpoint endpoints = 1; 11 | } 12 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/ansible_deploy.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # rsync 4 | ansible -i /root/blueshi/blue_hosts m_fg -m synchronize -a "src=/root/blueshi dest=/root/" 5 | 6 | # rsync 7 | ansible -i /root/blueshi/blue_hosts m_bg -m synchronize -a "src=/root/blueshi dest=/root/" 8 | -------------------------------------------------------------------------------- /bench/xkad_bench1/run1.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | rm -rf log1 4 | mkdir -p log1 5 | 6 | ./xkad_bench -a 127.0.0.1 -l 8833 -L log1/first_node.log 7 | # ./xkad_bench -a 192.168.50.211 -l 8833 -L log1/first_node.log 8 | # ./xkad_bench -a 192.168.50.242 -l 8833 -L log1/first_node.log 9 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/ansible_run2.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # # stop 4 | # ansible -i /root/blueshi/blue_hosts m_bg -m shell -a "cd /root/blueshi/xkad_bench1 && sh stop.sh" 5 | 6 | # run 7 | ansible -i /root/blueshi/blue_hosts m_bg -m shell -a "cd /root/blueshi/xkad_bench1 && sh online/run2.sh" 8 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/ansible_show.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # show 4 | ansible -i /root/blueshi/blue_hosts m_bg -m shell -a "cd /root/blueshi/xkad_bench1 && sh show.sh" 5 | 6 | # grep core 7 | # ansible -i /root/blueshi/blue_hosts m_bg -m shell -a "cd /root/blueshi/xkad_bench1 && ls -l | grep core" 8 | -------------------------------------------------------------------------------- /bench/xkad_bench1/deploy.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | target=src/xtopcom/xkad/bench/xkad_bench1 4 | 5 | # copy xkad_bench 6 | rsync -avz cbuild/bin/Linux/xkad_bench $target/ 7 | # rsync -avz cbuild/bin/Darwin/xkad_bench $target/ 8 | # strip $target/xkad_bench 9 | 10 | # copy bench1 11 | rsync -avz $target ~/run/ 12 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/deploy.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | target=src/xtopcom/xkad/bench/xkad_bench1 4 | 5 | # copy xkad_bench 6 | rsync -avz cbuild/bin/Linux/xkad_bench $target/ 7 | # rsync -avz cbuild/bin/Darwin/xkad_bench $target/ 8 | # strip $target/xkad_bench 9 | 10 | # copy bench1 11 | rsync -avz $target ~/run/ 12 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/run1.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | rm -rf log 4 | rm -rf core.* 5 | 6 | mkdir -p log 7 | ulimit -c unlimited 8 | 9 | IP=`/usr/sbin/ip a | grep 'inet ' | grep -v 'inet 127.' | grep -v 'inet 10.' | grep -v 'inet 172.16.' | awk '{print $ 2}' | awk -F/ '{print $1}'` 10 | echo ${IP} 11 | 12 | ./xkad_bench -a ${IP} -l 11000 -L log/first_node.log 13 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/run2fg.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | rm -rf log 4 | rm -rf core.* 5 | 6 | mkdir -p log 7 | ulimit -c unlimited 8 | 9 | IP=`/usr/sbin/ip a | grep 'inet ' | grep -v 'inet 127.' | grep -v 'inet 10.' | grep -v 'inet 172.16.' | awk '{print $ 2}' | awk -F/ '{print $1}'` 10 | echo ${IP} 11 | 12 | ./xkad_bench -a ${IP} -l 10900 -L log/run2fg.log -i 1 -p 157.245.138.194:11000 13 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 3 | aux_source_directory(./ xkad_test_dir) 4 | # set(xkad_test_dir ./test_routing_table3.cc ./test_main.cc) 5 | add_executable(xkad_test ${xkad_test_dir}) 6 | add_dependencies(xkad_test xkad) 7 | target_link_libraries(xkad_test xkad gtest gmock) 8 | 9 | if(XENABLE_CODE_COVERAGE) 10 | target_link_libraries(xkad_test gcov) 11 | endif() 12 | endif() 13 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/ansible_collect.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | mkdir -p /root/blueshi_log_collect/x 4 | 5 | # collect fg 6 | ansible -i /root/blueshi/blue_hosts m_fg -m synchronize -a "src=/root/blueshi/xkad_bench1 dest=/root/blueshi_log_collect/x/{{inventory_hostname}} mode=pull" 7 | 8 | # collect bg 9 | ansible -i /root/blueshi/blue_hosts m_bg -m synchronize -a "src=/root/blueshi/xkad_bench1 dest=/root/blueshi_log_collect/x/{{inventory_hostname}} mode=pull" 10 | -------------------------------------------------------------------------------- /xkad.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | xkad.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 5 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | 3 | include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/proto) 4 | 5 | aux_source_directory(./src xkad_src) 6 | aux_source_directory(./proto xkad_src) 7 | add_library(xkad ${xkad_src}) 8 | 9 | add_dependencies(xkad xpbase xtransport xledger) 10 | target_link_libraries(xkad xpbase xtransport xledger protobuf) 11 | 12 | if(XENABLE_TESTS) 13 | add_subdirectory(tests) 14 | add_subdirectory(bench) 15 | endif() 16 | -------------------------------------------------------------------------------- /demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | remove_definitions( 2 | -DGOSSIP_WITH_WROUTER 3 | ) 4 | 5 | aux_source_directory(./ xkad_demo_dir) 6 | add_executable(xkad_demo ${xkad_demo_dir}) 7 | 8 | add_dependencies(xkad_demo xgossip xkad xxbase) 9 | 10 | target_link_libraries(xkad_demo 11 | xgossip 12 | xkad 13 | xtransport 14 | xpbase 15 | xcrypto 16 | xutility 17 | xxbase 18 | xledger 19 | protobuf 20 | -lgtest 21 | -lgmock 22 | -lpthread -ldl 23 | -lrt 24 | ) 25 | 26 | -------------------------------------------------------------------------------- /nat_detect/nat_defines.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | namespace top { 8 | namespace kadmlia { 9 | 10 | enum NatType { 11 | kNatTypeUnknown = 0, 12 | kNatTypePublic = 1, 13 | kNatTypeConeNormal = 2, 14 | kNatTypeConeAbnormal = 3, 15 | }; 16 | 17 | } // namespace kadmlia 18 | } // namespace top 19 | -------------------------------------------------------------------------------- /nat_detect/nat_detect/nat_defines.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | namespace top { 8 | namespace kadmlia { 9 | 10 | enum NatType { 11 | kNatTypeUnknown = 0, 12 | kNatTypePublic = 1, 13 | kNatTypeConeNormal = 2, 14 | kNatTypeConeAbnormal = 3, 15 | }; 16 | 17 | } // namespace kadmlia 18 | } // namespace top 19 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/run2.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | killall -w xkad_bench || echo "no such process" 4 | rm -rf log 5 | rm -rf core.* 6 | 7 | mkdir -p log 8 | ulimit -c unlimited 9 | 10 | IP=`/usr/sbin/ip a | grep 'inet ' | grep -v 'inet 127.' | grep -v 'inet 10.' | grep -v 'inet 172.16.' | awk '{print $ 2}' | awk -F/ '{print $1}'` 11 | echo ${IP} 12 | 13 | for ((i=0;i<25;i++)); do 14 | echo "launching ${i} ..." 15 | PORT=$((10000+$i)) 16 | nohup ./xkad_bench -a ${IP} -l $PORT -L log/${i}.log -i 1 -p 157.245.138.194:11000 -g 0 >/dev/null 2>&1 -D 0 & 17 | done 18 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/bridge_deploy.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | target=src/xtopcom/xkad/bench/xkad_bench1 4 | 5 | # copy xkad_bench 6 | rsync -avz cbuild/bin/Linux/xkad_bench $target/ 7 | # rsync -avz cbuild/bin/Darwin/xkad_bench $target/ 8 | # strip $target/xkad_bench 9 | 10 | # copy bench1 11 | # rsync -avz $target ~/run/ 12 | 13 | ips=( 14 | "142.93.88.86" 15 | ) 16 | 17 | for ip in ${ips[@]}; do 18 | echo "===== rsyncing $ip ... =====" 19 | rsync -avz -e "ssh -p 1022 -i src/xtopcom/xkad/bench/xkad_bench1/online/bridge.pem" $target root@$ip:~/blueshi/ 20 | done 21 | -------------------------------------------------------------------------------- /demo/xkaddemo.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | xkaddemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 994ECA8C22B1EBA30035313B 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /gossip/rumor_filter.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | #include "xpbase/base/contain_template.h" 7 | #include "xtransport/proto/transport.pb.h" 8 | #include "xkad/proto/kadmlia.pb.h" 9 | #include "xkad/gossip/rumor_def.h" 10 | 11 | namespace top { 12 | namespace gossip { 13 | 14 | class RumorFilter : 15 | public ContainTemplate< 16 | uint32_t, 17 | kDefaultFilterSize, 18 | kRepeatedValueNum>{ 19 | public: 20 | static RumorFilter* Instance(); 21 | ~RumorFilter() {} 22 | bool FiltMessage( 23 | transport::protobuf::RoutingMessage&); 24 | private: 25 | RumorFilter() {} 26 | }; 27 | 28 | typedef std::shared_ptr RumorFilterPtr; 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/nodeid_utils.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/nodeid_utils.h" 6 | #include "xbase/xhash.h" 7 | 8 | #include 9 | 10 | namespace top { 11 | 12 | namespace kadmlia { 13 | 14 | uint8_t GetWorldCountryID(const std::string& country_code) { 15 | uint32_t hash = base::xhash32_t::digest(country_code); 16 | return (hash & 0xFF000000); 17 | } 18 | 19 | uint32_t GetBusinessID(const std::string& business) { 20 | auto iter = BusinessID.find(business); 21 | if (iter == BusinessID.end()) { 22 | return std::numeric_limits::max(); 23 | } 24 | 25 | return iter->second; 26 | } 27 | 28 | } // namespace kadmlia 29 | 30 | } // namespace top 31 | -------------------------------------------------------------------------------- /gossip/rumor_def.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include "xpbase/base/top_string_util.h" 11 | #include "xkad/routing_table/routing_utils.h" 12 | #include "xkad/routing_table/routing_utils.h" 13 | 14 | namespace top { 15 | 16 | namespace gossip { 17 | 18 | static const int32_t kDefautHopCount = 10; 19 | static const int32_t kDefaultSpreadPeriod = 3 * 1000 * 1000; 20 | static const int32_t kDefaultFilterSize = 3024000u; 21 | static const int32_t kRepeatedValueNum = 1; 22 | 23 | struct RumorIdentity final : public kadmlia::MessageIdentity { 24 | RumorIdentity( 25 | const uint32_t in_message_id, 26 | const std::string& in_node_id) 27 | :kadmlia::MessageIdentity(in_message_id,in_node_id) { 28 | } 29 | ~RumorIdentity() {} 30 | }; 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /routing_table/nodeid_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include "xpbase/base/top_utils.h" 11 | 12 | namespace top { 13 | 14 | namespace kadmlia { 15 | 16 | // 12 bit for business 17 | static const std::map BusinessID = { 18 | { "ROOT", top::kRoot }, 19 | { "CLIENT", top::kClient }, 20 | 21 | { "EDGEXVPN", top::kEdgeXVPN }, 22 | { "EDGEXMESSAGE", top::kEdgeTopMessage }, 23 | { "EDGEXSTORAGE", top::kEdgeTopStorage }, 24 | 25 | { "XVPN", top::kXVPN }, 26 | { "XMESSAGE", top::kTopMessage }, 27 | { "XSTORAGE", top::kTopStorage }, 28 | }; 29 | 30 | // 8 bit for countrycode 31 | uint8_t GetWorldCountryID(const std::string& country_code); 32 | uint32_t GetBusinessID(const std::string& business); 33 | 34 | } // namespace kadmlia 35 | 36 | } // namespace top 37 | -------------------------------------------------------------------------------- /routing_table/heartbeat_state.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | // #pragma once 6 | 7 | // #include 8 | // #include 9 | // #include 10 | // #include "xtransport/proto/transport.pb.h" 11 | // #include "xkad/proto/kadmlia.pb.h" 12 | 13 | // namespace top { 14 | // namespace kadmlia { 15 | 16 | // class HeartbeatState { 17 | // public: 18 | // static HeartbeatState& Instance(); 19 | // virtual void Send(const transport::protobuf::RoutingMessage& message, 20 | // const std::string& peer_ip, uint16_t peer_port) = 0; 21 | // // virtual void Join() = 0; 22 | // }; 23 | 24 | // class HeartbeatStateRecv { 25 | // public: 26 | // static HeartbeatStateRecv& Instance(); 27 | // virtual void Recv(const transport::protobuf::RoutingMessage& message) = 0; 28 | // // virtual void Join() = 0; 29 | // }; 30 | 31 | // } // namespace kadmlia 32 | // } // namespace top 33 | -------------------------------------------------------------------------------- /tests/lcov.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | pids=$(ps -ef | grep SimpleHTTPServer | grep -v grep | awk -F' ' '{print $2}') 4 | echo "pids: $pids" 5 | if [ -n "$pids" ]; then 6 | kill -9 $pids 7 | fi 8 | 9 | parent_path=$(pwd) 10 | 11 | cd cbuild 12 | 13 | bin/Linux/xkad_test 14 | abs_path=`pwd`"/src/xtopcom/xkad/CMakeFiles/xkad.dir/src/" 15 | lcov -d $abs_path -t 'test' -o 'test.info' -b . -c 16 | echo "=========================1" 17 | 18 | lcov --remove test.info \ 19 | '/usr/*' \ 20 | $parent_path'/src/xtopcom/xbase/*' \ 21 | $parent_path'/src/xtopcom/xdepends/*' \ 22 | $parent_path'/src/xtopcom/xpbase/*' \ 23 | $parent_path'/src/xtopcom/xtransport/*' \ 24 | $parent_path'/src/xtopcom/xsecurity/*' \ 25 | $parent_path'/src/xtopcom/xkad/proto/*' \ 26 | -o xkad.info 27 | echo "=========================2" 28 | genhtml -o result xkad.info 29 | echo "=========================3" 30 | cd result 31 | 32 | echo '' 33 | echo '' 34 | echo '' 35 | 36 | echo "visit this link to view code recover: http://0.0.0.0:8000" 37 | echo '' 38 | echo '' 39 | python -m SimpleHTTPServer > /dev/null 2>&1 & 40 | 41 | echo '' 42 | -------------------------------------------------------------------------------- /tests/test_routing_table_heartbeat.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | // #include 6 | 7 | // #include 8 | 9 | // #include 10 | // #include 11 | 12 | // #include "xkad/routing_table/routing_table_heartbeat.h" 13 | // #include "xkad/routing_table/routing_utils.h" 14 | 15 | // namespace top { 16 | 17 | // namespace kadmlia { 18 | 19 | // namespace test { 20 | 21 | // class TestHeartbeat : public testing::Test { 22 | // public: 23 | // static void SetUpTestCase() { 24 | 25 | // } 26 | 27 | // static void TearDownTestCase() { 28 | // } 29 | 30 | // virtual void SetUp() { 31 | 32 | // } 33 | 34 | // virtual void TearDown() { 35 | // } 36 | // }; 37 | 38 | // TEST_F(TestHeartbeat, Start) { 39 | // RoutingTableHeartbeat ht(); 40 | // ht.Start([]{}, []{}); 41 | // ::sleep(2); 42 | // ht.Stop(); 43 | // sleep(2); 44 | // } 45 | 46 | // } // namespace test 47 | 48 | // } // namespace kadmlia 49 | 50 | // } // namespace top 51 | -------------------------------------------------------------------------------- /bench/xkad_bench1/run2.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | rm -rf log2 4 | mkdir -p log2 5 | 6 | # launch second nodes 7 | for ((i=1;i<=400;i++)); do # 288bits 8 | # for ((i=1;i<=600;i++)); do # 40bits 9 | echo "launching ${i} ..." 10 | port=$((10000+i)) 11 | nohup ./xkad_bench -a 127.0.0.1 -l $port -L log2/${i}.log -i 1 -p 127.0.0.1:8833 -g 0 >/dev/null 2>&1 -D 0 & 12 | # nohup ./xkad_bench -a 192.168.1.101 -l 0 -L log2/${i}.log -i 1 -p 192.168.50.211:8833 -g 0 >/dev/null 2>&1 & 13 | # nohup ./xkad_bench -a 192.168.50.211 -l 0 -L log2/${i}.log -i 1 -p 192.168.50.211:8833 -g 0 >/dev/null 2>&1 & 14 | # nohup ./xkad_bench -a 192.168.50.214 -l 0 -L log2/${i}.log -i 1 -p 192.168.50.211:8833 -g 0 >/dev/null 2>&1 & 15 | 16 | # nohup ./xkad_bench -a 192.168.50.211 -l 0 -L log2/${i}.log -i 1 -p 192.168.50.242:8833 -g 0 >/dev/null 2>&1 & 17 | # nohup ./xkad_bench -a 192.168.50.214 -l 0 -L log2/${i}.log -i 1 -p 192.168.50.242:8833 -g 0 >/dev/null 2>&1 & 18 | # nohup ./xkad_bench -a 192.168.50.242 -l 0 -L log2/${i}.log -i 1 -p 192.168.50.242:8833 -g 0 >/dev/null 2>&1 & 19 | 20 | sleep 0.002 21 | done 22 | 23 | # foreground 24 | # ./xkad_bench -a 127.0.0.1 -l 8822 -L log2/1.log -i 1 -p 127.0.0.1:8833 25 | -------------------------------------------------------------------------------- /src/rumor_filter.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/gossip/rumor_filter.h" 6 | 7 | #include "xkad/gossip/rumor_def.h" 8 | #include "xkad/routing_table/routing_utils.h" 9 | #include "xpbase/base/top_log.h" 10 | 11 | namespace top { 12 | namespace gossip { 13 | 14 | RumorFilter* RumorFilter::Instance() { 15 | static RumorFilter ins; 16 | return &ins; 17 | } 18 | 19 | bool RumorFilter::FiltMessage( 20 | transport::protobuf::RoutingMessage& message) { 21 | auto gossip = message.gossip(); 22 | if (!gossip.has_msg_hash()) { 23 | TOP_WARN("filter failed, gossip msg should set msg_hash"); 24 | return true; 25 | } 26 | if (FindData(gossip.msg_hash())) { 27 | TOP_DEBUG("RumorFilter FindData, filter msg"); 28 | return true; 29 | } 30 | if (!AddData(gossip.msg_hash())) { 31 | TOP_WARN("RumorFilter::FiltMessage Success,%d Already Exist. filter msg", 32 | gossip.msg_hash()); 33 | return true; 34 | } 35 | return false; 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /gossip/rumor_message_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #include "xtransport/proto/transport.pb.h" 10 | #include "xkad/proto/kadmlia.pb.h" 11 | #include "xpbase/base/manager_template.h" 12 | #include "xkad/routing_table/node_info.h" 13 | #include "xkad/routing_table/routing_utils.h" 14 | 15 | namespace top { 16 | namespace gossip { 17 | 18 | class RumorMessageManager : public ManagerTemplate { 19 | public: 20 | RumorMessageManager() {} 21 | ~RumorMessageManager() {} 22 | bool AddMessage( 23 | const transport::protobuf::RoutingMessage&); 24 | void RemoveMessage( 25 | int32_t); 26 | bool SearchMessage( 27 | int32_t, 28 | transport::protobuf::RoutingMessage&) const; 29 | void GetAllMessages( 30 | std::vector&); 31 | uint32_t GetMessageCount() const; 32 | }; 33 | 34 | typedef std::shared_ptr RumorMessageManagerSptr; 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/heartbeat_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/heartbeat_manager.h" 6 | #include "xpbase/base/top_log.h" 7 | 8 | namespace top { 9 | namespace kadmlia { 10 | 11 | HeartbeatManagerIntf* HeartbeatManagerIntf::Instance() { 12 | static HeartbeatManager ins; 13 | return &ins; 14 | } 15 | 16 | void HeartbeatManagerIntf::OnHeartbeatCallback(const std::string& ip, uint16_t port) { 17 | HeartbeatManagerIntf::Instance()->OnHeartbeatFailed(ip, port); 18 | } 19 | 20 | // ---------------------------------------------------------------- 21 | void HeartbeatManager::Register(const std::string& name, OfflineCallback cb) { 22 | std::unique_lock lock(mutex_); 23 | vec_cb_.push_back(cb); 24 | TOP_INFO("[ht_cb] register %s", name.c_str()); 25 | } 26 | 27 | void HeartbeatManager::OnHeartbeatFailed(const std::string& ip, uint16_t port) { 28 | TOP_INFO("[ht_cb] %s:%d heartbeat failed", ip.c_str(), (int)port); 29 | std::unique_lock lock(mutex_); 30 | for (auto& cb : vec_cb_) { 31 | cb(ip, port); 32 | } 33 | } 34 | 35 | } // namespace kadmlia 36 | } // namespace top 37 | -------------------------------------------------------------------------------- /routing_table/heartbeat_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace top { 14 | namespace kadmlia { 15 | 16 | using OfflineCallback = std::function; 17 | 18 | class HeartbeatManagerIntf { 19 | public: 20 | static HeartbeatManagerIntf* Instance(); 21 | static void OnHeartbeatCallback(const std::string& ip, uint16_t port); 22 | 23 | virtual ~HeartbeatManagerIntf() {} 24 | virtual void Register(const std::string& name, OfflineCallback cb) = 0; 25 | 26 | private: 27 | virtual void OnHeartbeatFailed(const std::string& ip, uint16_t port) = 0; 28 | }; 29 | 30 | class HeartbeatManager : public HeartbeatManagerIntf { 31 | public: 32 | virtual void Register(const std::string& name, OfflineCallback cb) override; 33 | virtual void OnHeartbeatFailed(const std::string& ip, uint16_t port) override; 34 | 35 | private: 36 | std::mutex mutex_; 37 | std::vector vec_cb_; 38 | }; 39 | 40 | } // namespace kadmlia 41 | } // namespace top 42 | -------------------------------------------------------------------------------- /tests/test_heartbeat_state.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | // #include 6 | 7 | // #include 8 | 9 | // #include 10 | // #include 11 | 12 | // #include "xkad/routing_table/heartbeat_state.h" 13 | // #include "xkad/routing_table/routing_utils.h" 14 | // #include "xtransport/proto/transport.pb.h" 15 | // #include "xwrouter/wrouter_utils/wrouter_utils.h" 16 | 17 | // namespace top { 18 | 19 | // namespace kadmlia { 20 | 21 | // namespace test { 22 | 23 | // class TestHeartbeatState : public testing::Test { 24 | // public: 25 | // static void SetUpTestCase() { 26 | 27 | // } 28 | 29 | // static void TearDownTestCase() { 30 | // } 31 | 32 | // virtual void SetUp() { 33 | 34 | // } 35 | 36 | // virtual void TearDown() { 37 | // } 38 | // }; 39 | 40 | // TEST_F(TestHeartbeatState, HeartbeatState) { 41 | // transport::protobuf::RoutingMessage message; 42 | // message.set_type(kKadHeartbeatRequest); 43 | // HeartbeatState::Instance().Send(message, "1", 2); 44 | // HeartbeatStateRecv::Instance().Recv(message); 45 | // ::sleep(2); 46 | // } 47 | 48 | // } // namespace test 49 | 50 | // } // namespace kadmlia 51 | 52 | // } // namespace top 53 | -------------------------------------------------------------------------------- /routing_table/dynamic_xip_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "xkad/routing_table/routing_utils.h" 14 | 15 | namespace top { 16 | 17 | namespace base { 18 | class XipParser; 19 | }; 20 | 21 | namespace kadmlia { 22 | 23 | struct ClientNodeInfo; 24 | typedef std::shared_ptr ClientNodeInfoPtr; 25 | 26 | class DynamicXipManager { 27 | public: 28 | int AddClientNode(const std::string& dy_xip, ClientNodeInfoPtr node_ptr); 29 | void RemoveClientNode(const std::string& dy_xip); 30 | ClientNodeInfoPtr FindClientNode(const std::string& dy_xip); 31 | std::string DispatchDynamicXip(const base::XipParser& local_xip); 32 | public: 33 | DynamicXipManager(); 34 | ~DynamicXipManager(); 35 | 36 | // key is dynamic xip str 37 | std::map dy_xip_map_; 38 | std::mutex dy_xip_map_mutex_; 39 | std::atomic atom_xip_manager_id_; 40 | 41 | DISALLOW_COPY_AND_ASSIGN(DynamicXipManager); 42 | }; 43 | 44 | typedef std::shared_ptr DynamicXipManagerPtr; 45 | 46 | } // namespace kadmlia 47 | 48 | } // namespace top 49 | -------------------------------------------------------------------------------- /tests/test_node_info.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | #include 7 | #include 8 | #include "xkad/routing_table/node_info.h" 9 | 10 | namespace top { 11 | namespace kadmlia { 12 | namespace test { 13 | 14 | class TestNodeInfo : public testing::Test { 15 | public: 16 | static void SetUpTestCase() { 17 | } 18 | 19 | static void TearDownTestCase() { 20 | } 21 | 22 | virtual void SetUp() { 23 | } 24 | 25 | virtual void TearDown() { 26 | } 27 | }; 28 | 29 | TEST_F(TestNodeInfo, IsPublicNode) { 30 | NodeInfo node_info("node_id"); 31 | node_info.public_ip = "10.88.0.100"; 32 | node_info.public_port = 8080; 33 | node_info.local_ip = "10.88.0.100"; 34 | node_info.local_port = 8080; 35 | ASSERT_TRUE(node_info.IsPublicNode()); 36 | node_info.Heartbeat(); 37 | } 38 | 39 | TEST_F(TestNodeInfo, copy) { 40 | NodeInfo node_info; 41 | NodeInfo node2(node_info); 42 | 43 | NodeInfo node3; 44 | node3 = node_info; 45 | } 46 | 47 | TEST_F(TestNodeInfo, cmp) { 48 | NodeInfo node; 49 | node.node_id = "1"; 50 | 51 | NodeInfo node2; 52 | node2.node_id = "2"; 53 | 54 | ASSERT_TRUE(node < node2); 55 | ASSERT_EQ("1", node.string()); 56 | } 57 | 58 | } // namespace test 59 | } // namespace kadmlia 60 | } // namespace top 61 | -------------------------------------------------------------------------------- /tests/test_client_node_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #define private public 12 | #include "xkad/routing_table/client_node_manager.h" 13 | 14 | namespace top { 15 | 16 | namespace kadmlia { 17 | 18 | namespace test { 19 | 20 | class TestClientNodeManager : public testing::Test { 21 | public: 22 | static void SetUpTestCase() { 23 | 24 | } 25 | 26 | static void TearDownTestCase() { 27 | } 28 | 29 | virtual void SetUp() { 30 | 31 | } 32 | 33 | virtual void TearDown() { 34 | } 35 | }; 36 | 37 | TEST_F(TestClientNodeManager, All) { 38 | ASSERT_NE(nullptr, ClientNodeManager::Instance()); 39 | 40 | ClientNodeManager client_node_mgr; 41 | ClientNodeInfoPtr node_info; 42 | node_info.reset(new ClientNodeInfo("id")); 43 | ASSERT_EQ(client_node_mgr.AddClientNode(node_info), kKadSuccess); 44 | 45 | { 46 | ASSERT_NE(nullptr, client_node_mgr.FindClientNode("id")); 47 | ASSERT_EQ(nullptr, client_node_mgr.FindClientNode("id2")); 48 | } 49 | 50 | client_node_mgr.RemoveClientNode("id"); 51 | ASSERT_TRUE(client_node_mgr.client_nodes_map_.empty()); 52 | 53 | } 54 | 55 | } // namespace test 56 | 57 | } // namespace kadmlia 58 | 59 | } // namespace top 60 | -------------------------------------------------------------------------------- /nat_detect/nat_manager_intf.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include "nat_defines.h" 11 | #include "xtransport/transport_fwd.h" 12 | 13 | namespace top { 14 | namespace kadmlia { 15 | 16 | class NatManagerIntf { 17 | using MessagePtr = std::shared_ptr; 18 | using PacketPtr = std::shared_ptr; 19 | public: 20 | static NatManagerIntf* Instance(); 21 | virtual ~NatManagerIntf() {} 22 | virtual bool GetLocalNatType(int32_t& nat_type) = 0; 23 | virtual void PushMessage(MessagePtr message_ptr, PacketPtr packet_ptr) = 0; 24 | virtual void PushMessage( 25 | transport::protobuf::RoutingMessage& message, 26 | base::xpacket_t& packet) = 0; 27 | virtual bool Start( 28 | bool first_node, 29 | const std::set>& boot_endpoints, 30 | transport::MultiThreadHandler* messager_handler, 31 | transport::Transport* transport, 32 | transport::Transport* nat_transport) = 0; 33 | virtual void Stop() = 0; 34 | virtual void SetNatType(NatType nat_type) = 0; 35 | }; 36 | 37 | } // namespace kadmlia 38 | } // namespace top 39 | -------------------------------------------------------------------------------- /src/rumor_message_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/gossip/rumor_message_manager.h" 6 | 7 | #include "xpbase/base/top_log.h" 8 | 9 | namespace top { 10 | namespace gossip { 11 | 12 | bool RumorMessageManager::AddMessage( 13 | const transport::protobuf::RoutingMessage& message) { 14 | if (!AddData(message.type(),message)) { 15 | TOP_WARN("RumorMessageManager::AddMessage Failed,message tpye[%d]",message.type()); 16 | return false; 17 | } 18 | return true; 19 | } 20 | 21 | void RumorMessageManager::RemoveMessage(int32_t message_type) { 22 | DeleteKey(message_type); 23 | } 24 | 25 | bool RumorMessageManager::SearchMessage( 26 | int32_t message_type, 27 | transport::protobuf::RoutingMessage& message) const { 28 | if (!FindData(message_type, message)) { 29 | TOP_WARN("RumorMessageManager::SearchMessage Failed,message type[%d]", 30 | message_type); 31 | return false; 32 | } 33 | return true; 34 | } 35 | 36 | void RumorMessageManager::GetAllMessages( 37 | std::vector& all_messages) { 38 | GetAllData(all_messages); 39 | } 40 | 41 | uint32_t RumorMessageManager::GetMessageCount() const { 42 | return Count(); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /bench/node.proto: -------------------------------------------------------------------------------- 1 | // protoc -I. --cpp_out=. node.proto 2 | 3 | syntax = "proto2"; 4 | package top.kadmlia.test.pb; 5 | 6 | 7 | message AllNodes { 8 | message Node { 9 | required string local_ip = 1; 10 | required int32 local_port = 2; 11 | required string public_ip = 3; 12 | required int32 public_port = 4; 13 | required uint64 service_type = 5; 14 | required int32 nat_type = 6; 15 | // required string xid = 7; 16 | // required uint64 hash64 = 8; 17 | // required string xip = 9; 18 | required bytes node_id = 10; 19 | }; 20 | 21 | repeated Node nodes = 1; 22 | }; 23 | 24 | message TestReportNodes { 25 | required int32 nodes_size = 1; 26 | } 27 | 28 | 29 | message TestConnRequest { 30 | required int64 tp1 = 1; 31 | 32 | required string src_ip = 10; 33 | required int32 src_port = 11; 34 | } 35 | 36 | message TestConnResponse { 37 | required int64 tp1 = 1; 38 | required int64 hops1 = 2; 39 | 40 | required string src_ip = 10; 41 | required int32 src_port = 11; 42 | } 43 | 44 | 45 | message TestConn2Request { 46 | required int64 tp1 = 1; 47 | 48 | required bool send_or_relay = 10; // true: send, false: relay 49 | required string src_ip = 11; 50 | required int32 src_port = 12; 51 | } 52 | 53 | message TestConn2Response { 54 | required int64 tp1 = 1; 55 | required int64 hops1 = 2; 56 | 57 | required bool send_or_relay = 10; 58 | } 59 | -------------------------------------------------------------------------------- /routing_table/client_node_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "xkad/routing_table/routing_utils.h" 14 | 15 | namespace top { 16 | 17 | namespace kadmlia { 18 | 19 | struct ClientNodeInfo { 20 | public: 21 | ClientNodeInfo(); 22 | explicit ClientNodeInfo(const std::string& id); 23 | ~ClientNodeInfo(); 24 | 25 | std::string node_id; 26 | std::string public_ip; 27 | uint16_t public_port; 28 | uint64_t src_service_type; 29 | 30 | private: 31 | DISALLOW_COPY_AND_ASSIGN(ClientNodeInfo); 32 | }; 33 | 34 | typedef std::shared_ptr ClientNodeInfoPtr; 35 | 36 | class ClientNodeManager { 37 | public: 38 | static ClientNodeManager* Instance(); 39 | int AddClientNode(ClientNodeInfoPtr node_ptr); 40 | void RemoveClientNode(const std::string& node_id); 41 | ClientNodeInfoPtr FindClientNode(const std::string& node_id); 42 | 43 | private: 44 | ClientNodeManager(); 45 | ~ClientNodeManager(); 46 | 47 | std::map client_nodes_map_; 48 | std::mutex client_nodes_map_mutex_; 49 | 50 | DISALLOW_COPY_AND_ASSIGN(ClientNodeManager); 51 | }; 52 | 53 | } // namespace kadmlia 54 | 55 | } // namespace top 56 | -------------------------------------------------------------------------------- /bench/util.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "xpbase/base/top_config.h" 13 | #include "xpbase/base/args_parser.h" 14 | 15 | namespace top { 16 | namespace kadmlia { 17 | namespace test { 18 | 19 | class BenchCommand { 20 | public: 21 | using Arguments = std::vector; 22 | using CommandProc = std::function; 23 | using MapCommands = std::map; 24 | 25 | public: 26 | static BenchCommand* Instance(); 27 | void Init(bool show_cmd); 28 | void Run(); 29 | void ProcessCommand(const std::string& cmdline); 30 | void RegisterCommand(const std::string& cmd_name, CommandProc cmd_proc); 31 | void PrintUsage(); 32 | 33 | protected: 34 | bool show_cmd_{true}; 35 | std::mutex map_commands_mutex_; 36 | MapCommands map_commands_; 37 | }; 38 | 39 | class Util { 40 | public: 41 | static Util* Instance(); 42 | bool HandleParamsAndConfig(int argc, char** argv, base::Config& config); 43 | 44 | private: 45 | bool ParseParams(int argc, char** argv, ArgsParser& args_parser); 46 | bool ResetConfig(ArgsParser& args_parser, base::Config& config); 47 | }; 48 | 49 | } // namespace test 50 | } // namespace kadmlia 51 | } // namespace top 52 | -------------------------------------------------------------------------------- /tests/test_dynamic_xip_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "xkad/routing_table/client_node_manager.h" 12 | #define private public 13 | #include "xkad/routing_table/dynamic_xip_manager.h" 14 | 15 | namespace top { 16 | 17 | namespace kadmlia { 18 | 19 | namespace test { 20 | 21 | class TestDynamicXipManager : public testing::Test { 22 | public: 23 | static void SetUpTestCase() { 24 | 25 | } 26 | 27 | static void TearDownTestCase() { 28 | } 29 | 30 | virtual void SetUp() { 31 | 32 | } 33 | 34 | virtual void TearDown() { 35 | } 36 | }; 37 | 38 | TEST_F(TestDynamicXipManager, All) { 39 | auto manager = std::make_shared(); 40 | ClientNodeInfoPtr node_info; 41 | node_info.reset(new ClientNodeInfo("id")); 42 | std::string dyxip = "1234"; 43 | ASSERT_EQ(kKadSuccess, manager->AddClientNode(dyxip, node_info)); 44 | 45 | { 46 | ASSERT_NE(nullptr, manager->FindClientNode(dyxip)); 47 | ASSERT_EQ(nullptr, manager->FindClientNode("abcd")); 48 | } 49 | 50 | manager->RemoveClientNode(dyxip); 51 | 52 | 53 | { 54 | const base::XipParser local_xip; 55 | auto ret = manager->DispatchDynamicXip(local_xip); 56 | ASSERT_EQ(16u, ret.size()); 57 | } 58 | } 59 | 60 | } // namespace test 61 | 62 | } // namespace kadmlia 63 | 64 | } // namespace top 65 | -------------------------------------------------------------------------------- /tests/test_nat_handshake_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "xtransport/udp_transport/udp_transport.h" 12 | #define private public 13 | #define protected public 14 | #include "xkad/nat_detect/nat_handshake_manager.h" 15 | 16 | namespace top { 17 | 18 | namespace kadmlia { 19 | 20 | namespace test { 21 | 22 | class TestNatHandshakeManager : public testing::Test { 23 | public: 24 | static void SetUpTestCase() { 25 | 26 | } 27 | 28 | static void TearDownTestCase() { 29 | } 30 | 31 | virtual void SetUp() { 32 | 33 | } 34 | 35 | virtual void TearDown() { 36 | } 37 | }; 38 | 39 | TEST_F(TestNatHandshakeManager, All) { 40 | NatHandshakeManager manager(base::TimerManager::Instance()); 41 | 42 | ASSERT_TRUE(manager.Start()); 43 | 44 | { 45 | std::string ip = "1234"; 46 | uint16_t port = 12345; 47 | auto transport = std::make_shared(); 48 | uint16_t detect_port = 5555; 49 | int32_t message_type = kKadNatDetectHandshake2Boot; 50 | int32_t delay_ms = 0; 51 | manager.AddDetection(ip, port, transport.get(), detect_port, message_type, delay_ms); 52 | 53 | manager.DetectProc(); 54 | 55 | manager.RemoveDetection(ip, port); 56 | } 57 | 58 | manager.Stop(); 59 | } 60 | 61 | 62 | } // namespace test 63 | 64 | } // namespace kadmlia 65 | 66 | } // namespace top 67 | -------------------------------------------------------------------------------- /routing_table/node_detection_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "xpbase/base/top_timer.h" 14 | #include "xkad/routing_table/routing_utils.h" 15 | 16 | namespace top { 17 | 18 | namespace kadmlia { 19 | 20 | struct NodeInfo; 21 | class RoutingTable; 22 | 23 | class NodeDetectionManager { 24 | public: 25 | explicit NodeDetectionManager(base::TimerManager* timer_manager, RoutingTable& routing_table); 26 | ~NodeDetectionManager(); 27 | void Join(); 28 | int AddDetectionNode(std::shared_ptr node_ptr); 29 | void RemoveDetection(const std::string& ip, uint16_t port); 30 | bool Detected(const std::string& id); 31 | 32 | private: 33 | void DoTetection(); 34 | int Handshake(std::shared_ptr node_ptr); 35 | 36 | std::map> detection_nodes_map_; 37 | std::mutex detection_nodes_map_mutex_; 38 | std::map> detected_nodes_map_; 39 | std::mutex detected_nodes_map_mutex_; 40 | RoutingTable& routing_table_; 41 | base::TimerManager* timer_manager_{nullptr}; 42 | std::shared_ptr timer_; 43 | bool destroy_{ false }; 44 | 45 | DISALLOW_COPY_AND_ASSIGN(NodeDetectionManager); 46 | }; 47 | 48 | } // namespace kadmlia 49 | 50 | } // namespace top 51 | -------------------------------------------------------------------------------- /routing_table/routing_table_heartbeat.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | // #pragma once 6 | 7 | // #include 8 | // #include 9 | // #include 10 | // #include 11 | // #include 12 | 13 | // #include "xpbase/base/top_log.h" 14 | // #include "xpbase/base/top_timer.h" 15 | 16 | // namespace top { 17 | // namespace kadmlia { 18 | 19 | // typedef std::function Callback; 20 | // typedef std::mutex Mutex; 21 | // typedef std::lock_guard Guard; 22 | 23 | // class RoutingTableHeartbeat { 24 | // public: 25 | // void Start(Callback heartbeat_proc, Callback heartbeat_check_proc) { 26 | // TOP_INFO("[heartbeat] starting ..."); 27 | // assert(heartbeat_proc); 28 | // assert(heartbeat_check_proc); 29 | // Guard guard(mutex_); 30 | 31 | // timer_.Start(10 * 1000, 1000 * 1000, heartbeat_proc); 32 | // timer_check_.Start(10 * 1000, 1000 * 1000, heartbeat_check_proc); 33 | // TOP_INFO("[heartbeat] started"); 34 | // } 35 | 36 | // void Stop() { 37 | // TOP_INFO("[heartbeat] stopping ..."); 38 | // Guard guard(mutex_); 39 | // timer_.Join(); 40 | // timer_check_.Join(); 41 | // TOP_INFO("[heartbeat] stopped"); 42 | // } 43 | 44 | // private: 45 | // Mutex mutex_; 46 | // Callback callback_; 47 | // base::TimerRepeated timer_; 48 | // base::TimerRepeated timer_check_; 49 | // }; 50 | 51 | // } // namespace kadmlia 52 | // } // namespace top 53 | -------------------------------------------------------------------------------- /tests/test_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "xpbase/base/top_log.h" 10 | #include "xpbase/base/top_config.h" 11 | #include "xkad/routing_table/routing_utils.h" 12 | 13 | namespace top { 14 | std::shared_ptr global_xid; 15 | uint32_t gloabl_platform_type = kPlatform; 16 | std::string global_node_id = RandomString(256); 17 | std::string global_node_id_hash(""); 18 | } 19 | 20 | int main(int argc, char *argv[]) { 21 | { 22 | const std::string str_file = 23 | R"( 24 | [log] 25 | path = ./log/bitvpn.log 26 | 27 | [node] 28 | first_node = false 29 | local_ip = 127.0.0.1 30 | local_port = 0 31 | client_mode = false 32 | country = US 33 | business = EDGE 34 | public_endpoints = 127.0.0.1:9000 35 | show_cmd = false 36 | role = 1 37 | 38 | [db] 39 | path = ./db 40 | 41 | )"; 42 | std::fstream fout("/tmp/test_routing_table.conf", std::ios::out); 43 | fout << str_file; 44 | fout.close(); 45 | } 46 | 47 | xinit_log("bitvpn_ut.log", true, true); 48 | xset_log_level(enum_xlog_level_debug); 49 | top::base::Config config; 50 | config.Init("/tmp/test_routing_table.conf"); 51 | top::kadmlia::CreateGlobalXid(config); 52 | 53 | testing::GTEST_FLAG(output) = "xml:"; 54 | testing::InitGoogleTest(&argc, argv); 55 | ::testing::InitGoogleMock(&argc, argv); 56 | int ret = RUN_ALL_TESTS(); 57 | TOP_INFO("exit"); 58 | return ret; 59 | } 60 | -------------------------------------------------------------------------------- /tests/test_node_detection_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "xkad/routing_table/routing_table.h" 12 | #include "xkad/routing_table/node_info.h" 13 | #define private public 14 | #define protected public 15 | #include "xkad/routing_table/node_detection_manager.h" 16 | 17 | namespace top { 18 | 19 | namespace kadmlia { 20 | 21 | namespace test { 22 | 23 | class TestNodeDetectionManager : public testing::Test { 24 | public: 25 | static void SetUpTestCase() { 26 | 27 | } 28 | 29 | static void TearDownTestCase() { 30 | } 31 | 32 | virtual void SetUp() { 33 | 34 | } 35 | 36 | virtual void TearDown() { 37 | } 38 | }; 39 | 40 | TEST_F(TestNodeDetectionManager, All) { 41 | auto sptr_node_info = std::make_shared("qwertgfdsazxcvbnhcdswq34321edswq"); 42 | sptr_node_info->public_ip = "10.18.0.100"; 43 | sptr_node_info->public_port = 5000; 44 | std::shared_ptr local_node = std::make_shared(); 45 | RoutingTable routing_table(nullptr, kNodeIdSize, local_node); 46 | NodeDetectionManager node_detection_mgr(base::TimerManager::Instance(), routing_table); 47 | node_detection_mgr.AddDetectionNode(sptr_node_info); 48 | node_detection_mgr.RemoveDetection("10.18.0.100", 5000); 49 | 50 | { 51 | std::string id = "1234"; 52 | ASSERT_FALSE(node_detection_mgr.Detected(id)); 53 | } 54 | } 55 | 56 | 57 | } // namespace test 58 | 59 | } // namespace kadmlia 60 | 61 | } // namespace top 62 | -------------------------------------------------------------------------------- /tests/test_bootstrap_cache.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include "xpbase/base/top_utils.h" 10 | #include "xpbase/base/line_parser.h" 11 | #include "xkad/routing_table/routing_utils.h" 12 | #define private public 13 | #include "xkad/routing_table/bootstrap_cache.h" 14 | 15 | namespace top { 16 | namespace kadmlia { 17 | namespace test { 18 | 19 | class TestBootstrapCache : public testing::Test { 20 | public: 21 | static void SetUpTestCase() { 22 | } 23 | 24 | static void TearDownTestCase() { 25 | } 26 | 27 | virtual void SetUp() { 28 | } 29 | 30 | virtual void TearDown() { 31 | } 32 | }; 33 | 34 | TEST_F(TestBootstrapCache, GetCache) { 35 | BootstrapCacheManager manager; 36 | ASSERT_TRUE(manager.Init()); 37 | ASSERT_TRUE(manager.Init()); // init again 38 | auto cache = manager.GetBootStrapCache(1); 39 | ASSERT_NE(nullptr, cache); 40 | VecBootstrapEndpoint vec_bootstrap_endpoint = { 41 | {"1.1.1.1", 11111}, 42 | {"2.2.2.2", 22222} 43 | }; 44 | ASSERT_TRUE(cache->SetCache(vec_bootstrap_endpoint)); 45 | VecBootstrapEndpoint vec2; 46 | ASSERT_TRUE(cache->GetCache(vec2)); 47 | // ASSERT_EQ(vec_bootstrap_endpoint, vec2); 48 | } 49 | 50 | TEST_F(TestBootstrapCache, GetBootstrapCache) { 51 | const uint64_t service_type = kRoot; 52 | auto ptr = GetBootstrapCache(service_type); 53 | ASSERT_NE(nullptr, ptr); 54 | } 55 | 56 | } // namespace test 57 | } // namespace kadmlia 58 | } // namespace top 59 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/node.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAsYVOoKUD8/+3gyzL22Vq4YYUVGo49H1vNJg4/PbENA7YrRCh 3 | jXUKHR3en9JTjOlAc0ggWKPJ8MdTKVWU9ldK13Lo3cRHh6RAwcFk9YZ1e5cLmH+r 4 | ppTPV0JFGI9HEwNwfoaS4N46JYOyHcmAMp6xg0+u/6YLPJiuPhqtCOkgPNiyAnFF 5 | 0PAtrfzmlOU8eF+CWqjwAseStQDfWDQHUOEE+jENPFqksUF5/ZA1hKRKhm7qtE/Y 6 | JOP5Dh7+hrhzWtrOS4IEPP1eKRMAqYwv16bcFQhNZwb2IKo2TzqjfDw1ZRcAlQ2F 7 | N7eFejeGY29fD85t25bCMHJ4+LwzcdIr+RL00wIDAQABAoIBABGS+O2+aF3Hewtp 8 | a+UUbThWZbzVpz3NDS1PxJSGeXYN4jV/5/5xD8dCJb/8unjAvriq80jTLjLACOOW 9 | rWCV07rwjU0nGU28XQzRcIU+AnNxyJwYR43+PWiODvkXdhnTxVdBS1knpun/16pL 10 | QH3CaCBvywtUDNi65MURLwAq1B4xy1mdAjBSaYj/nQ6X8Be7y1iNj7z3mltfKA1Q 11 | z4BF4gfyXfLgUKkJ/baL0je8ULRyKNmgorE2E9urp8HiotcnGdaalaDo3O1AqdGj 12 | XMh7O9qVYfNqnEOl4RlgAo5HIvDUhoUDtItqcFglPNGN05QeAwnvFTiSBd4R7k+i 13 | U+qQFQECgYEA5c/MA8lqxxKMy1BvYnhgnQN1rtfmEBW4LZs5ikr6Ccoa9rLbJipP 14 | Wom87vD1w1MGdmcy3eMUa7CUOqDv/RaskiBxo9/L3sl6jlFdb/u3cY/XJUmDcpxE 15 | fMBS2P2eSoOQCtjmRsk0Ck1bHR6aIBUTSBRoO5lAr/2K5xwM9X6qE/ECgYEAxcAM 16 | A1GFAwowa4QGyout9ylkzTh68pBjY+jSNaQmp07Y7t9tC+OlJrEAs1bRO7pluFWT 17 | z5H1OzmTd+uvp3BL3jEz4QPr0ndddHaY35bOGcwqqiKzMOIQTzXYe/aAMol6rMG/ 18 | VJADfZk6SCwbb4OqIp+j/AeZYhKPMSBmDyS1SQMCgYEA2juhVntAHfl8oFoq3AzK 19 | WnB9oeK+Q8oMU6rTUoNuvDsjreAdAjotjyG7vAAwsiK2wVuwz0skCjvuF1rba7DL 20 | ghyzLdaJSHB2JI4ZuA0GoB3jRjJwVDcXRoxwYEU/uy0CbXqZ+uB4vcvF2XpFDHBX 21 | Fhzi+q3G4xlXfa6Ck+KL6lECgYATpjGLYt5Enw6QoF3MYnS2ynYpriMJVy+JDelV 22 | SypMFZmYorrDI6uVXKElMMs5lBvnZRl61pX3fJEaqWCa0p23RkxRX4JfN10h5Wbr 23 | UKDKD29t2GTVxqC4PjF0n9m9K8v0vou0a1rtb/xKj5dqTTrqldJFiLvE8vMnfoCl 24 | oJAi4QKBgE9bF38NP1tEmYaif/eU2vZw+ww1LhvYQjITRqIpt7aAB/9DA/kxh3wM 25 | ZwdGMXEa8RfbC17nfAv+sgEhs2QqgOraj5vp9DgvM1EhLfa7XSe4jA6TwzPeMVYR 26 | SmvYKhBabFhqakp8iTe+ffAYwR2yVUmRIKedXysP9eQK9VQwIMb0 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /bench/xkad_bench1/online/bridge.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAyURdU78uQOoe9OrC9yDsmqW7KoQ60nChLXvPMSyrXEgY+H5Q 3 | TktaEgvVDCAZjqS1WjScqn6LIfCt1ote4vh+zbH+jbJQa0YLCspaZqngmkW+COWK 4 | SLOSQkDVx8+qY00flb6xqrbINQwAwTreZ1nsWo/KKvsU753WsQ0/PADnOpboVq1C 5 | xW04nOEW8zNwOHZs4CQnHK/nLbt6gABAaCoakp77RaXmeu0mqa+bES0u5lH5yzDU 6 | whqDh7yD4Vl1pJiS36ajDulN3xwxul2zfnjsnpNBKLH4zu+k42BiSr5G4loOJcaT 7 | c40z1bEafz4DpClwtiw5gAQA1RArnWMtjjpyQQIDAQABAoIBAAy0dRO5SMkuPkAF 8 | pcMF4AmvFo6LhE8Obw44945KHJMZtgHRr24R0aC8AHngeNyJRy1njtAwZsYAtGiL 9 | qbS4LQD9EG2PaQYsiLvopCZA6P20E1fqbX1DYKMwBo6zbDUShEDmpb56BU9b75xD 10 | BBEQGxxoYUGvUdYCZ7ALfwdhozcOfPjofL+GRtsNsey+tLZtTeSH+D/sFfms+YJn 11 | vpEDQP68jQ/kmFYyJrmjw9utJsTLyfF2N+SaPhPkHEDUgyW+ojZjf2SfkxCtLiwb 12 | 3Is6Q/UtvsjXcMb0+hmy4YOjRun6kYi2mjvZmHO8P+DcxgyijL6wwqUxdfaCrFlM 13 | L+8DncECgYEA5nj7hJVOO6wD7gFXdhIsWMJw67oDg0B9nWoKVTnM6hN+rZZg9a+z 14 | ryyTfHB4/ohcy97mzsKcZCErx7SGFCJ69Ggbt+JJ+JaNsk/NqiIKbD1Uh1p2QNp0 15 | lqhLWDYaS2+2XVq94I7V1zau50OAzoj/aiZSN5eEdABSsoGhdH+L9rkCgYEA349D 16 | XoUU4MPH39Yo3czPGiDtKm/VTLx7m+bqaR+GF48ubLiibY7cV2K353b+6cO3gCWU 17 | oSTMXAkNWof9heDOefS+uejtUmvgENFYHjWVGn82rwCHPIpe5Xi3Zp80QOyDqqZE 18 | uet4yCYsnLubHeAnppH8dEQy3tMXhJ65ilM2E8kCgYEAo7yP9EGeswYiRJTvbhK7 19 | LtP1JYOhuz22AH+1l5bY3fO7q9eKSwHoxisFHQNK8oouYyiZEYtxUDHAyMCYAPX+ 20 | JGVSS/GYW+OaB3RqyNQmU3++7ep22NxauC4YWTMWu0FCblBpVYAkrCFNYT+z4wex 21 | bdiL0LL0hvUzy14NNpbm+QECgYEA0rIs5jo60RLzn2wxm8jZL2D05Nf9iZLiVK6v 22 | ImBJeo7BTEo/G05XMCyj8oxd92cz3JyOlckeqWcGpNoiADk9oAcgcgqrENEGnhMP 23 | H3mUiyJ2IT04N8CZa1/4Scml78J43S5S+36HmOsRhK3zpZaLCBvyeImGACemtKD7 24 | cPi3sLECgYBZxuPrbtqE38UkXarwEJINnyiAFYuPhkAGrHys/+RYHrMQKDRQsERk 25 | oNwY75XkwQ04aNQ9mKex1xdcdRUOj6v21bEJzwAXq5S6K1Lj8or8shcB7+Xki5Et 26 | etxz/73hRBQNdrBTQFZDTL1t3Vgw6cTcX0sC7Mk+wqXssxgGtwrsgQ== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /routing_table/nat_detect_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "xpbase/base/top_timer.h" 14 | #include "xkad/routing_table/routing_utils.h" 15 | #include "xkad/routing_table/node_info.h" 16 | 17 | namespace top { 18 | 19 | namespace kadmlia { 20 | 21 | struct NodeInfo; 22 | class RoutingTable; 23 | class NatDetectSocket; 24 | 25 | class NatDetectManager { 26 | struct NatDetectStruct { 27 | std::string ip; 28 | uint16_t port; 29 | uint16_t detect_port; 30 | int32_t message_type; 31 | int32_t delay_count{0}; 32 | int32_t detect_count{0}; 33 | }; 34 | 35 | public: 36 | NatDetectManager(RoutingTable* routing_table, int64_t service_type); 37 | ~NatDetectManager(); 38 | void AddDetection( 39 | const std::string& ip, 40 | uint16_t port, 41 | uint16_t detect_port, 42 | int32_t message_type, 43 | int32_t delay_ms); 44 | void RemoveDetection(const std::string& ip, uint16_t port); 45 | bool Start(); 46 | bool Stop(); 47 | 48 | private: 49 | void DetectProc(); 50 | int DoHandshake( 51 | const std::string& peer_ip, 52 | uint16_t detect_port, 53 | int32_t message_type); 54 | 55 | RoutingTable* routing_table_{nullptr}; 56 | int64_t service_type_{-1}; 57 | std::map> peers_; 58 | std::mutex mutex_; 59 | std::shared_ptr timer_{std::make_shared()}; 60 | 61 | DISALLOW_COPY_AND_ASSIGN(NatDetectManager); 62 | }; 63 | 64 | } // namespace kadmlia 65 | 66 | } // namespace top 67 | -------------------------------------------------------------------------------- /routing_table/node_info.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "xbasic/xhash.hpp" 12 | #include "xkad/routing_table/routing_utils.h" 13 | #include "xkad/nat_detect/nat_defines.h" 14 | #include "xtransport/transport_fwd.h" 15 | 16 | namespace top { 17 | namespace kadmlia { 18 | 19 | const int kInvalidBucketIndex = -1; 20 | const int kSelfBucketIndex = 0; 21 | 22 | struct NodeInfo { 23 | public: 24 | NodeInfo(); 25 | NodeInfo(const NodeInfo& other); 26 | NodeInfo(const std::string& id); 27 | ~NodeInfo(); 28 | NodeInfo& operator=(const NodeInfo& other); 29 | bool operator < (const NodeInfo& other) const; 30 | bool IsPublicNode(); 31 | std::string string(); 32 | bool IsTimeout(std::chrono::steady_clock::time_point tp_now); 33 | bool IsTimeToHeartbeat(std::chrono::steady_clock::time_point tp_now); 34 | void Heartbeat(); 35 | void ResetHeartbeat(); 36 | 37 | public: 38 | std::string node_id; 39 | int bucket_index{ kInvalidBucketIndex }; 40 | std::string public_ip; 41 | uint16_t public_port{ 0 }; 42 | std::string local_ip; 43 | uint16_t local_port{ 0 }; 44 | int32_t connection_id{ 0 }; 45 | int32_t detection_count{ 0 }; 46 | int32_t nat_type{ 0 }; 47 | int32_t detection_delay_count{ 0 }; 48 | int32_t heartbeat_count{ 0 }; // count > 3 49 | uint64_t service_type{ 0 }; 50 | bool is_client{ false }; 51 | std::chrono::steady_clock::time_point tp_next_time_to_heartbeat; 52 | bool same_vlan{ false }; 53 | std::string xid; 54 | std::string xip; 55 | uint32_t score{ 0 }; 56 | uint64_t hash64{ 0 }; 57 | transport::UdpPropertyPtr udp_property; 58 | }; 59 | 60 | typedef std::shared_ptr NodeInfoPtr; 61 | 62 | } // namespace kadmlia 63 | } // namespace top 64 | -------------------------------------------------------------------------------- /nat_detect/nat_handshake_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "xtransport/transport.h" 14 | #include "xpbase/base/xbyte_buffer.h" 15 | #include "xpbase/base/top_timer.h" 16 | #include "xkad/routing_table/routing_utils.h" 17 | #include "xkad/routing_table/node_info.h" 18 | 19 | namespace top { 20 | namespace kadmlia { 21 | 22 | class NatHandshakeManager { 23 | struct NatDetectStruct { 24 | std::string ip; 25 | uint16_t port; 26 | transport::Transport* transport; 27 | uint16_t detect_port; 28 | int32_t message_type; 29 | int32_t delay_count{0}; 30 | int32_t detect_count{0}; 31 | }; 32 | 33 | public: 34 | NatHandshakeManager(base::TimerManager* timer_manager); 35 | ~NatHandshakeManager(); 36 | void AddDetection( 37 | const std::string& ip, 38 | uint16_t port, 39 | transport::Transport* transport, 40 | uint16_t detect_port, 41 | int32_t message_type, 42 | int32_t delay_ms); 43 | void RemoveDetection(const std::string& ip, uint16_t port); 44 | bool Start(); 45 | void Stop(); 46 | void SetName(const std::string& name); 47 | 48 | private: 49 | void DetectProc(); 50 | int DoHandshake( 51 | transport::Transport* transport, 52 | const std::string& peer_ip, 53 | uint16_t detect_port, 54 | int32_t message_type); 55 | 56 | std::string name_{""}; 57 | std::atomic started_{false}; 58 | std::map> peers_; 59 | std::mutex mutex_; 60 | base::TimerManager* timer_manager_{nullptr}; 61 | std::shared_ptr timer_; 62 | 63 | DISALLOW_COPY_AND_ASSIGN(NatHandshakeManager); 64 | }; 65 | 66 | } // namespace kadmlia 67 | } // namespace top 68 | -------------------------------------------------------------------------------- /src/client_node_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/client_node_manager.h" 6 | 7 | #include "xbase/xutl.h" 8 | #include "xkad/routing_table/routing_table.h" 9 | #include "xpbase/base/top_log.h" 10 | 11 | namespace top { 12 | 13 | namespace kadmlia { 14 | 15 | ClientNodeInfo::ClientNodeInfo() 16 | : node_id(), 17 | public_ip(), 18 | public_port(0), 19 | src_service_type(0) {} 20 | 21 | ClientNodeInfo::ClientNodeInfo(const std::string& id) 22 | : node_id(id), 23 | public_ip(), 24 | public_port(0), 25 | src_service_type(0) {} 26 | 27 | ClientNodeInfo::~ClientNodeInfo() {} 28 | 29 | ClientNodeManager::ClientNodeManager() 30 | : client_nodes_map_(), 31 | client_nodes_map_mutex_() {} 32 | 33 | ClientNodeManager::~ClientNodeManager() {} 34 | 35 | ClientNodeManager* ClientNodeManager::Instance() { 36 | static ClientNodeManager ins; 37 | return &ins; 38 | } 39 | 40 | int ClientNodeManager::AddClientNode(ClientNodeInfoPtr node_ptr) { 41 | std::unique_lock lock(client_nodes_map_mutex_); 42 | std::string key = node_ptr->node_id; 43 | client_nodes_map_[key] = node_ptr; 44 | return kKadSuccess; 45 | } 46 | 47 | void ClientNodeManager::RemoveClientNode(const std::string& node_id) { 48 | std::unique_lock lock(client_nodes_map_mutex_); 49 | std::string key = node_id; 50 | auto iter = client_nodes_map_.find(key); 51 | if (iter != client_nodes_map_.end()) { 52 | client_nodes_map_.erase(iter); 53 | } 54 | } 55 | 56 | ClientNodeInfoPtr ClientNodeManager::FindClientNode(const std::string& node_id) { 57 | std::unique_lock lock(client_nodes_map_mutex_); 58 | std::string key = node_id; 59 | auto iter = client_nodes_map_.find(key); 60 | if (iter != client_nodes_map_.end()) { 61 | return iter->second; 62 | } 63 | return nullptr; 64 | } 65 | 66 | } // namespace kadmlia 67 | 68 | } // namespace top 69 | -------------------------------------------------------------------------------- /routing_table/bootstrap_cache.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "xpbase/base/top_utils.h" 15 | #include "xpbase/base/top_config.h" 16 | 17 | namespace top { 18 | namespace kadmlia { 19 | 20 | using BootstrapEndpoint = std::pair; 21 | using VecBootstrapEndpoint = std::vector; 22 | 23 | class BootstrapCacheManager; 24 | class BootstrapCache { 25 | friend class BootstrapCacheManager; 26 | using Lock = std::unique_lock; 27 | const uint32_t INVALID_SERVICE_TYPE = (uint32_t)-1; 28 | 29 | public: 30 | BootstrapCache(); 31 | ~BootstrapCache(); 32 | bool GetCache(VecBootstrapEndpoint& vec_bootstrap_endpoint); 33 | bool SetCache(const VecBootstrapEndpoint& vec_bootstrap_endpoint); 34 | 35 | private: 36 | uint64_t service_type_{INVALID_SERVICE_TYPE}; 37 | BootstrapCacheManager* manager_{nullptr}; 38 | 39 | private: 40 | DISALLOW_COPY_AND_ASSIGN(BootstrapCache); 41 | }; 42 | 43 | using BootstrapCachePtr = std::shared_ptr; 44 | 45 | BootstrapCachePtr GetBootstrapCache(uint64_t service_type); 46 | 47 | class BootstrapCacheManager { 48 | using Lock = std::unique_lock; 49 | public: 50 | static BootstrapCacheManager* Instance(); 51 | BootstrapCacheManager(); 52 | ~BootstrapCacheManager(); 53 | bool Init(); 54 | BootstrapCachePtr GetBootStrapCache(uint64_t service_type); 55 | bool SetCache(uint64_t service_type, const VecBootstrapEndpoint& vec_bootstrap_endpoint); 56 | bool GetCache(uint64_t service_type, VecBootstrapEndpoint& vec_bootstrap_endpoint); 57 | 58 | private: 59 | std::mutex mutex_; 60 | bool inited_{false}; 61 | std::map map_; 62 | 63 | private: 64 | DISALLOW_COPY_AND_ASSIGN(BootstrapCacheManager); 65 | }; 66 | 67 | } // namespace kadmlia 68 | } // namespace top 69 | -------------------------------------------------------------------------------- /gossip/rumor_handler.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include "xkad/proto/kadmlia.pb.h" 11 | #include "xkad/gossip/rumor_message_manager.h" 12 | #include "xkad/gossip/rumor_def.h" 13 | #include "xkad/routing_table/node_info.h" 14 | #include "xkad/routing_table/local_node_info.h" 15 | 16 | namespace top { 17 | 18 | namespace kadmlia { 19 | class RoutingTable; 20 | typedef std::shared_ptr RoutingTablePtr; 21 | } 22 | 23 | namespace gossip { 24 | 25 | class RumorHandler { 26 | public: 27 | RumorHandler() 28 | :inited_(false), 29 | just_root_(false), 30 | kad_routing_table_(), 31 | message_manager_ptr_(std::make_shared()) {} 32 | 33 | RumorHandler(bool just_root) 34 | :inited_(false), 35 | just_root_(just_root), 36 | kad_routing_table_(), 37 | message_manager_ptr_(std::make_shared()) {} 38 | ~RumorHandler() {} 39 | bool Init( 40 | kadmlia::RoutingTablePtr); 41 | bool UnInit(); 42 | bool AddRumorMessage( 43 | const transport::protobuf::RoutingMessage&); 44 | void RemoveRumorMessage( 45 | int32_t); 46 | bool FindRumorMessage( 47 | int32_t, 48 | transport::protobuf::RoutingMessage&); 49 | void GetAllRumorMessage( 50 | std::vector&); 51 | bool SendToClosestNode( 52 | const transport::protobuf::RoutingMessage&); 53 | std::shared_ptr LocalNodeInfo() const; 54 | void SpreadNeighbors( 55 | transport::protobuf::RoutingMessage&, 56 | const std::vector&); 57 | void SpreadNeighborsRapid( 58 | transport::protobuf::RoutingMessage&); 59 | void SpreadNeighborsSelfMessage(); 60 | void GetAllNeighborNodes( 61 | std::vector&); 62 | private: 63 | bool inited_; 64 | bool just_root_; 65 | kadmlia::RoutingTablePtr kad_routing_table_; 66 | RumorMessageManagerSptr message_manager_ptr_; 67 | 68 | DISALLOW_COPY_AND_ASSIGN(RumorHandler); 69 | }; 70 | 71 | using RumorHandlerSptr = std::shared_ptr; 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/node_mgr.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "xpbase/base/top_utils.h" 17 | #include "xpbase/base/line_parser.h" 18 | #include "xpbase/base/kad_key/platform_kadmlia_key.h" 19 | #include "xtransport/udp_transport/udp_transport.h" 20 | #include "xtransport/src/message_manager.h" 21 | #define private public 22 | #define protected public 23 | #include "xkad/routing_table/routing_table.h" 24 | #include "xkad/routing_table/bootstrap_cache_helper.h" 25 | #include "xkad/routing_table/local_node_info.h" 26 | #include "xkad/routing_table/kad_message_handler.h" 27 | #include "xtransport/message_manager/multi_message_handler.h" 28 | #include "xkad/src/nat_manager.h" 29 | #undef private 30 | #undef protected 31 | #include "xpbase/base/top_timer.h" 32 | 33 | namespace top { 34 | namespace kadmlia { 35 | namespace test { 36 | 37 | class NodeMgr { 38 | public: 39 | NodeMgr(); 40 | ~NodeMgr(); 41 | bool Init(bool first_node, const std::string& name_prefix); 42 | bool NatDetect(const std::string& peer_ip, uint16_t peer_port); 43 | bool JoinRt(const std::string& peer_ip, uint16_t peer_port); 44 | std::string LocalIp(); 45 | uint16_t RealLocalPort(); 46 | void HandleMessage( 47 | transport::protobuf::RoutingMessage& message, 48 | base::xpacket_t& packet); 49 | 50 | protected: 51 | std::shared_ptr timer_manager_impl_; 52 | 53 | transport::UdpTransportPtr nat_transport_; 54 | std::shared_ptr nat_manager_; 55 | 56 | kadmlia::KadMessageHandler kad_message_handler_; 57 | transport::MessageManager message_manager_; 58 | std::shared_ptr thread_message_handler_; 59 | transport::UdpTransportPtr udp_transport_; 60 | std::shared_ptr routing_table_ptr_; 61 | bool first_node_{false}; 62 | std::string name_prefix_; 63 | std::string name_{""}; 64 | const std::string local_ip_{"127.0.0.1"}; 65 | const uint16_t local_port_{0}; 66 | uint16_t real_local_port_{0}; 67 | }; 68 | 69 | } // namespace test 70 | } // namespace kadmlia 71 | } // namespace top 72 | -------------------------------------------------------------------------------- /src/dynamic_xip_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/dynamic_xip_manager.h" 6 | 7 | //#include "xbase/xutl.h" 8 | #include "xkad/routing_table/client_node_manager.h" 9 | #include "xpbase/base/top_log.h" 10 | #include "xpbase/base/xip_parser.h" 11 | 12 | #define d_get_process_id(id) ( ((id) & 0xF00000) >> 16 ) 13 | #define d_get_router_id(id) ( ((id) & 0x0F0000) >> 16 ) 14 | #define d_get_switch_id(id) ( ((id) & 0xFF00) >> 8 ) 15 | #define d_get_local_id(id) ( ((id) & 0xFF) ) 16 | 17 | namespace top { 18 | 19 | namespace kadmlia { 20 | 21 | DynamicXipManager::DynamicXipManager() 22 | : dy_xip_map_(), 23 | dy_xip_map_mutex_() {} 24 | 25 | DynamicXipManager::~DynamicXipManager() {} 26 | 27 | // dispatch xip for bootstrap node 28 | std::string DynamicXipManager::DispatchDynamicXip(const base::XipParser& local_xip) { 29 | base::XipParser dynamic_xip(local_xip); 30 | dynamic_xip.set_xip_type(enum_xip_type_dynamic); 31 | 32 | // TODO(smaug) not sure about bit operation 33 | uint32_t now_id = ++atom_xip_manager_id_; 34 | dynamic_xip.set_process_id(d_get_process_id(now_id)); 35 | dynamic_xip.set_router_id(d_get_router_id(now_id)); 36 | dynamic_xip.set_switch_id(d_get_switch_id(now_id)); 37 | dynamic_xip.set_local_id(d_get_local_id(now_id)); 38 | return dynamic_xip.xip(); 39 | } 40 | 41 | int DynamicXipManager::AddClientNode(const std::string& dy_xip, ClientNodeInfoPtr node_ptr) { 42 | std::unique_lock lock(dy_xip_map_mutex_); 43 | dy_xip_map_[dy_xip] = node_ptr; 44 | return kKadSuccess; 45 | } 46 | 47 | void DynamicXipManager::RemoveClientNode(const std::string& dy_xip) { 48 | std::unique_lock lock(dy_xip_map_mutex_); 49 | std::string key = dy_xip; 50 | auto iter = dy_xip_map_.find(key); 51 | if (iter != dy_xip_map_.end()) { 52 | dy_xip_map_.erase(iter); 53 | } 54 | } 55 | 56 | ClientNodeInfoPtr DynamicXipManager::FindClientNode(const std::string& dy_xip) { 57 | std::unique_lock lock(dy_xip_map_mutex_); 58 | std::string key = dy_xip; 59 | auto iter = dy_xip_map_.find(key); 60 | if (iter != dy_xip_map_.end()) { 61 | return iter->second; 62 | } 63 | return nullptr; 64 | } 65 | 66 | } // namespace kadmlia 67 | 68 | } // namespace top 69 | -------------------------------------------------------------------------------- /tests/test_local_node_info.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #define private public 13 | #include "xkad/routing_table/local_node_info.h" 14 | #include "xpbase/base/xid/xid_generator.h" 15 | #include "xkad/nat_detect/nat_manager_intf.h" 16 | #include "xpbase/base/kad_key/platform_kadmlia_key.h" 17 | 18 | namespace top { 19 | 20 | namespace kadmlia { 21 | 22 | namespace test { 23 | 24 | class TestLocalNodeInfo : public testing::Test { 25 | public: 26 | static void SetUpTestCase() { 27 | } 28 | 29 | static void TearDownTestCase() { 30 | } 31 | 32 | virtual void SetUp() { 33 | } 34 | 35 | virtual void TearDown() { 36 | } 37 | }; 38 | 39 | TEST_F(TestLocalNodeInfo, All) { 40 | std::string idtype(top::kadmlia::GenNodeIdType("CN", "VPN")); 41 | LocalNodeInfo local_node_info; 42 | base::XIDGenerator xid_generator; 43 | base::XIDType xid_type; 44 | xid_type.xnetwork_id_ = 19; 45 | xid_type.zone_id_ = 250; 46 | ASSERT_TRUE(xid_generator.CreateXID(xid_type)); 47 | base::XIDSptr xid = nullptr; 48 | xid.reset(new base::XID); 49 | ASSERT_TRUE(xid_generator.GetXID(*xid)); 50 | NatManagerIntf::Instance()->SetNatType(kNatTypePublic); 51 | local_node_info.nat_type_ = kNatTypePublic; 52 | auto kad_key = std::make_shared(); 53 | kad_key->set_xnetwork_id(kEdgeXVPN); 54 | const bool first_node = true; 55 | ASSERT_TRUE(local_node_info.Init( 56 | "0.0.0.0", 15942, first_node, false, idtype, kad_key, kEdgeXVPN, kRoleEdge)); 57 | 58 | { 59 | base::XipParser xip_parser; 60 | auto str_xip = xip_parser.xip(); 61 | local_node_info.set_xip(str_xip); 62 | } 63 | 64 | { 65 | const std::string node_id = "1234"; 66 | const std::string dxip = "abcd"; 67 | local_node_info.AddDxip(node_id, dxip); 68 | ASSERT_TRUE(local_node_info.HasDynamicXip(dxip)); 69 | local_node_info.DropDxip(node_id); 70 | ASSERT_FALSE(local_node_info.HasDynamicXip(dxip)); 71 | } 72 | 73 | local_node_info.Reset(); 74 | } 75 | 76 | TEST_F(TestLocalNodeInfo, set_xip) { 77 | 78 | } 79 | 80 | } // namespace test 81 | 82 | } // namespace kadmlia 83 | 84 | } // namespace top 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xkad(a high performance X-DHT) 2 | 3 | >A High Performance Distributed Hash Table implementation of TOP Network. 4 | 5 | ## Feature highlights 6 | 7 | + Lightweight and scalable, designed for large networks and small devices 8 | + Fully designed for Multi-Cores and Muti-Threads 9 | + High resilience to network disruption 10 | + Multi-Network support & High Performance & Low memory/cpu consumption 11 | + TCP,UDP,XUDP,ICMP protocols support, and IPv4 & IPv6 support 12 | + Public key cryptography layer providing optional data signature and encryption 13 | + iOS, Android, Windows, MacOS, Linux support 14 | 15 | ## Example 16 | 17 | ### C++ example 18 | 19 | The demo and bench directory includes some simple example programs: 20 | 21 | + Kademlia, a High Performance Kademlia 22 | 23 | 24 | ``` 25 | int main() { 26 | // something init 27 | // .... 28 | // 29 | 30 | // load config 31 | base::Config config; 32 | std::string local_ip; 33 | ASSERT_TRUE(config.Get("node", "local_ip", local_ip)); 34 | uint16_t local_port = 0; 35 | NatManagerIntf::Instance()->SetNatType(kNatTypePublic); 36 | udp_transport_.reset(new top::transport::UdpTransport()); 37 | thread_message_handler_ = std::make_shared(); 38 | thread_message_handler_->Init(); 39 | auto kad_key = std::make_shared(); 40 | kad_key->set_xnetwork_id(top::kRoot); 41 | uint32_t zone_id = 0; 42 | kad_key->set_zone_id(zone_id); 43 | auto local_node_ptr = CreateLocalInfoFromConfig(config, kad_key); 44 | const uint64_t service_type = kRoot; 45 | local_node_ptr->set_service_type(service_type); 46 | 47 | // create routing table 48 | routing_table_ptr_.reset(new top::kadmlia::RoutingTable( 49 | udp_transport_, 50 | kNodeIdSize, 51 | local_node_ptr)); 52 | kad_message_handler_.set_routing_ptr(routing_table_ptr_); 53 | std::set> boot_endpoints{ 54 | { node_mgr_->LocalIp(), node_mgr_->RealLocalPort() } 55 | }; 56 | 57 | // join network 58 | int res = routing_table_ptr_->MultiJoin(boot_endpoints); 59 | 60 | 61 | // something uninit 62 | // .... 63 | return res; 64 | } 65 | 66 | ``` 67 | 68 | 69 | ## Contact 70 | 71 | [TOP Network](https://www.topnetwork.org/) 72 | 73 | ## License 74 | 75 | Copyright (c) 2017-2019 Telos Foundation & contributors 76 | 77 | Distributed under the MIT software license, see the accompanying 78 | 79 | file COPYING or http://www.opensource.org/licenses/mit-license.php. 80 | -------------------------------------------------------------------------------- /routing_table/callback_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "xpbase/base/top_timer.h" 15 | #include "xkad/routing_table/routing_utils.h" 16 | #include "xtransport/proto/transport.pb.h" 17 | #include "xkad/proto/kadmlia.pb.h" 18 | 19 | namespace top { 20 | 21 | namespace base { 22 | class xpacket_t; 23 | } 24 | 25 | namespace kadmlia { 26 | 27 | typedef std::function ResponseFunctor; 31 | typedef std::function, 36 | std::shared_ptr)> CallbackResponseFunctor; 37 | 38 | struct CallbackItem { 39 | uint32_t message_id; 40 | ResponseFunctor callback; 41 | CallbackResponseFunctor mutex_callback; 42 | int32_t timeout_sec; 43 | int32_t expect_count; 44 | std::shared_ptr wait_mutex; 45 | std::shared_ptr wait_condition; 46 | 47 | ~CallbackItem(); 48 | }; 49 | 50 | typedef std::shared_ptr CallbackItemPtr; 51 | 52 | class CallbackManager { 53 | public: 54 | static CallbackManager* Instance(); 55 | static uint32_t MessageId(); 56 | void Join(); 57 | void Add( 58 | uint32_t message_id, 59 | int32_t timeout_sec, 60 | ResponseFunctor callback, 61 | int32_t expect_count); 62 | void Add(CallbackItemPtr callback_ptr); 63 | void Callback( 64 | uint32_t message_id, 65 | transport::protobuf::RoutingMessage& message, 66 | base::xpacket_t& packet); 67 | void Timeout(uint32_t message_id); 68 | void Cancel(uint32_t message_id, uint32_t no_callback); 69 | 70 | private: 71 | CallbackManager(); 72 | ~CallbackManager(); 73 | 74 | void TimeoutCheck(); 75 | 76 | static std::atomic msg_id_; 77 | std::map callback_map_; 78 | std::mutex callback_map_mutex_; 79 | base::SingleThreadTimer timer_; 80 | 81 | DISALLOW_COPY_AND_ASSIGN(CallbackManager); 82 | }; 83 | 84 | typedef std::shared_ptr CallbackManagerPtr; 85 | 86 | } // namespace kadmlia 87 | 88 | } // namespace top 89 | -------------------------------------------------------------------------------- /routing_table/kad_message_handler.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include "xbase/xlog.h" 11 | #include "xbase/xobject.h" 12 | #include "xbase/xthread.h" 13 | #include "xbase/xtimer.h" 14 | #include "xbase/xdata.h" 15 | #include "xbase/xpacket.h" 16 | #include "xbase/xsocket.h" 17 | #include "xbase/xutl.h" 18 | 19 | #include "xtransport/proto/transport.pb.h" 20 | #include "xkad/proto/kadmlia.pb.h" 21 | #include "xkad/routing_table/routing_utils.h" 22 | #include "xwrouter/register_message_handler.h" 23 | #include "xtransport/message_manager/message_manager_intf.h" 24 | #include "xkad/nat_detect/nat_manager_intf.h" 25 | 26 | namespace top { 27 | 28 | namespace kadmlia { 29 | 30 | class RoutingTable; 31 | class ThreadHandler; 32 | typedef std::shared_ptr RoutingTablePtr; 33 | 34 | class KadMessageHandler { 35 | public: 36 | KadMessageHandler(); 37 | ~KadMessageHandler(); 38 | void Init(); 39 | void set_routing_ptr(std::shared_ptr routing_ptr); 40 | std::shared_ptr routing_ptr() { return routing_ptr_; } 41 | 42 | private: 43 | void AddBaseHandlers(); 44 | int HandleClientMessage(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 45 | void HandleConnectRequest(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 46 | void HandleHandshake(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 47 | void HandleBootstrapJoinRequest(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 48 | void HandleBootstrapJoinResponse(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 49 | void HandleFindNodesRequest(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 50 | void HandleFindNodesResponse(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 51 | void SendAck(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 52 | void HandleHeartbeatRequest(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 53 | void HandleHeartbeatResponse(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 54 | 55 | std::shared_ptr routing_ptr_; 56 | transport::MessageManagerIntf* message_manager_{transport::MessageManagerIntf::Instance()}; 57 | kadmlia::NatManagerIntf* nat_manager_{kadmlia::NatManagerIntf::Instance()}; 58 | }; 59 | 60 | } // namespace kadmlia 61 | 62 | } // namespace top 63 | -------------------------------------------------------------------------------- /bench/main.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | #include "util.h" 7 | #include "node.h" 8 | #include "xpbase/base/kad_key/get_kadmlia_key.h" 9 | #include "xkad/routing_table/routing_utils.h" 10 | #include "xpbase/base/endpoint_util.h" 11 | 12 | using namespace top::kadmlia::test; 13 | 14 | namespace top { 15 | uint32_t gloabl_platform_type = kPlatform; 16 | std::shared_ptr global_xid; 17 | std::string global_node_id = RandomString(kNodeIdSize); 18 | std::string global_node_id_hash(""); 19 | } 20 | 21 | int main(int argc, char* argv[]) { 22 | // load argv 23 | base::Config config; 24 | { 25 | // default config as first node 26 | config.Set("node", "first_node", true); 27 | config.Set("node", "show_cmd", true); 28 | config.Set("node", "local_ip", "127.0.0.1"); 29 | config.Set("node", "local_port", 0); 30 | config.Set("node", "public_endpoints", "127.0.0.1:0"); 31 | config.Set("node", "log_path", "./xkad_bench.log"); 32 | config.Set("node", "log_level", enum_xlog_level_debug); // debug 33 | config.Set("node", "zone_id", 1); // for global xid 34 | if (!Util::Instance()->HandleParamsAndConfig(argc, argv, config)) { 35 | TOP_FATAL("handle argv failed"); 36 | return 1; 37 | } 38 | } 39 | 40 | // init log 41 | { 42 | std::string log_path; 43 | if (!config.Get("node", "log_path", log_path)) { 44 | assert(0); 45 | } 46 | int log_level = enum_xlog_level_debug; 47 | if (!config.Get("node", "log_level", log_level)) { 48 | assert(0); 49 | } 50 | xinit_log(log_path.c_str(), true, true); 51 | xset_log_level((enum_xlog_level)log_level); 52 | } 53 | 54 | // init global xid 55 | if (!top::kadmlia::CreateGlobalXid(config)) { 56 | assert(0); 57 | } 58 | 59 | bool first_node = false; 60 | if (!config.Get("node", "first_node", first_node)) { 61 | assert(0); 62 | } 63 | 64 | bool show_cmd = false; 65 | if (!config.Get("node", "show_cmd", show_cmd)) { 66 | assert(0); 67 | } 68 | BenchCommand::Instance()->Init(show_cmd); 69 | MyNodeMgr node_mgr; 70 | 71 | if (first_node) { 72 | if (!node_mgr.Init(config, "1")) { 73 | TOP_FATAL("node_mgr init failed"); 74 | return 1; 75 | } 76 | } else { 77 | if (!node_mgr.Init(config, "2")) { 78 | TOP_FATAL("node_mgr init failed"); 79 | return 1; 80 | } 81 | 82 | if (!node_mgr.JoinRt()) { 83 | TOP_FATAL("node_mgr join failed"); 84 | return 1; 85 | } 86 | } 87 | 88 | BenchCommand::Instance()->Run(); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /tests/test_bootstrap_cache_helper.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include "xpbase/base/top_utils.h" 10 | #include "xpbase/base/line_parser.h" 11 | #include "xkad/routing_table/routing_utils.h" 12 | #include "xpbase/base/kad_key/get_kadmlia_key.h" 13 | #define private public 14 | #include "xkad/routing_table/bootstrap_cache_helper.h" 15 | 16 | namespace top { 17 | namespace kadmlia { 18 | namespace test { 19 | 20 | class TestBootstrapCacheHelper : public testing::Test { 21 | public: 22 | static void SetUpTestCase() { 23 | } 24 | 25 | static void TearDownTestCase() { 26 | } 27 | 28 | virtual void SetUp() { 29 | } 30 | 31 | virtual void TearDown() { 32 | } 33 | }; 34 | 35 | TEST_F(TestBootstrapCacheHelper, All) { 36 | auto helper = std::make_shared(base::TimerManager::Instance()); 37 | auto kad_key = base::GetKadmliaKey(); 38 | kad_key->set_xnetwork_id(kRoot); 39 | auto get_public_nodes = [](std::vector& vec){ 40 | auto node_info = std::make_shared(); 41 | node_info->public_ip = "1"; 42 | node_info->public_port = 2; 43 | vec.push_back(node_info); 44 | }; 45 | auto get_service_public_nodes = [](uint64_t service_type, std::vector& vec){ 46 | auto node_info = std::make_shared(); 47 | node_info->public_ip = "3"; 48 | node_info->public_port = 4; 49 | vec.push_back(node_info); 50 | }; 51 | ASSERT_TRUE(helper->Start(kad_key, get_public_nodes, get_service_public_nodes)); 52 | ASSERT_TRUE(helper->Start(kad_key, get_public_nodes, get_service_public_nodes)); // start again 53 | 54 | { 55 | std::vector public_nodes; 56 | helper->GetPublicEndpoints(public_nodes); 57 | ASSERT_EQ(0u, public_nodes.size()); 58 | } 59 | 60 | { 61 | std::set> boot_endpoints; 62 | helper->GetPublicEndpoints(boot_endpoints); 63 | ASSERT_EQ(0u, boot_endpoints.size()); 64 | } 65 | 66 | { 67 | uint64_t service_type = kRoot; 68 | ASSERT_TRUE(helper->SetCacheServiceType(service_type)); 69 | std::set> boot_endpoints; 70 | ASSERT_TRUE(helper->GetCacheServicePublicNodes(service_type, boot_endpoints)); 71 | ASSERT_EQ(1u, boot_endpoints.size()); 72 | } 73 | 74 | { 75 | helper->DumpPublicEndpoints(); 76 | } 77 | 78 | { 79 | auto ret = helper->GetRandomCacheServiceType(); 80 | ASSERT_EQ(top::kRoot, ret); 81 | } 82 | 83 | { 84 | helper->RepeatCacheServicePublicNodes(); 85 | } 86 | 87 | helper->Stop(); 88 | } 89 | 90 | } // namespace test 91 | } // namespace kadmlia 92 | } // namespace top 93 | -------------------------------------------------------------------------------- /tests/test_kad_message_handler.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | // #include 6 | 7 | // #include 8 | 9 | // #include 10 | 11 | // #include "xkad/routing_table/routing_table.h" 12 | // #include "xtransport/udp_transport/udp_transport.h" 13 | // #include "xpbase/base/kad_key/get_kadmlia_key.h" 14 | // #include "xkad/routing_table/local_node_info.h" 15 | // #define private public 16 | // #define protected public 17 | // #include "xkad/routing_table/kad_message_handler.h" 18 | // #include "xtransport/message_manager/message_manager_intf.h" 19 | 20 | // namespace top { 21 | 22 | // namespace kadmlia { 23 | 24 | // namespace test { 25 | 26 | // class TestKadMessageHandler : public testing::Test { 27 | // public: 28 | // static void SetUpTestCase() { 29 | 30 | // } 31 | 32 | // static void TearDownTestCase() { 33 | // } 34 | 35 | // virtual void SetUp() { 36 | 37 | // } 38 | 39 | // virtual void TearDown() { 40 | // } 41 | // }; 42 | 43 | // TEST_F(TestKadMessageHandler, All) { 44 | // std::vector vec_message{ 45 | // kKadConnectRequest, 46 | // kKadHandshake, 47 | // kKadBootstrapJoinRequest, 48 | // kKadBootstrapJoinResponse, 49 | // kKadFindNodesRequest, 50 | // kKadFindNodesResponse, 51 | // kKadHeartbeatRequest, 52 | // kKadHeartbeatResponse, 53 | // kKadAck, 54 | // kKadNatDetectRequest, 55 | // kKadNatDetectResponse, 56 | // kKadNatDetectHandshake2Node, 57 | // kKadNatDetectHandshake2Boot, 58 | // kKadNatDetectFinish, 59 | // }; 60 | 61 | // for (auto msg_type : vec_message) { 62 | // transport::MessageManagerIntf::Instance()->UnRegisterMessageProcessor(msg_type); 63 | // } 64 | 65 | // auto local_node = std::make_shared(); 66 | // // const base::XipParser xip; 67 | // // local_node->set_kadmlia_key(base::GetKadmliaKey(xip)); 68 | // std::string xid; 69 | // xid.resize(kNodeIdSize); 70 | // local_node->set_kadmlia_key(base::GetKadmliaKey(xid)); 71 | // local_node->set_first_node(true); 72 | // uint32_t kadmlia_key_len = kNodeIdSize; 73 | // auto transport = std::make_shared(); 74 | // auto routing_table = std::make_shared(transport, kadmlia_key_len, local_node); 75 | // ASSERT_TRUE(routing_table->Init()); 76 | // KadMessageHandler message_handler; 77 | // message_handler.set_routing_ptr(routing_table); 78 | // for (auto msg_type : vec_message) { 79 | // transport::protobuf::RoutingMessage message; 80 | // { 81 | // std::string des_node_id; 82 | // des_node_id.resize(36); 83 | // message.set_des_node_id(des_node_id); 84 | // } 85 | // base::xpacket_t packet; 86 | // message.set_type(msg_type); 87 | // transport::MessageManagerIntf::Instance()->HandleMessage(message, packet); 88 | // } 89 | // } 90 | 91 | // } // namespace test 92 | 93 | // } // namespace kadmlia 94 | 95 | // } // namespace top 96 | -------------------------------------------------------------------------------- /tests/test_routing_table2.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "xpbase/base/top_utils.h" 15 | #include "xpbase/base/top_timer.h" 16 | #include "xpbase/base/line_parser.h" 17 | #include "xpbase/base/kad_key/platform_kadmlia_key.h" 18 | #include "xtransport/udp_transport/udp_transport.h" 19 | #include "xtransport/src/message_manager.h" 20 | #include "node_mgr.h" 21 | 22 | namespace top { 23 | namespace kadmlia { 24 | namespace test { 25 | 26 | class TestRoutingTable2 : public testing::Test { 27 | public: 28 | static void SetUpTestCase() { 29 | mgr1_ = std::make_shared(); 30 | ASSERT_TRUE(mgr1_->Init(true, "1")); 31 | } 32 | 33 | static void TearDownTestCase() { 34 | mgr1_ = nullptr; 35 | } 36 | 37 | virtual void SetUp() {} 38 | 39 | virtual void TearDown() {} 40 | 41 | protected: 42 | static std::shared_ptr mgr1_; 43 | }; 44 | 45 | std::shared_ptr TestRoutingTable2::mgr1_; 46 | 47 | TEST_F(TestRoutingTable2, NatDetect) { 48 | auto mgr2 = std::make_shared(); 49 | ASSERT_TRUE(mgr2->Init(false, "2")); 50 | ASSERT_TRUE(mgr2->NatDetect(mgr1_->LocalIp(), mgr1_->RealLocalPort())); 51 | mgr2 = nullptr; 52 | } 53 | 54 | TEST_F(TestRoutingTable2, Join) { 55 | auto mgr2 = std::make_shared(); 56 | ASSERT_TRUE(mgr2->Init(false, "3")); 57 | ASSERT_TRUE(mgr2->JoinRt(mgr1_->LocalIp(), mgr1_->RealLocalPort())); 58 | mgr2 = nullptr; 59 | } 60 | 61 | // handle message 62 | TEST_F(TestRoutingTable2, kKadConnectRequest) { 63 | transport::protobuf::RoutingMessage message; 64 | message.set_type(kKadConnectRequest); 65 | base::xpacket_t packet; 66 | mgr1_->HandleMessage(message, packet); 67 | } 68 | 69 | TEST_F(TestRoutingTable2, kKadNatDetectRequest) { 70 | transport::protobuf::RoutingMessage message; 71 | message.set_type(kKadNatDetectRequest); 72 | base::xpacket_t packet; 73 | mgr1_->HandleMessage(message, packet); 74 | } 75 | 76 | TEST_F(TestRoutingTable2, kKadNatDetectResponse) { 77 | transport::protobuf::RoutingMessage message; 78 | message.set_type(kKadNatDetectResponse); 79 | base::xpacket_t packet; 80 | mgr1_->HandleMessage(message, packet); 81 | } 82 | 83 | TEST_F(TestRoutingTable2, kKadNatDetectHandshake2Node) { 84 | transport::protobuf::RoutingMessage message; 85 | message.set_type(kKadNatDetectHandshake2Node); 86 | base::xpacket_t packet; 87 | mgr1_->HandleMessage(message, packet); 88 | } 89 | 90 | TEST_F(TestRoutingTable2, kKadNatDetectHandshake2Boot) { 91 | transport::protobuf::RoutingMessage message; 92 | message.set_type(kKadNatDetectHandshake2Boot); 93 | base::xpacket_t packet; 94 | mgr1_->HandleMessage(message, packet); 95 | } 96 | 97 | TEST_F(TestRoutingTable2, kKadNatDetectFinish) { 98 | transport::protobuf::RoutingMessage message; 99 | message.set_type(kKadNatDetectFinish); 100 | base::xpacket_t packet; 101 | mgr1_->HandleMessage(message, packet); 102 | } 103 | 104 | } // namespace test 105 | } // namespace kadmlia 106 | } // namespace top 107 | -------------------------------------------------------------------------------- /routing_table/bootstrap_cache_helper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "xpbase/base/top_timer.h" 16 | #include "xpbase/base/rand_util.h" 17 | #include "xpbase/base/kad_key/kadmlia_key.h" 18 | #include "xkad/routing_table/bootstrap_cache.h" 19 | #include "xkad/routing_table/node_info.h" 20 | 21 | namespace top { 22 | namespace kadmlia { 23 | 24 | // get public nodes from self routing table 25 | using GetPublicNodes = std::function&)>; 26 | // get some kind service public node from root-routing-table 27 | using GetServicePublicNodes = std::function&)>; 28 | typedef std::shared_ptr> VecNodeInfoPtr; 29 | 30 | class BootstrapCacheHelper : public std::enable_shared_from_this { 31 | static const int32_t kDumpBootstrapPeriod = 60 * 1000 * 1000; // 60s 32 | static const int32_t kCacheServiceBootstrapPeriod = 3 * 1000 * 1000; // 60s 33 | static const int32_t kCacheServiceNodesSize = 8; // keep 8 nodes enough 34 | static const int32_t kCacheServiceNodesDeleteSize = 4; // if more than 8 nodes, delete 4 nodes base insert time 35 | public: 36 | bool Start( 37 | base::KadmliaKeyPtr kad_key, 38 | GetPublicNodes get_public_nodes, 39 | GetServicePublicNodes get_service_public_nodes = nullptr); 40 | void Stop(); 41 | void GetPublicEndpoints(std::vector& public_endpoints); 42 | void GetPublicEndpoints(std::set>& boot_endpoints); 43 | // add target service_type to be cached 44 | bool SetCacheServiceType(uint64_t service_type); 45 | // get cache nodes of service_type give 46 | bool GetCacheServicePublicNodes( 47 | uint64_t service_type, 48 | std::set>& boot_endpoints); 49 | BootstrapCacheHelper(base::TimerManager* timer_manager); 50 | ~BootstrapCacheHelper(); 51 | 52 | private: 53 | void DumpPublicEndpoints(); 54 | void LoadBootstrapCache(); 55 | void RepeatCacheServicePublicNodes(); 56 | void CacheServicePublicNodes(uint64_t service_type); 57 | uint64_t GetRandomCacheServiceType(); 58 | 59 | private: 60 | std::mutex mutex_; 61 | bool inited_{false}; 62 | base::KadmliaKeyPtr kad_key_; 63 | std::mutex public_endpoint_mutex_; 64 | std::vector public_endpoints_; 65 | top::kadmlia::VecBootstrapEndpoint vec_endpoints_; 66 | base::TimerManager* timer_manager_{nullptr}; 67 | std::shared_ptr timer_dump_public_endpoints_; 68 | std::shared_ptr timer_Cache_Service_public_endpoints_; 69 | kadmlia::BootstrapCachePtr bootstrap_cache_ptr_; 70 | GetPublicNodes get_public_nodes_; 71 | // get some kind service public node from root-routing-table 72 | GetServicePublicNodes get_service_public_nodes_; 73 | // key is service_type, value is node of the service_type 74 | std::map service_public_nodes_; 75 | std::mutex service_public_nodes_mutex_; 76 | // keep target service_types which need to be cached 77 | std::set cache_service_types_; 78 | std::mutex cache_service_types_mutex_; 79 | }; 80 | 81 | } // namespace kadmlia 82 | } // namespace top 83 | -------------------------------------------------------------------------------- /tests/test_nat_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "xpbase/base/top_log.h" 12 | #include "xtransport/udp_transport/udp_transport.h" 13 | #include "xtransport/message_manager/multi_message_handler.h" 14 | #include "xpbase/base/top_utils.h" 15 | #define private public 16 | #define protected public 17 | #include "xkad/src/nat_manager.h" 18 | 19 | namespace top { 20 | 21 | namespace kadmlia { 22 | 23 | namespace test { 24 | 25 | class TestNatManager : public testing::Test { 26 | public: 27 | static void SetUpTestCase() { 28 | 29 | } 30 | 31 | static void TearDownTestCase() { 32 | } 33 | 34 | virtual void SetUp() { 35 | 36 | } 37 | 38 | virtual void TearDown() { 39 | } 40 | }; 41 | 42 | TEST_F(TestNatManager, NatManagerIntf) { 43 | NatManagerIntf* p = new NatManager(); 44 | delete p; 45 | p = nullptr; 46 | } 47 | 48 | TEST_F(TestNatManager, All) { 49 | ASSERT_NE(nullptr, NatManagerIntf::Instance()); 50 | 51 | auto manager = std::make_shared(); 52 | auto message_handler = std::make_shared(); 53 | message_handler->Init(); 54 | auto transport = std::make_shared(); 55 | transport->Start("127.0.0.1", 0, message_handler.get()); 56 | auto nat_transport = std::make_shared(); 57 | nat_transport->Start("127.0.0.1", 0, message_handler.get()); 58 | 59 | // TODO: need first node 60 | { 61 | bool first_node = true; 62 | const std::set> boot_endpoints{{"127.0.0.1", 9000}}; 63 | ASSERT_TRUE(manager->Start( 64 | first_node, 65 | boot_endpoints, 66 | message_handler.get(), 67 | transport.get(), 68 | nat_transport.get())); 69 | 70 | 71 | } 72 | 73 | { 74 | int32_t nat_type; 75 | ASSERT_TRUE(manager->GetLocalNatType(nat_type)); 76 | // ASSERT_EQ(kNatTypeUnknown, nat_type); // TODO: 77 | } 78 | 79 | { 80 | manager->SetNatTypeAndNotify(kNatTypePublic); 81 | } 82 | 83 | { 84 | transport::protobuf::RoutingMessage message; 85 | base::xpacket_t packet; 86 | manager->HandleNatDetectRequest(message, packet); 87 | manager->HandleNatDetectResponse(message, packet); 88 | manager->HandleNatDetectHandshake2Node(message, packet); 89 | manager->HandleNatDetectHandshake2Boot(message, packet); 90 | manager->HandleNatDetectFinish(message, packet); 91 | } 92 | 93 | { 94 | auto message = std::make_shared(); 95 | auto packet = std::make_shared(); 96 | manager->PushMessage(message, packet); 97 | manager->PushMessage(*message, *packet); 98 | // manager->ThreadProc(); 99 | } 100 | 101 | { 102 | manager->SendNatDetectRequest("1234", 1234); 103 | manager->SendNatDetectFinish("1234", 1234); 104 | } 105 | 106 | manager->OnTimerNatDetectTimeout(); 107 | manager->ThreadJoin(); 108 | manager->ThreadProc(); 109 | manager->Stop(); 110 | 111 | nat_transport->Stop(); 112 | transport->Stop(); 113 | TOP_DEBUG("stoping all objectes"); 114 | 115 | manager = nullptr; 116 | nat_transport = nullptr; 117 | transport = nullptr; 118 | message_handler = nullptr; 119 | 120 | SleepUs(2 * 1000 * 1000); 121 | TOP_DEBUG("stopped all objectes"); 122 | } 123 | 124 | 125 | } // namespace test 126 | 127 | } // namespace kadmlia 128 | 129 | } // namespace top 130 | -------------------------------------------------------------------------------- /demo/xkaddemo.xcodeproj/xcshareddata/xcschemes/xkaddemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 81 | 87 | 88 | 89 | 90 | 92 | 93 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/node_info.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/node_info.h" 6 | #include "xtransport/udp_transport/xudp_socket.h" 7 | 8 | namespace top { 9 | namespace kadmlia { 10 | 11 | static const int kHeartbeatFirstTimeout = 8; // seconds 12 | static const int kHeartbeatSecondTimeout = 2; // seconds 13 | static const int kHeartbeatErrorMaxCount = 12; 14 | 15 | NodeInfo::NodeInfo() { 16 | ResetHeartbeat(); 17 | } 18 | 19 | NodeInfo::NodeInfo(const NodeInfo& other) 20 | : node_id(other.node_id), 21 | bucket_index(other.bucket_index), 22 | public_ip(other.public_ip), 23 | public_port(other.public_port), 24 | local_ip(other.local_ip), 25 | local_port(other.local_port), 26 | connection_id(other.connection_id), 27 | detection_count(other.detection_count), 28 | nat_type(other.nat_type), 29 | detection_delay_count(other.detection_delay_count), 30 | heartbeat_count(other.heartbeat_count), 31 | service_type(other.service_type), 32 | is_client(other.is_client), 33 | same_vlan(other.same_vlan), 34 | xid(other.xid), 35 | xip(other.xip), 36 | score(other.score) { 37 | hash64 = base::xhash64_t::digest(xid); 38 | ResetHeartbeat(); 39 | udp_property.reset(new top::transport::UdpProperty()); 40 | } 41 | 42 | NodeInfo::NodeInfo(const std::string& id) : node_id(id) { 43 | ResetHeartbeat(); 44 | udp_property.reset(new top::transport::UdpProperty()); 45 | } 46 | 47 | NodeInfo::~NodeInfo() { 48 | udp_property = nullptr; 49 | } 50 | 51 | NodeInfo& NodeInfo::operator=(const NodeInfo& other) { 52 | if (this == &other) { 53 | return *this; 54 | } 55 | node_id = other.node_id; 56 | bucket_index = other.bucket_index; 57 | public_ip = other.public_ip; 58 | public_port = other.public_port; 59 | local_ip = other.local_ip; 60 | local_port = other.local_port; 61 | connection_id = other.connection_id; 62 | detection_count = other.detection_count; 63 | nat_type = other.nat_type; 64 | detection_delay_count = other.detection_delay_count; 65 | heartbeat_count = other.heartbeat_count; // count > 3 66 | service_type = other.service_type; 67 | is_client = other.is_client; 68 | tp_next_time_to_heartbeat = other.tp_next_time_to_heartbeat; 69 | same_vlan = other.same_vlan; 70 | xid = other.xid; 71 | xip = other.xip; 72 | score = other.score; 73 | hash64 = base::xhash64_t::digest(xid); 74 | return *this; 75 | } 76 | 77 | bool NodeInfo::operator < (const NodeInfo& other) const { 78 | return node_id < other.node_id; 79 | } 80 | 81 | bool NodeInfo::IsPublicNode() { 82 | return public_ip == local_ip && public_port == local_port; 83 | } 84 | 85 | std::string NodeInfo::string() { 86 | return node_id; 87 | } 88 | 89 | bool NodeInfo::IsTimeout(std::chrono::steady_clock::time_point tp_now) { 90 | return heartbeat_count >= kHeartbeatErrorMaxCount; 91 | } 92 | 93 | bool NodeInfo::IsTimeToHeartbeat(std::chrono::steady_clock::time_point tp_now) { 94 | return tp_now > tp_next_time_to_heartbeat; 95 | } 96 | 97 | void NodeInfo::Heartbeat() { 98 | ++heartbeat_count; 99 | tp_next_time_to_heartbeat = std::chrono::steady_clock::now() + 100 | std::chrono::seconds(kHeartbeatSecondTimeout); 101 | } 102 | 103 | void NodeInfo::ResetHeartbeat() { 104 | heartbeat_count = 0; 105 | tp_next_time_to_heartbeat = std::chrono::steady_clock::now() + 106 | std::chrono::seconds(kHeartbeatFirstTimeout); 107 | } 108 | 109 | } // namespace kadmlia 110 | } // namespace top 111 | -------------------------------------------------------------------------------- /nat_detect/nat_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include "xkad/nat_detect/nat_manager_intf.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "xbase/xpacket.h" 21 | #include "xtransport/transport.h" 22 | #include "xtransport/proto/transport.pb.h" 23 | #include "xpbase/base/xbyte_buffer.h" 24 | #include "xpbase/base/top_utils.h" 25 | #include "xpbase/base/top_timer.h" 26 | #include "xkad/proto/kadmlia.pb.h" 27 | #include "xkad/nat_detect/nat_defines.h" 28 | #include "xkad/nat_detect/nat_handshake_manager.h" 29 | 30 | namespace top { 31 | 32 | namespace transport { 33 | class MultiThreadHandler; 34 | } 35 | 36 | namespace kadmlia { 37 | 38 | class NatManager : public NatManagerIntf { 39 | using MessagePtr = std::shared_ptr; 40 | using PacketPtr = std::shared_ptr; 41 | class MessageQueue { 42 | public: 43 | void PushMessage(MessagePtr message_ptr, PacketPtr packet_ptr); 44 | bool GetMessage(MessagePtr& message_ptr, PacketPtr& packet_ptr); 45 | void Clear(); 46 | void SetName(const std::string& name); 47 | 48 | private: 49 | std::string name_{""}; 50 | std::mutex mutex_; 51 | std::condition_variable condv_; 52 | std::deque> queue_; 53 | }; 54 | 55 | public: 56 | NatManager(); 57 | ~NatManager(); 58 | bool GetLocalNatType(int32_t& nat_type); 59 | void PushMessage(MessagePtr message_ptr, PacketPtr packet_ptr); 60 | void PushMessage( 61 | transport::protobuf::RoutingMessage& message, 62 | base::xpacket_t& packet); 63 | bool Start( 64 | bool first_node, 65 | const std::set>& boot_endpoints, 66 | transport::MultiThreadHandler*, 67 | transport::Transport* transport, 68 | transport::Transport* nat_transport); 69 | void Stop(); 70 | void SetNatType(NatType nat_type); 71 | 72 | private: 73 | void HandleNatDetectRequest(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 74 | void HandleNatDetectResponse(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 75 | void HandleNatDetectHandshake2Node(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 76 | void HandleNatDetectHandshake2Boot(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 77 | void HandleNatDetectFinish(transport::protobuf::RoutingMessage& message, base::xpacket_t& packet); 78 | void SendNatDetectRequest( 79 | const std::string& peer_ip, 80 | uint16_t peer_port); 81 | void SendNatDetectFinish( 82 | const std::string& peer_ip, 83 | uint16_t peer_port); 84 | bool MultiNatDetect(const std::set>& boot_endpoints); 85 | void ThreadProc(); 86 | void ThreadJoin(); 87 | xbyte_buffer_t SerializeMessage(const transport::protobuf::RoutingMessage& message); 88 | void OnTimerNatDetectTimeout(); 89 | bool SetNatTypeAndNotify(NatType nat_type); 90 | 91 | private: 92 | std::string name_{""}; 93 | std::atomic started_{false}; 94 | std::atomic stopped_{false}; 95 | std::mutex mutex_; 96 | std::condition_variable cond_; 97 | std::atomic nat_type_{kNatTypePublic}; 98 | MessageQueue message_queue_; 99 | std::shared_ptr nat_handshake_manager_; 100 | base::TimerManager* timer_manager_{base::TimerManager::Instance()}; 101 | std::shared_ptr timer_; 102 | transport::Transport* transport_{nullptr}; 103 | transport::Transport* nat_transport_; 104 | std::atomic thread_destroy_{false}; 105 | std::shared_ptr thread_; 106 | 107 | private: 108 | DISALLOW_COPY_AND_ASSIGN(NatManager); 109 | }; 110 | 111 | } // namespace kadmlia 112 | } // namespace top 113 | -------------------------------------------------------------------------------- /routing_table/local_node_info.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "xkad/routing_table/routing_utils.h" 14 | #include "xpbase/base/xid/xid_def.h" 15 | #include "xkad/nat_detect/nat_defines.h" 16 | #include "xpbase/base/kad_key/kadmlia_key.h" 17 | #include "xpbase/base/xip_parser.h" 18 | #include "xkad/nat_detect/nat_manager_intf.h" 19 | 20 | namespace top { 21 | 22 | namespace kadmlia { 23 | 24 | class LocalNodeInfo { 25 | public: 26 | LocalNodeInfo(); 27 | ~LocalNodeInfo(); 28 | 29 | bool Init( 30 | const std::string& local_ip, 31 | uint16_t local_port, 32 | bool first_node, 33 | bool client, 34 | const std::string& idtype, 35 | base::KadmliaKeyPtr kadmlia_key, 36 | uint64_t service_type, 37 | uint32_t role); 38 | void Reset(); 39 | bool IsPublicNode() const; 40 | std::string kad_key(); 41 | std::string xid(); 42 | std::string xip(); 43 | std::string id(); 44 | base::XipParser& GetXipParser(); 45 | std::string local_ip() { return local_ip_; } 46 | uint16_t local_port() { return local_port_; } 47 | void set_local_port(uint16_t local_port) { local_port_ = local_port; } 48 | bool first_node() { return first_node_; } 49 | void set_first_node(bool first_node) { first_node_ = first_node; } 50 | bool client_mode() { return client_mode_; } 51 | std::string private_key() { return private_key_; } 52 | std::string public_key() { return public_key_; } 53 | std::string public_ip() { return public_ip_; } 54 | std::string idtype() { return idtype_; } 55 | uint16_t public_port() { return public_port_; } 56 | int32_t nat_type() { return nat_type_; } 57 | void set_public_ip(const std::string& ip) { public_ip_ = ip; } 58 | void set_public_port(uint16_t port) { public_port_ = port; } 59 | uint64_t service_type() { return service_type_; } 60 | void set_service_type(uint64_t service_type) { service_type_ = service_type; } 61 | uint32_t routing_table_id() { return routing_table_id_; } 62 | void set_routing_table_id(uint32_t routing_table_id) { routing_table_id_ = routing_table_id; } 63 | uint32_t role() { return role_; } 64 | void set_role(int32_t role_type) { role_ = role_type; } 65 | base::KadmliaKeyPtr kadmlia_key() { 66 | std::lock_guard lock(kadkey_mutex_); 67 | return kadmlia_key_; 68 | } 69 | void set_kadmlia_key(base::KadmliaKeyPtr kadmlia_key) { 70 | std::lock_guard lock(kadkey_mutex_); 71 | kadmlia_key_ = kadmlia_key; 72 | } 73 | uint32_t score() { return score_; } 74 | void set_xip(const std::string& xip_str); 75 | inline bool use_kad_key() { 76 | if (kadmlia_key_) { 77 | return true; 78 | } 79 | return false; 80 | } 81 | bool HasDynamicXip(const std::string& dxip); 82 | void AddDxip(const std::string& node_id, const std::string& dxip); 83 | void DropDxip(const std::string& node_id); 84 | uint16_t rpc_http_port() { return rpc_http_port_; } 85 | uint16_t rpc_ws_port() { return rpc_ws_port_; } 86 | void set_rpc_http_port(uint16_t http_port) { rpc_http_port_ = http_port; } 87 | void set_rpc_ws_port(uint16_t ws_port) { rpc_ws_port_ = ws_port; } 88 | bool is_root() { return is_root_; } 89 | void set_is_root(bool root) { is_root_ = root; } 90 | uint64_t hash64() { return hash64_; } 91 | 92 | private: 93 | std::string local_ip_; 94 | uint16_t local_port_{ 0 }; 95 | uint16_t rpc_http_port_{ 0 }; 96 | uint16_t rpc_ws_port_{ 0 }; 97 | bool first_node_{ false }; 98 | bool client_mode_{ false }; 99 | std::string private_key_; 100 | std::string public_key_; 101 | std::string public_ip_; 102 | uint16_t public_port_{ 0 }; 103 | int32_t nat_type_{kNatTypeUnknown}; 104 | std::string idtype_; 105 | uint64_t service_type_{ kInvalidType }; 106 | uint32_t routing_table_id_{0}; 107 | uint32_t role_{ kRoleInvalid }; 108 | base::XipParserPtr xip_{std::make_shared()}; 109 | std::mutex kadkey_mutex_; 110 | base::KadmliaKeyPtr kadmlia_key_{ nullptr }; 111 | uint32_t score_; 112 | // key is node_id, value is dynamicxip distribute by node_id 113 | std::map node_dxip_map_; 114 | std::mutex node_dxip_map_mutex_; 115 | std::map dxip_node_map_; 116 | std::mutex dxip_node_map_mutex_; 117 | bool is_root_{ false }; 118 | uint64_t hash64_{ 0 }; 119 | kadmlia::NatManagerIntf* nat_manager_{kadmlia::NatManagerIntf::Instance()}; 120 | 121 | 122 | DISALLOW_COPY_AND_ASSIGN(LocalNodeInfo); 123 | }; 124 | 125 | typedef std::shared_ptr LocalNodeInfoPtr; 126 | 127 | } // namespace kadmlia 128 | 129 | } // namespace top 130 | -------------------------------------------------------------------------------- /src/local_node_info.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/local_node_info.h" 6 | 7 | #include 8 | 9 | #include "xbase/xhash.h" 10 | #include "common/xdfcurve.h" 11 | #include "common/xaes.h" 12 | #include "common/secp256k1.h" 13 | #include "common/sha2.h" 14 | 15 | #include "xpbase/base/rand_util.h" 16 | #include "xpbase/base/top_log.h" 17 | 18 | namespace top { 19 | 20 | namespace kadmlia { 21 | 22 | LocalNodeInfo::LocalNodeInfo() {} 23 | LocalNodeInfo::~LocalNodeInfo() {} 24 | 25 | bool LocalNodeInfo::Init( 26 | const std::string& local_ip, 27 | uint16_t local_port, 28 | bool first_node, 29 | bool client, 30 | const std::string& idtype, 31 | base::KadmliaKeyPtr kadmlia_key, 32 | uint64_t service_type, 33 | uint32_t role) { 34 | local_ip_ = local_ip; 35 | local_port_ = local_port; 36 | first_node_ = first_node; 37 | client_mode_ = client; 38 | idtype_ = idtype; 39 | kadmlia_key_ = kadmlia_key; 40 | xip_ = std::make_shared(kadmlia_key->Xip()); 41 | TOP_INFO("local_node_start: kad_key[%s]; xip[%s]", 42 | HexEncode(kad_key()).c_str(), 43 | HexEncode(xip_->xip()).c_str()); 44 | if (first_node_) { 45 | public_ip_ = local_ip_; 46 | public_port_ = local_port_; 47 | } 48 | if (!nat_manager_->GetLocalNatType(nat_type_) 49 | || nat_type_ == kNatTypeUnknown) { 50 | TOP_ERROR("bluenat get local nat type(%d) failed", nat_type_); 51 | return false; 52 | } 53 | service_type_ = kadmlia_key_->GetServiceType(); 54 | role_ = role; 55 | score_ = RandomUint32() % 100; 56 | hash64_ = base::xhash64_t::digest(global_xid->Get()); 57 | return true; 58 | } 59 | 60 | void LocalNodeInfo::Reset() { 61 | xip_ = nullptr; 62 | kadmlia_key_ = nullptr; 63 | local_ip_ = ""; 64 | local_port_ = 0; 65 | first_node_ = false; 66 | client_mode_ = false; 67 | private_key_ = ""; 68 | public_key_ = ""; 69 | public_ip_ = ""; 70 | public_port_ = 0; 71 | nat_type_ = kNatTypeUnknown; 72 | idtype_ = ""; 73 | role_ = kRoleInvalid; 74 | } 75 | 76 | bool LocalNodeInfo::IsPublicNode() const { 77 | return local_ip_ == public_ip_ && local_port_ == public_port_; 78 | } 79 | std::string LocalNodeInfo::kad_key() { 80 | return id(); 81 | } 82 | std::string LocalNodeInfo::xid() { return global_xid->Get(); } 83 | std::string LocalNodeInfo::xip() { return GetXipParser().xip(); } 84 | 85 | void LocalNodeInfo::set_xip(const std::string& xip_str) { 86 | base::XipParser xip(xip_str); 87 | *xip_ = xip; 88 | } 89 | 90 | std::string LocalNodeInfo::id() { 91 | assert(kadmlia_key_); 92 | std::lock_guard lock(kadkey_mutex_); 93 | return kadmlia_key_->Get(); 94 | } 95 | 96 | base::XipParser& LocalNodeInfo::GetXipParser() { 97 | if (client_mode_) { 98 | std::unique_lock lock(dxip_node_map_mutex_); 99 | base::XipParserPtr client_xip_ptr; 100 | if (dxip_node_map_.empty()) { 101 | client_xip_ptr.reset(new base::XipParser()); 102 | return *client_xip_ptr; 103 | } 104 | std::string client_random_self_dxip = dxip_node_map_.begin()->first; 105 | client_xip_ptr.reset(new base::XipParser(client_random_self_dxip)); 106 | return *client_xip_ptr; 107 | } 108 | return *xip_; 109 | }; 110 | 111 | void LocalNodeInfo::AddDxip(const std::string& node_id, const std::string& dxip) { 112 | { 113 | std::unique_lock lock(node_dxip_map_mutex_); 114 | node_dxip_map_[node_id] = dxip; 115 | } 116 | { 117 | std::unique_lock lock(dxip_node_map_mutex_); 118 | dxip_node_map_[dxip] = node_id; 119 | } 120 | } 121 | 122 | void LocalNodeInfo::DropDxip(const std::string& node_id) { 123 | std::string tmp_dxip; 124 | { 125 | std::unique_lock lock(node_dxip_map_mutex_); 126 | auto ifind = node_dxip_map_.find(node_id); 127 | if (ifind == node_dxip_map_.end()) { 128 | return; 129 | } 130 | tmp_dxip = ifind->second; 131 | node_dxip_map_.erase(ifind); 132 | TOP_DEBUG("dropdxip1: node(%s) dxip(%s)", 133 | HexSubstr(node_id).c_str(), 134 | HexEncode(tmp_dxip).c_str()); 135 | } 136 | { 137 | std::unique_lock lock(dxip_node_map_mutex_); 138 | auto ifind = dxip_node_map_.find(tmp_dxip); 139 | if (ifind != dxip_node_map_.end()) { 140 | dxip_node_map_.erase(ifind); 141 | TOP_DEBUG("dropdxip2: node(%s)", HexSubstr(node_id).c_str()); 142 | } 143 | } 144 | } 145 | 146 | 147 | bool LocalNodeInfo::HasDynamicXip(const std::string& dxip) { 148 | std::unique_lock lock(dxip_node_map_mutex_); 149 | auto ifind = dxip_node_map_.find(dxip); 150 | if (ifind != dxip_node_map_.end()) { 151 | return true; 152 | } 153 | return false; 154 | } 155 | 156 | } // namespace kadmlia 157 | 158 | } // namespace top 159 | -------------------------------------------------------------------------------- /src/heartbeat_state.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | 6 | // #include "xkad/routing_table/heartbeat_state.h" 7 | 8 | // #include 9 | // #include 10 | 11 | // #include 12 | // #include 13 | // #include 14 | // #include 15 | // #include 16 | // #include 17 | // #include 18 | // #include 19 | 20 | // #include "xpbase/base/top_log.h" 21 | // #include "xpbase/base/top_timer.h" 22 | // #include "xkad/routing_table/routing_utils.h" 23 | // #include "xtransport/proto/transport.pb.h" 24 | // #include "xkad/proto/kadmlia.pb.h" 25 | 26 | // namespace top { 27 | // namespace kadmlia { 28 | 29 | // typedef std::chrono::system_clock Clock; 30 | // typedef std::mutex Mutex; 31 | // typedef std::lock_guard Guard; 32 | // typedef std::function Callback; 33 | 34 | // class HeartbeatStateImpl : public HeartbeatState { 35 | // public: 36 | // explicit HeartbeatStateImpl(const std::string &type) { 37 | // Init(); 38 | // type_ = type; 39 | // } 40 | 41 | // // void Join() override { 42 | // // if (timer_ != nullptr) { 43 | // // timer_->close(); 44 | // // timer_->release_ref(); 45 | // // timer_ = nullptr; 46 | // // } 47 | 48 | // // if (iothread_ != nullptr) { 49 | // // iothread_->close(); 50 | // // iothread_->release_ref(); 51 | // // iothread_ = nullptr; 52 | // // } 53 | // // } 54 | 55 | // // req 56 | // void Send(const transport::protobuf::RoutingMessage& message, const std::string& peer_ip, 57 | // uint16_t peer_port) override { 58 | // if (message.type() != kKadHeartbeatRequest && 59 | // message.type() != kKadHeartbeatResponse) 60 | // return; 61 | 62 | // static bool flag_message_size = false; 63 | // if (!flag_message_size) { 64 | // flag_message_size = true; 65 | // TOP_INFO("[ht_state] heartbeat request message size: %d bytes", 66 | // static_cast(message.ByteSizeLong())); 67 | // } 68 | 69 | // Guard guard(mutex_); 70 | // ++sum_1_; 71 | // } 72 | 73 | // void Recv(const transport::protobuf::RoutingMessage& message) { 74 | // if (message.type() != kKadHeartbeatRequest && 75 | // message.type() != kKadHeartbeatResponse) 76 | // return; 77 | 78 | // static bool flag_message_size = false; 79 | // if (!flag_message_size) { 80 | // flag_message_size = true; 81 | // TOP_INFO("[ht_state] heartbeat response message size: %d bytes", 82 | // static_cast(message.ByteSizeLong())); 83 | // } 84 | 85 | // Guard guard(mutex_); 86 | // ++sum_1_; 87 | // } 88 | 89 | // void DumpAndReset_1() { 90 | // TOP_DEBUG("[ht_state] %s sum_1: %d", type_.c_str(), sum_1_); 91 | // sum_1_ = 0; 92 | // } 93 | 94 | // void DumpAndReset_5() { 95 | // if (n_calls_ > 0 && n_calls_ % 5 == 0) { 96 | // TOP_DEBUG("[ht_state] %s sum_5: %d", type_.c_str(), sum_5_); 97 | // sum_5_ = 0; 98 | // } 99 | // } 100 | 101 | // void DumpAndReset_30() { 102 | // if (n_calls_ > 0 && n_calls_ % 30 == 0) { 103 | // TOP_DEBUG("[ht_state] %s sum_30: %d", type_.c_str(), sum_30_); 104 | // sum_30_ = 0; 105 | // } 106 | // } 107 | 108 | // private: 109 | // void TimerProc() { 110 | // Guard guard(mutex_); 111 | // // sum_1_ 112 | // sum_5_ += sum_1_; 113 | // sum_30_ += sum_1_; 114 | // ++n_calls_; 115 | 116 | // // TOP_INFO("[ht_state] ========== begin ========== "); 117 | // DumpAndReset_1(); 118 | // DumpAndReset_5(); 119 | // DumpAndReset_30(); 120 | // // TOP_INFO("[ht_state] ========== end ========== "); 121 | // } 122 | 123 | // // init 124 | // void Init() { 125 | // TOP_INFO("[ht_state] initing ..."); 126 | 127 | // timer_->Start( 128 | // 10 * 1000, 1000 * 1000, 129 | // std::bind(&HeartbeatStateImpl::TimerProc, this)); 130 | // TOP_INFO("[ht_state] inited"); 131 | // } 132 | 133 | // private: 134 | // Mutex mutex_; 135 | // std::string type_; 136 | // int n_calls_{0}; 137 | // int sum_1_{0}; // 1 unit 138 | // int sum_5_{0}; // 5 units 139 | // int sum_30_{0}; // 30 units 140 | 141 | // std::shared_ptr timer_{std::make_shared()}; 142 | // }; 143 | 144 | // HeartbeatState& HeartbeatState::Instance() { 145 | // static HeartbeatStateImpl ins("send"); 146 | // return ins; 147 | // } 148 | 149 | // class HeartbeatStateRecvImpl : public HeartbeatStateRecv { 150 | // public: 151 | // void Recv(const transport::protobuf::RoutingMessage& message) override { 152 | // recv_state_.Recv(message); 153 | // } 154 | // // void Join() override { 155 | // // recv_state_.Join(); 156 | // // } 157 | 158 | // private: 159 | // HeartbeatStateImpl recv_state_{"recv"}; 160 | // }; 161 | 162 | // HeartbeatStateRecv& HeartbeatStateRecv::Instance() { 163 | // static HeartbeatStateRecvImpl ins; 164 | // return ins; 165 | // } 166 | 167 | // } // namespace kadmlia 168 | // } // namespace top 169 | -------------------------------------------------------------------------------- /src/bootstrap_cache.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/bootstrap_cache.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "xpbase/base/top_log.h" 13 | #include "xkad/routing_table/routing_utils.h" 14 | #include "xkad/proto/ledger.pb.h" 15 | 16 | namespace top { 17 | namespace kadmlia { 18 | 19 | BootstrapCachePtr GetBootstrapCache(uint64_t service_type) { 20 | return BootstrapCacheManager::Instance()->GetBootStrapCache(service_type); 21 | } 22 | 23 | BootstrapCacheManager* BootstrapCacheManager::Instance() { 24 | static BootstrapCacheManager ins; 25 | static std::once_flag s_flag; 26 | std::call_once(s_flag, []{ 27 | if (!ins.Init()) { 28 | assert(0); 29 | } 30 | }); 31 | 32 | return &ins; 33 | } 34 | 35 | BootstrapCache::BootstrapCache() {} 36 | BootstrapCache::~BootstrapCache() {} 37 | 38 | bool BootstrapCache::GetCache(VecBootstrapEndpoint& vec_bootstrap_endpoint) { 39 | return manager_->GetCache(service_type_, vec_bootstrap_endpoint); 40 | } 41 | 42 | bool BootstrapCache::SetCache(const VecBootstrapEndpoint& vec_bootstrap_endpoint) { 43 | return manager_->SetCache(service_type_, vec_bootstrap_endpoint); 44 | } 45 | 46 | BootstrapCacheManager::BootstrapCacheManager() {} 47 | BootstrapCacheManager::~BootstrapCacheManager() {} 48 | 49 | bool BootstrapCacheManager::Init() { 50 | TOP_INFO("BootstrapCacheManager::Init() ..."); 51 | Lock lock(mutex_); 52 | if (inited_) { 53 | TOP_INFO("inited before"); 54 | return true; 55 | } 56 | 57 | inited_ = true; 58 | TOP_INFO("BootstrapCacheManager::Init() success"); 59 | return true; 60 | } 61 | 62 | BootstrapCachePtr BootstrapCacheManager::GetBootStrapCache(uint64_t service_type) { 63 | Lock lock(mutex_); 64 | assert(inited_); 65 | 66 | auto it = map_.find(service_type); 67 | if (it != map_.end()) 68 | return it->second; 69 | 70 | auto ptr = std::make_shared(); 71 | ptr->service_type_ = service_type; 72 | ptr->manager_ = this; 73 | map_[service_type] = ptr; 74 | TOP_INFO("create bootstrap cache[%llu]", (int)service_type); 75 | return ptr; 76 | } 77 | 78 | // size 79 | // static std::string ToString(const VecBootstrapEndpoint& vec_bootstrap_endpoint) { 80 | // top::kadmlia::pb::PbBootstrapCache pb_cache; 81 | // for (const auto& ep : vec_bootstrap_endpoint) { 82 | // auto pb_ep = pb_cache.add_endpoints(); 83 | // pb_ep->set_ip(ep.first); 84 | // pb_ep->set_port(ep.second); 85 | // } 86 | // std::string ret; 87 | // assert(pb_cache.SerializeToString(&ret)); 88 | // return ret; 89 | // } 90 | 91 | // static bool ToVecBootstrapEndpoint(const std::string& str, VecBootstrapEndpoint& vec_bootstrap_endpoint) { 92 | // top::kadmlia::pb::PbBootstrapCache pb_cache; 93 | // if (!pb_cache.ParseFromString(str)) { 94 | // TOP_ERROR("cache.ParseFromString failed"); 95 | // return false; 96 | // } 97 | 98 | // vec_bootstrap_endpoint.clear(); 99 | // for (int i = 0; i < pb_cache.endpoints_size(); ++i) { 100 | // const auto& pb_ep = pb_cache.endpoints(i); 101 | // if (pb_ep.port() > std::numeric_limits::max()) { 102 | // TOP_WARN("ignore invalid endpoint(%s:%d)", pb_ep.ip().c_str(), (int)pb_ep.port()); 103 | // continue; 104 | // } 105 | // vec_bootstrap_endpoint.push_back(std::make_pair(pb_ep.ip(), (uint16_t)pb_ep.port())); 106 | // } 107 | 108 | // return true; 109 | // } 110 | 111 | bool BootstrapCacheManager::SetCache(uint64_t service_type, const VecBootstrapEndpoint& vec_bootstrap_endpoint) { 112 | // Lock lock(mutex_); 113 | // assert(inited_); 114 | // 115 | // const std::string field = std::to_string(service_type); 116 | // const std::string value = ToString(vec_bootstrap_endpoint); 117 | // const auto ret = top::storage::XLedgerDB::Instance()->map_set( 118 | // top::kadmlia::BOOTSTRAP_CACHE_DB_KEY, 119 | // field, 120 | // value); 121 | // if (ret != top::ledger::ok) { 122 | // TOP_ERROR("ledger map_set(%s, %s) failed, ret=%d", 123 | // top::kadmlia::BOOTSTRAP_CACHE_DB_KEY.c_str(), 124 | // field.c_str(), 125 | // ret); 126 | // return false; 127 | // } 128 | 129 | return true; 130 | } 131 | 132 | bool BootstrapCacheManager::GetCache(uint64_t service_type, VecBootstrapEndpoint& vec_bootstrap_endpoint) { 133 | // Lock lock(mutex_); 134 | // assert(inited_); 135 | // 136 | // const std::string field = std::to_string(service_type); 137 | // std::string value; 138 | // const auto ret = top::storage::XLedgerDB::Instance()->map_get( 139 | // top::kadmlia::BOOTSTRAP_CACHE_DB_KEY, 140 | // field, 141 | // value); 142 | // if (ret != top::ledger::ok) { 143 | // TOP_ERROR("ledger map_get(%s, %s) failed, ret=%d", 144 | // top::kadmlia::BOOTSTRAP_CACHE_DB_KEY.c_str(), 145 | // field.c_str(), 146 | // ret); 147 | // return false; 148 | // } 149 | // 150 | // if (!ToVecBootstrapEndpoint(value, vec_bootstrap_endpoint)) { 151 | // TOP_ERROR("parse vec_bootstrap_endpoint from value failed"); 152 | // return false; 153 | // } 154 | 155 | return true; 156 | } 157 | 158 | } // namespace kadmlia 159 | } // namespace top 160 | -------------------------------------------------------------------------------- /src/callback_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/callback_manager.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "xbase/xpacket.h" 11 | #include "xpbase/base/top_utils.h" 12 | #include "xpbase/base/top_log.h" 13 | #include "xkad/routing_table/routing_table.h" 14 | 15 | namespace top { 16 | 17 | namespace kadmlia { 18 | 19 | static const int32_t kTimeCheckoutPeriod = 1000 * 1000; // 1s 20 | 21 | CallbackItem::~CallbackItem() {} 22 | 23 | std::atomic CallbackManager::msg_id_(time(0)); 24 | 25 | uint32_t CallbackManager::MessageId() { 26 | return ++msg_id_; 27 | } 28 | 29 | CallbackManager::CallbackManager() 30 | : callback_map_(), 31 | callback_map_mutex_() { 32 | timer_.CallAfter(kTimeCheckoutPeriod, std::bind(&CallbackManager::TimeoutCheck, this)); 33 | } 34 | 35 | CallbackManager::~CallbackManager() { 36 | Join(); 37 | TOP_INFO("CallbackManager thread joined!"); 38 | } 39 | 40 | CallbackManager* CallbackManager::Instance() { 41 | static CallbackManager ins; 42 | return &ins; 43 | } 44 | 45 | void CallbackManager::Join() { 46 | timer_.Join(); 47 | { 48 | std::unique_lock lock(callback_map_mutex_); 49 | callback_map_.clear(); 50 | } 51 | } 52 | 53 | void CallbackManager::Add( 54 | uint32_t message_id, 55 | int32_t timeout_sec, 56 | ResponseFunctor callback, 57 | int32_t expect_count) { 58 | CallbackItemPtr item_ptr; 59 | item_ptr.reset(new CallbackItem{ 60 | message_id, callback, nullptr, 61 | timeout_sec, expect_count, nullptr, nullptr }); 62 | std::unique_lock lock(callback_map_mutex_); 63 | callback_map_.insert(std::make_pair(message_id, item_ptr)); 64 | } 65 | 66 | void CallbackManager::Add(CallbackItemPtr callback_ptr) { 67 | if (!callback_ptr) { 68 | return; 69 | } 70 | 71 | std::unique_lock lock(callback_map_mutex_); 72 | callback_map_.insert(std::make_pair(callback_ptr->message_id, callback_ptr)); 73 | } 74 | 75 | void CallbackManager::Callback( 76 | uint32_t message_id, 77 | transport::protobuf::RoutingMessage& message, 78 | base::xpacket_t& packet) { 79 | CallbackItemPtr item_ptr; 80 | { 81 | std::unique_lock lock(callback_map_mutex_); 82 | auto iter = callback_map_.find(message_id); 83 | if (iter == callback_map_.end()) { 84 | return; 85 | } 86 | 87 | item_ptr = iter->second; 88 | iter->second->expect_count--; 89 | if (iter->second->expect_count <= 0) { 90 | callback_map_.erase(iter); 91 | } 92 | } 93 | 94 | if (item_ptr) { 95 | if (item_ptr->callback) { 96 | item_ptr->callback(kKadSuccess, message, packet); 97 | } 98 | 99 | if (item_ptr->mutex_callback) { 100 | item_ptr->mutex_callback( 101 | kKadSuccess, 102 | message, 103 | packet, 104 | item_ptr->wait_mutex, 105 | item_ptr->wait_condition); 106 | } 107 | } 108 | } 109 | 110 | void CallbackManager::Timeout(uint32_t message_id) { 111 | Cancel(message_id, 0); 112 | } 113 | 114 | // if no_callback is 0, call callback. if no_callback is 1, do not call callback 115 | void CallbackManager::Cancel(uint32_t message_id, uint32_t no_callback) { 116 | ResponseFunctor callback; 117 | CallbackItemPtr mutex_callback_item; 118 | int32_t expect_count = 0; 119 | { 120 | std::unique_lock lock(callback_map_mutex_); 121 | auto iter = callback_map_.find(message_id); 122 | if (iter == callback_map_.end()) { 123 | return; 124 | } 125 | 126 | callback = iter->second->callback; 127 | mutex_callback_item = iter->second; 128 | expect_count = iter->second->expect_count; 129 | callback_map_.erase(iter); 130 | } 131 | 132 | if (no_callback != 0) 133 | return; 134 | if (callback) { 135 | transport::protobuf::RoutingMessage message; 136 | message.set_id(message_id); 137 | base::xpacket_t packet; 138 | for (int i = 0; i < expect_count; ++i) { 139 | callback(kKadTimeout, message, packet); 140 | } 141 | } 142 | 143 | if (mutex_callback_item->mutex_callback) { 144 | transport::protobuf::RoutingMessage message; 145 | base::xpacket_t packet; 146 | for (int i = 0; i < expect_count; ++i) { 147 | mutex_callback_item->mutex_callback( 148 | kKadTimeout, 149 | message, 150 | packet, 151 | mutex_callback_item->wait_mutex, 152 | mutex_callback_item->wait_condition); 153 | } 154 | } 155 | } 156 | 157 | void CallbackManager::TimeoutCheck() { 158 | std::vector message_vec; 159 | { 160 | std::unique_lock lock(callback_map_mutex_); 161 | for (auto iter = callback_map_.begin(); iter != callback_map_.end(); ++iter) { 162 | iter->second->timeout_sec--; 163 | if (iter->second->timeout_sec <= 0) { 164 | message_vec.push_back(iter->first); 165 | } 166 | } 167 | } 168 | 169 | for (uint32_t i = 0; i < message_vec.size(); ++i) { 170 | Timeout(message_vec[i]); 171 | } 172 | timer_.CallAfter(kTimeCheckoutPeriod, std::bind(&CallbackManager::TimeoutCheck, this)); 173 | } 174 | 175 | } // namespace kadmlia 176 | 177 | } // namespace top 178 | -------------------------------------------------------------------------------- /src/nat_handshake_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/nat_detect/nat_handshake_manager.h" 6 | 7 | #include "xbase/xutl.h" 8 | 9 | #include "xpbase/base/top_utils.h" 10 | #include "xkad/routing_table/callback_manager.h" 11 | #include "xtransport/proto/transport.pb.h" 12 | #include "xkad/proto/kadmlia.pb.h" 13 | // #include "xkad/nat_detect/nat_log.h" 14 | #include "xpbase/base/top_log_name.h" 15 | 16 | namespace top { 17 | namespace kadmlia { 18 | 19 | static const int32_t kDetectionPeriod = 50; // 50ms 20 | static const int32_t kDetectCount = 2000 / kDetectionPeriod; // max: 2000ms 21 | 22 | void NatHandshakeManager::SetName(const std::string& name) { 23 | name_ = name; 24 | } 25 | 26 | NatHandshakeManager::NatHandshakeManager(base::TimerManager* timer_manager) { 27 | TOP_WARN_NAME("NatHandshakeManager"); 28 | timer_manager_ = timer_manager; 29 | } 30 | 31 | NatHandshakeManager::~NatHandshakeManager() { 32 | TOP_WARN_NAME("~NatHandshakeManager ..."); 33 | Stop(); 34 | TOP_WARN_NAME("~NatHandshakeManager"); 35 | } 36 | 37 | void NatHandshakeManager::AddDetection( 38 | const std::string& ip, 39 | uint16_t port, 40 | transport::Transport* transport, 41 | uint16_t detect_port, 42 | int32_t message_type, 43 | int32_t delay_ms) { 44 | assert(transport); 45 | const auto delay_count = delay_ms / kDetectionPeriod; 46 | TOP_INFO_NAME("add nat detection(%s:%d, detect_port=%d, message_type=%d, delay_ms=%d(%d)", 47 | ip.c_str(), (int)port, (int)detect_port, message_type, delay_ms, delay_count); 48 | const std::string key = ip + "_" + std::to_string(port); 49 | auto ptr = std::make_shared(); 50 | ptr->ip = ip; 51 | ptr->port = port; 52 | ptr->transport = transport; 53 | ptr->detect_port = detect_port; 54 | ptr->message_type = message_type; 55 | ptr->delay_count = delay_count; 56 | ptr->detect_count = kDetectCount; 57 | 58 | std::unique_lock lock(mutex_); 59 | peers_[key] = ptr; // overlap old one 60 | } 61 | 62 | void NatHandshakeManager::RemoveDetection(const std::string& ip, uint16_t port) { 63 | TOP_INFO_NAME("remove nat detection(%s:%d)", 64 | ip.c_str(), (int)port); 65 | const std::string key = ip + "_" + std::to_string(port); 66 | std::unique_lock lock(mutex_); 67 | peers_.erase(key); 68 | } 69 | 70 | bool NatHandshakeManager::Start() { 71 | TOP_INFO_NAME("starting ..."); 72 | std::unique_lock lock(mutex_); 73 | if (started_) { 74 | TOP_INFO_NAME("start before"); 75 | return true; 76 | } 77 | 78 | peers_.clear(); 79 | timer_ = std::make_shared(timer_manager_, "NatHandshakeManager"); 80 | timer_->Start( 81 | kDetectionPeriod * 1000, 82 | kDetectionPeriod * 1000, 83 | std::bind(&NatHandshakeManager::DetectProc, this)); 84 | started_ = true; 85 | TOP_INFO_NAME("start success"); 86 | return true; 87 | } 88 | 89 | void NatHandshakeManager::Stop() { 90 | TOP_INFO_NAME("stopping ..."); 91 | std::unique_lock lock(mutex_); 92 | if (!started_) { 93 | TOP_INFO_NAME("haven't started"); 94 | return; 95 | } 96 | 97 | if (timer_) { 98 | timer_->Join(); 99 | } 100 | 101 | started_ = false; 102 | TOP_INFO_NAME("stop success"); 103 | } 104 | 105 | int NatHandshakeManager::DoHandshake( 106 | transport::Transport* transport, 107 | const std::string& peer_ip, 108 | uint16_t detect_port, 109 | int32_t message_type) { 110 | transport::protobuf::RoutingMessage message; 111 | // message.set_src_service_type(service_type_); 112 | // message.set_des_service_type(kRoot); 113 | message.set_hop_num(0); 114 | message.set_src_node_id(""); 115 | message.set_des_node_id(""); 116 | message.set_type(message_type); 117 | message.set_id(CallbackManager::MessageId()); 118 | message.set_is_root(true); 119 | 120 | TOP_WARN_NAME("send handshake(%d) to peer(%s:%d)", 121 | message_type, 122 | peer_ip.c_str(), (int)detect_port); 123 | 124 | std::string msg; 125 | if (!message.SerializeToString(&msg)) { 126 | TOP_INFO("RoutingMessage SerializeToString failed!"); 127 | return kKadFailed; 128 | } 129 | xbyte_buffer_t xdata{msg.begin(), msg.end()}; 130 | return transport->SendPing(xdata, peer_ip, detect_port); 131 | } 132 | 133 | void NatHandshakeManager::DetectProc() { 134 | std::map> peers; 135 | { 136 | std::unique_lock lock(mutex_); 137 | peers = peers_; // yes, copy! 138 | if (peers_.size() > 1000) { 139 | TOP_WARN_NAME("detection peers_ size: %d", (int)peers_.size()); 140 | } 141 | } 142 | 143 | for (auto& kv : peers) { 144 | auto& st = *kv.second; 145 | if (st.delay_count > 0) { 146 | st.delay_count -= 1; 147 | continue; 148 | } 149 | 150 | if (st.detect_count > 0) { 151 | DoHandshake(st.transport, st.ip, st.detect_port, st.message_type); 152 | st.detect_count -= 1; 153 | } 154 | 155 | if (st.detect_count <= 0) { 156 | TOP_INFO_NAME("stop handshake(%d) to peer(%s:%d)", 157 | st.message_type, 158 | st.ip.c_str(), (int)st.detect_port); 159 | std::unique_lock lock(mutex_); 160 | peers_.erase(kv.first); 161 | } 162 | } 163 | } 164 | 165 | } // namespace kadmlia 166 | } // namespace top 167 | -------------------------------------------------------------------------------- /tests/test_callback_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "xbase/xpacket.h" 12 | #define private public 13 | #include "xkad/routing_table/callback_manager.h" 14 | 15 | namespace top { 16 | 17 | namespace kadmlia { 18 | 19 | namespace test { 20 | 21 | class TestCallbackManager : public testing::Test { 22 | public: 23 | static void SetUpTestCase() { 24 | 25 | } 26 | 27 | static void TearDownTestCase() { 28 | } 29 | 30 | virtual void SetUp() { 31 | } 32 | 33 | virtual void TearDown() { 34 | } 35 | }; 36 | 37 | TEST_F(TestCallbackManager, Init) { 38 | CallbackManager callback_mgr; 39 | } 40 | 41 | TEST_F(TestCallbackManager, Add1) { 42 | CallbackManager callback_mgr; 43 | callback_mgr.Add(1, 5, nullptr, 1); 44 | auto iter = callback_mgr.callback_map_.find(1); 45 | ASSERT_FALSE(iter == callback_mgr.callback_map_.end()); 46 | } 47 | 48 | TEST_F(TestCallbackManager, Add2) { 49 | CallbackManager callback_mgr; 50 | CallbackItemPtr item_ptr; 51 | item_ptr.reset(new CallbackItem{ 2, NULL, nullptr, 4, 1, nullptr, nullptr }); 52 | callback_mgr.Add(item_ptr); 53 | auto iter = callback_mgr.callback_map_.find(2); 54 | ASSERT_FALSE(iter == callback_mgr.callback_map_.end()); 55 | } 56 | 57 | TEST_F(TestCallbackManager, Callback1) { 58 | CallbackManager callback_mgr; 59 | 60 | std::mutex mutex; 61 | std::condition_variable cond_var; 62 | int called_times = 0; 63 | auto callback = [&called_times]( 64 | int status, transport::protobuf::RoutingMessage & tmp_message, base::xpacket_t& packet) { 65 | ++called_times; 66 | }; 67 | callback_mgr.Add(1, 5, callback, 5); 68 | auto iter = callback_mgr.callback_map_.find(1); 69 | ASSERT_FALSE(iter == callback_mgr.callback_map_.end()); 70 | top::transport::protobuf::RoutingMessage message; 71 | base::xpacket_t packet; 72 | callback_mgr.Callback(1, message, packet); 73 | callback_mgr.Callback(1, message, packet); 74 | callback_mgr.Callback(1, message, packet); 75 | callback_mgr.Callback(1, message, packet); 76 | callback_mgr.Callback(1, message, packet); 77 | callback_mgr.Callback(1, message, packet); 78 | callback_mgr.Callback(1, message, packet); 79 | ASSERT_EQ(called_times, 5); 80 | } 81 | 82 | TEST_F(TestCallbackManager, Callback2) { 83 | CallbackManager callback_mgr; 84 | std::shared_ptr pmutex = std::make_shared(); 85 | std::shared_ptr cond_var = std::make_shared(); 86 | int called_times = 0; 87 | auto callback = [&called_times]( 88 | int status, 89 | transport::protobuf::RoutingMessage& tmp_message, 90 | base::xpacket_t& packet, 91 | std::shared_ptr pmutex, 92 | std::shared_ptr cond_var) { 93 | ++called_times; 94 | }; 95 | CallbackItemPtr item_ptr; 96 | item_ptr.reset(new CallbackItem{ 2, NULL, callback, 4, 5, pmutex, cond_var }); 97 | callback_mgr.Add(item_ptr); 98 | auto iter = callback_mgr.callback_map_.find(2); 99 | ASSERT_FALSE(iter == callback_mgr.callback_map_.end()); 100 | top::transport::protobuf::RoutingMessage message; 101 | base::xpacket_t packet; 102 | callback_mgr.Callback(2, message, packet); 103 | callback_mgr.Callback(2, message, packet); 104 | callback_mgr.Callback(2, message, packet); 105 | callback_mgr.Callback(2, message, packet); 106 | callback_mgr.Callback(2, message, packet); 107 | callback_mgr.Callback(2, message, packet); 108 | callback_mgr.Callback(2, message, packet); 109 | callback_mgr.Callback(2, message, packet); 110 | ASSERT_EQ(called_times, 5); 111 | } 112 | 113 | TEST_F(TestCallbackManager, Timeout1) { 114 | CallbackManager callback_mgr; 115 | 116 | std::mutex mutex; 117 | std::condition_variable cond_var; 118 | auto callback = []( 119 | int status, transport::protobuf::RoutingMessage & tmp_message, base::xpacket_t& packet) {}; 120 | callback_mgr.Add(1, 5, callback, 1); 121 | auto iter = callback_mgr.callback_map_.find(1); 122 | ASSERT_FALSE(iter == callback_mgr.callback_map_.end()); 123 | top::transport::protobuf::RoutingMessage message; 124 | base::xpacket_t packet; 125 | callback_mgr.Timeout(1); 126 | } 127 | 128 | TEST_F(TestCallbackManager, Timeout2) { 129 | CallbackManager callback_mgr; 130 | std::shared_ptr pmutex = std::make_shared(); 131 | std::shared_ptr cond_var = std::make_shared(); 132 | // int res = kKadFailed; 133 | auto callback = []( 134 | int status, 135 | transport::protobuf::RoutingMessage& tmp_message, 136 | base::xpacket_t& packet, 137 | std::shared_ptr pmutex, 138 | std::shared_ptr cond_var) {}; 139 | CallbackItemPtr item_ptr; 140 | item_ptr.reset(new CallbackItem{ 2, NULL, callback, 4, 1, pmutex, cond_var }); 141 | callback_mgr.Add(item_ptr); 142 | auto iter = callback_mgr.callback_map_.find(2); 143 | ASSERT_FALSE(iter == callback_mgr.callback_map_.end()); 144 | top::transport::protobuf::RoutingMessage message; 145 | base::xpacket_t packet; 146 | callback_mgr.Timeout(2); 147 | } 148 | 149 | TEST_F(TestCallbackManager, Instance) { 150 | ASSERT_NE(nullptr, CallbackManager::Instance()); 151 | } 152 | 153 | TEST_F(TestCallbackManager, TimeoutCheck) { 154 | CallbackManager callback_mgr; 155 | callback_mgr.TimeoutCheck(); 156 | } 157 | 158 | 159 | } // namespace test 160 | 161 | } // namespace kadmlia 162 | 163 | } // namespace top 164 | -------------------------------------------------------------------------------- /proto/kadmlia.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package top.kadmlia.protobuf; 4 | 5 | message TestMultiRelayRequest { 6 | optional bytes ping = 1; 7 | } 8 | 9 | message TestMultiRelayResponse { 10 | optional bytes pong = 1; 11 | } 12 | 13 | message ConnectReq { 14 | optional bytes local_ip = 1; 15 | optional int32 local_port = 2; 16 | optional bytes public_ip = 3; 17 | optional int32 public_port = 4; 18 | optional int32 nat_type = 5; 19 | optional bytes relay_routing_id = 6; 20 | } 21 | 22 | message ConnectRes { 23 | optional bytes public_ip = 1; 24 | optional int32 public_port = 2; 25 | optional bytes local_ip = 3; 26 | optional int32 local_port = 4; 27 | optional int32 nat_type = 5; 28 | } 29 | 30 | message BootstrapJoinRequest { 31 | optional bytes local_ip = 1; 32 | optional int32 local_port = 2; 33 | optional bool client_mode = 3; 34 | optional int32 nat_type = 4; 35 | optional bytes xid = 5; 36 | optional bytes xip = 6; 37 | } 38 | 39 | message BootstrapJoinResponse { 40 | optional bytes public_ip = 1; 41 | optional int32 public_port = 2; 42 | optional bytes bootstrap_id = 3; 43 | optional int32 nat_type = 4; 44 | optional bytes xid = 5; 45 | // bootstrap node self xip 46 | optional bytes xip = 6; 47 | // bootsrap node dispatch dynamic xip for "client" node 48 | optional bytes dxip = 7; 49 | } 50 | 51 | message NatDetectRequest { 52 | optional bytes local_ip = 1; 53 | optional int32 local_port = 2; 54 | } 55 | 56 | message NatDetectResponse { 57 | optional int32 nat_type = 1; 58 | optional int32 detect_port = 2; // node -> boot.detect_port 59 | } 60 | 61 | message NatDetectFinish { // to boot for stop detection! 62 | optional int32 resv = 1; 63 | } 64 | 65 | message NatDetectHandshake2Node { 66 | optional int32 resv = 1; 67 | } 68 | 69 | message NatDetectHandshake2Boot { 70 | optional int32 resv = 1; 71 | } 72 | 73 | message Handshake { 74 | optional bytes local_ip = 1; 75 | optional int32 local_port = 2; 76 | optional int32 type = 3; 77 | optional bytes public_ip = 4; 78 | optional int32 public_port = 5; 79 | optional int32 nat_type = 6; 80 | optional bytes xid = 7; 81 | optional bytes xip = 8; 82 | } 83 | 84 | message NodeInfo { 85 | optional bytes public_ip = 1; 86 | optional int32 public_port = 2; 87 | optional bytes local_ip = 3; 88 | optional int32 local_port = 4; 89 | optional bytes id = 5; 90 | optional int32 nat_type = 6; 91 | optional bytes xip = 7; 92 | optional bytes xid = 8; 93 | } 94 | 95 | message Heartbeat { 96 | map extinfo_map = 1; 97 | } 98 | 99 | message FindClosestNodesRequest { 100 | optional uint32 count = 1; 101 | optional bytes target_id = 2; 102 | repeated uint64 bloomfilter = 3; 103 | optional NodeInfo src_nodeinfo = 4; 104 | } 105 | 106 | message FindClosestNodesResponse { 107 | repeated NodeInfo nodes = 1; 108 | } 109 | 110 | message GetNearestNodesRequest { 111 | optional bytes target_id = 1; 112 | optional uint32 count = 2; 113 | } 114 | 115 | message GetNearestNodesResponse { 116 | repeated NodeInfo nodes = 1; 117 | } 118 | 119 | message UdpNatDetectRequest { 120 | optional uint32 resv = 1; 121 | } 122 | 123 | message UdpNatDetectResponse { 124 | optional bytes public_ip = 1; 125 | optional int32 public_port = 2; 126 | } 127 | 128 | message EdgeNodesRequest { 129 | optional bytes target_id = 1; 130 | optional uint32 count = 2; 131 | } 132 | 133 | message EdgeNodesResponse { 134 | repeated NodeInfo nodes = 1; 135 | } 136 | 137 | message AddressInfo { 138 | optional bytes public_ip = 1; 139 | optional uint32 public_port = 2; 140 | optional uint32 local_port = 3; 141 | optional bytes detect_local_ip = 4; 142 | optional uint32 detect_local_port = 5; 143 | } 144 | 145 | message EdgeInfoRequest { 146 | map client_info = 1; 147 | optional int32 nat_type = 2; 148 | } 149 | 150 | message EdgeInfoResponse { 151 | map edge_info = 1; 152 | optional int32 nat_type = 2; 153 | } 154 | 155 | message GetAllNodesFromBootRequest { 156 | optional int32 start_pos = 1; 157 | optional int32 len = 2; 158 | } 159 | 160 | message GetAllNodesFromBootResponse { 161 | repeated NodeInfo nodes = 1; 162 | } 163 | //used for data transfer 164 | message SmartObjectData { 165 | optional uint32 type = 1; 166 | optional uint32 oper = 2; 167 | optional bytes key = 3; 168 | optional bytes value = 4; 169 | optional bytes field = 5; 170 | repeated bytes list_value = 6; 171 | optional uint32 ttl = 7; 172 | optional bytes public_key = 8; 173 | optional bytes aes_key = 9; 174 | optional uint32 encrypt_mode = 10; 175 | } 176 | //used for data refresh 177 | message SmartObjectTuple { 178 | optional uint32 type = 1; 179 | optional bytes key = 2; 180 | optional bytes value = 3; 181 | optional bytes field = 4; 182 | repeated bytes list_value = 5; 183 | optional uint64 save_time = 6; 184 | optional uint32 ttl = 7; 185 | } 186 | //used for data refresh 187 | message SmartObjectRefreshData { 188 | optional uint32 oper = 1; 189 | repeated SmartObjectTuple list_tuple = 2; 190 | } 191 | //used for each data block 192 | message SmartObjectDataBlock { 193 | optional uint32 id = 1; 194 | optional bytes block_hash = 2; 195 | optional bytes data = 3; 196 | } 197 | //used for sync data 198 | message SmartObjectSyncData { 199 | optional uint32 type = 1; 200 | optional bytes key = 2; 201 | optional bytes version = 3; 202 | optional bytes root_hash = 4; 203 | optional bytes sync_node = 5; 204 | repeated SmartObjectDataBlock list_block = 6; 205 | } 206 | 207 | message RootGetNodesRequest { 208 | optional bytes id = 1; 209 | optional uint32 count = 2; 210 | } 211 | 212 | message RootGetNodesResponse { 213 | repeated NodeInfo nodes = 1; 214 | } 215 | 216 | message RootMessage { 217 | optional uint32 message_type = 1; 218 | optional bytes data = 2; 219 | } 220 | 221 | -------------------------------------------------------------------------------- /routing_table/routing_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "xpbase/base/top_utils.h" 16 | #include "xpbase/base/error_code.h" 17 | #include "xpbase/base/top_string_util.h" 18 | #include "xpbase/base/top_config.h" 19 | #include "xpbase/base/xip_parser.h" 20 | #include "xpbase/base/kad_key/kadmlia_key.h" 21 | 22 | namespace top { 23 | 24 | namespace kadmlia { 25 | 26 | class LocalNodeInfo; 27 | typedef std::shared_ptr LocalNodeInfoPtr; 28 | 29 | enum RoutingMessageRequestType { 30 | kNone = 0, 31 | kRequestMsg, 32 | kResponseMsg, 33 | }; 34 | 35 | enum HandshakeType { 36 | kHandshakeRequest = 1, 37 | kHandshakeResponse = 2, 38 | }; 39 | 40 | enum RelayMessageCode { 41 | kErrorReturn = 1, 42 | kSuccessReturn, 43 | kContinue, 44 | }; 45 | 46 | /* 47 | enum RoutingMessageType { 48 | kKadConnectRequest = 0, 49 | kKadConnectResponse = 1, 50 | kKadHandshake = 2, 51 | kKadBootstrapJoinRequest = 3, 52 | kKadBootstrapJoinResponse = 4, 53 | kKadFindNodesRequest = 5, 54 | kKadFindNodesResponse = 6, 55 | kKadAck = 7, 56 | kKadHeartbeatRequest = 8, 57 | kKadHeartbeatResponse = 9, 58 | 59 | kKadNatDetectRequest = 23, 60 | kKadNatDetectResponse = 24, 61 | kKadNatDetectHandshake2Node = 25, 62 | kKadNatDetectHandshake2Boot = 26, 63 | kKadNatDetectFinish = 27, 64 | kKadDropNodeRequest = 28, 65 | kKadMessageTypeMax, // other message mast bigger than it 66 | }; 67 | */ 68 | 69 | enum VpnProtocal { 70 | kTcp = 8080, 71 | kXtcp = 14550, 72 | kSsl1 = 443, 73 | kSsl = 465, 74 | kHttp = 80, 75 | kTdns = 533, 76 | 77 | kUdp = 500, 78 | kXudp = 18721, 79 | kDns = 53, 80 | kDns1 = 531, 81 | kIcmp = 100, 82 | }; 83 | 84 | struct AddressInfo { 85 | std::string ip; 86 | uint16_t port; 87 | std::string detect_local_ip; 88 | uint16_t detect_local_port; 89 | }; 90 | 91 | struct UdpClientNatInfo { 92 | uint32_t protocal; 93 | std::string local_ip; 94 | uint16_t local_port; 95 | std::string public_ip; 96 | uint16_t public_port; 97 | }; 98 | 99 | struct VpnServer { 100 | int protocal; 101 | std::vector vpn_info; 102 | }; 103 | 104 | typedef std::vector VpnArray; 105 | 106 | struct MessageIdentity { 107 | MessageIdentity():message_id(), node_id() {} 108 | MessageIdentity( 109 | const uint32_t in_message_id, 110 | const std::string& in_node_id) 111 | :message_id(in_message_id), 112 | node_id(in_node_id){ 113 | } 114 | virtual ~MessageIdentity() {} 115 | virtual std::string ToString() const { 116 | return base::StringUtil::str_fmt("%d_", message_id) + node_id; 117 | } 118 | bool operator< (const MessageIdentity& other) const { 119 | if(message_id < other.message_id) { 120 | return true; 121 | } else if(message_id == other.message_id) { 122 | if(node_id < other.node_id) { 123 | return true; 124 | } 125 | } 126 | return false; 127 | } 128 | uint32_t message_id; 129 | std::string node_id; 130 | }; 131 | 132 | static const int kKadParamK = 8; 133 | static const int kKadParamAlpha = 2; 134 | static const int kKadParamAlphaRandom = 1; // 0 if no random node 135 | static const int kNodeIdTypeSize = 4; 136 | static const int kRoutingMaxNodesSize = kNodeIdSize * 8 * kKadParamK; 137 | static const int kFindNodesMaxSize = kRoutingMaxNodesSize; // max size find nodes from neighbors 138 | static const int kRandomRoutingPos = kRoutingMaxNodesSize * 2 / 3; 139 | static const int kClosestNodesNum = 16; 140 | static const int kDetectionTimes = 4; 141 | static const int kHopToLive = 20; 142 | static const int kJoinRetryTimes = 5; 143 | static const uint32_t kFindNodesBloomfilterBitSize = 4096; 144 | static const uint32_t kFindNodesBloomfilterHashNum = 11; 145 | 146 | static const std::string kUdpNatDetectMagic = "UdpNatDetectMagic"; 147 | static const std::string LOCAL_COUNTRY_DB_KEY = "local_country_code"; 148 | static const std::string LOCAL_EDGE_DB_KEY = "local_edge"; 149 | static const std::string TCP_RELAY_PORT_DB_KEY = "tcp_relay_ports"; 150 | static const std::string BOOTSTRAP_CACHE_DB_KEY = "bootstrap_cache"; 151 | static const std::string VERSION_KEY = "NODE_VERSION"; 152 | static const std::string COPYRIGHT_KEY = "NODE_COPYRIGHT"; 153 | 154 | std::string GenNodeIdType(const std::string& country, const std::string& business); 155 | std::string GenRandomID(const std::string& country, const std::string& business); 156 | std::string GenNodeIdType(uint8_t country_code, uint8_t service_type); 157 | std::string GenRandomID(uint8_t country_code, uint8_t service_type); 158 | bool GetNetworkId(const std::string& id, uint32_t& network_id); 159 | bool GetZoneIdFromConfig(const base::Config& config, uint32_t& zone_id); 160 | void GetPublicEndpointsConfig( 161 | const top::base::Config& config, 162 | std::set>& boot_endpoints); 163 | void GetPublicServiceEndpointsConfig( 164 | const top::base::Config& config, 165 | const std::string& service_name, 166 | std::set>& boot_endpoints); 167 | void GetAllPublicServiceEndpointsConfig( 168 | const top::base::Config& config, 169 | const std::string& service_list, 170 | std::set>& boot_endpoints); 171 | uint32_t GetXNetworkID(const std::string& id); 172 | uint8_t GetZoneID(const std::string& id); 173 | void toupper(std::string &str); 174 | void tolower(std::string &str); 175 | 176 | bool CreateGlobalXid(const base::Config& config); 177 | LocalNodeInfoPtr CreateLocalInfoFromConfig( 178 | const base::Config& config, 179 | base::KadmliaKeyPtr kad_key); 180 | 181 | } // namespace kadmlia 182 | 183 | } // namespace top 184 | -------------------------------------------------------------------------------- /tests/node_mgr.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "node_mgr.h" 6 | #include "xpbase/base/top_log_name.h" 7 | 8 | namespace top { 9 | namespace kadmlia { 10 | namespace test { 11 | 12 | bool NodeMgr::Init(bool first_node, const std::string& name_prefix) { 13 | TOP_FATAL_NAME("NodeMgr::Init"); 14 | timer_manager_impl_ = base::TimerManager::CreateInstance(); 15 | timer_manager_impl_->Start(1); 16 | 17 | first_node_ = first_node; 18 | name_prefix_ = name_prefix; 19 | name_ = name_prefix + name_; 20 | 21 | // basic config 22 | const bool client_mode = false; 23 | const std::string idtype = ""; 24 | const std::string str_key = name_; 25 | const bool hash_tag = true; 26 | auto kad_key = std::make_shared(str_key, hash_tag); 27 | 28 | // init nat manager 29 | nat_manager_ = std::make_shared(); 30 | nat_manager_->name_ = name_prefix_ + nat_manager_->name_; 31 | nat_manager_->timer_manager_ = timer_manager_impl_.get(); 32 | 33 | // register message handler 34 | kad_message_handler_.message_manager_ = &this->message_manager_; 35 | kad_message_handler_.nat_manager_ = this->nat_manager_.get(); 36 | kad_message_handler_.Init(); 37 | 38 | // init message process threads 39 | thread_message_handler_ = std::make_shared(); 40 | thread_message_handler_->m_woker_threads_count = 1; 41 | thread_message_handler_->Init(); 42 | for (auto& thread : thread_message_handler_->m_worker_threads) { 43 | thread->message_manager_ = &this->message_manager_; 44 | } 45 | 46 | // init udp socket 47 | { 48 | udp_transport_.reset(new top::transport::UdpTransport()); 49 | auto ret = udp_transport_->Start(local_ip_, 0, thread_message_handler_.get()); 50 | if (ret != top::kadmlia::kKadSuccess) { 51 | TOP_FATAL_NAME("udp_transport start failed!"); 52 | return false; 53 | } 54 | udp_transport_->RegisterOfflineCallback(kadmlia::HeartbeatManagerIntf::OnHeartbeatCallback); 55 | real_local_port_ = udp_transport_->local_port(); 56 | TOP_FATAL_NAME("real local port: %d", (int)real_local_port_); 57 | } 58 | 59 | // init nat 60 | if (first_node_) { 61 | auto ret = NatDetect("", 0); 62 | assert(ret); 63 | } 64 | 65 | // init local node info 66 | auto local_node_ptr = std::make_shared(); 67 | if (!local_node_ptr->Init( 68 | local_ip_, 69 | local_port_, 70 | first_node, 71 | client_mode, 72 | idtype, 73 | kad_key, 74 | kad_key->xnetwork_id(), 75 | kRoleInvalid)) { 76 | TOP_FATAL_NAME("local_node_ptr init failed!"); 77 | return false; 78 | } 79 | local_node_ptr->set_service_type(kRoot); 80 | 81 | // init routing table 82 | routing_table_ptr_.reset(new top::kadmlia::RoutingTable( 83 | udp_transport_, 84 | kNodeIdSize, 85 | local_node_ptr)); 86 | routing_table_ptr_->name_ = name_prefix + routing_table_ptr_->name_; 87 | routing_table_ptr_->timer_manager_ = timer_manager_impl_.get(); 88 | 89 | if (!routing_table_ptr_->Init()) { 90 | TOP_FATAL_NAME("routing_table_ptr init failed!"); 91 | return false; 92 | } 93 | 94 | kad_message_handler_.set_routing_ptr(routing_table_ptr_); 95 | TOP_FATAL_NAME("init success"); 96 | return true; 97 | } 98 | 99 | NodeMgr::NodeMgr() { 100 | // TOP_FATAL_NAME("---------------------------------------- new NodeMgr(%p)", this); 101 | } 102 | 103 | NodeMgr::~NodeMgr() { 104 | // TOP_FATAL_NAME("---------------------------------------- delete NodeMgr(%p)", this); 105 | if (nat_transport_) { 106 | nat_transport_->Stop(); 107 | } 108 | 109 | if (udp_transport_) { 110 | udp_transport_->Stop(); 111 | } 112 | 113 | // TODO: merge nat transport to nat manager! 114 | if (nat_manager_) { 115 | nat_manager_->Stop(); 116 | } 117 | 118 | if (thread_message_handler_) { 119 | thread_message_handler_->Stop(); 120 | } 121 | 122 | if (routing_table_ptr_) { 123 | routing_table_ptr_->UnInit(); 124 | } 125 | 126 | timer_manager_impl_->Stop(); 127 | 128 | // sleep(5); 129 | } 130 | 131 | bool NodeMgr::NatDetect(const std::string& peer_ip, uint16_t peer_port) { 132 | { 133 | nat_transport_.reset(new top::transport::UdpTransport()); 134 | auto ret = nat_transport_->Start(local_ip_, 0, thread_message_handler_.get()); 135 | if (ret != top::kadmlia::kKadSuccess) { 136 | TOP_FATAL_NAME("nat_transport start failed!"); 137 | return false; 138 | } 139 | } 140 | 141 | std::set> boot_endpoints; 142 | boot_endpoints.insert({peer_ip, peer_port}); 143 | transport::MultiThreadHandler* messager_handler = nullptr; 144 | if (!nat_manager_->Start( 145 | first_node_, 146 | boot_endpoints, 147 | messager_handler, 148 | udp_transport_.get(), 149 | nat_transport_.get())) { 150 | TOP_FATAL_NAME("nat detect failed"); 151 | return false; 152 | } 153 | 154 | int32_t nat_type = kNatTypeUnknown; 155 | nat_manager_->GetLocalNatType(nat_type); 156 | TOP_FATAL_NAME("nat detect over: %d", nat_type); 157 | return true; 158 | } 159 | 160 | bool NodeMgr::JoinRt(const std::string& peer_ip, uint16_t peer_port) { 161 | std::set> boot_endpoints; 162 | boot_endpoints.insert({peer_ip, peer_port}); 163 | int ret = routing_table_ptr_->MultiJoin(boot_endpoints); 164 | if (ret != kKadSuccess) { 165 | TOP_FATAL_NAME("join failed"); 166 | return false; 167 | } 168 | 169 | TOP_FATAL_NAME("join ok"); 170 | return true; 171 | } 172 | 173 | std::string NodeMgr::LocalIp() { 174 | return local_ip_; 175 | } 176 | 177 | uint16_t NodeMgr::RealLocalPort() { 178 | return real_local_port_; 179 | } 180 | 181 | void NodeMgr::HandleMessage( 182 | transport::protobuf::RoutingMessage& message, 183 | base::xpacket_t& packet) { 184 | message_manager_.HandleMessage(message, packet); 185 | } 186 | 187 | } // namespace test 188 | } // namespace kadmlia 189 | } // namespace top 190 | -------------------------------------------------------------------------------- /tests/test_routing_utils.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "xkad/routing_table/routing_utils.h" 12 | #include "xpbase/base/xid/xid_def.h" 13 | 14 | namespace top { 15 | 16 | namespace kadmlia { 17 | 18 | namespace test { 19 | 20 | class TestRoutingUtil : public testing::Test { 21 | public: 22 | static void SetUpTestCase() { 23 | 24 | } 25 | 26 | static void TearDownTestCase() { 27 | } 28 | 29 | virtual void SetUp() { 30 | 31 | } 32 | 33 | virtual void TearDown() { 34 | } 35 | }; 36 | 37 | TEST_F(TestRoutingUtil, TestAll) { 38 | random_number_generator_mutex(); 39 | std::string str(RandomString(256)); 40 | std::string hex_enc = HexEncode(str); 41 | std::string hex_dec = HexDecode(hex_enc); 42 | ASSERT_EQ(hex_dec, str); 43 | HexSubstr(str); 44 | 45 | std::string base_enc = Base64Encode(str); 46 | std::string base_dec = Base64Decode(base_enc); 47 | ASSERT_EQ(base_dec, str); 48 | Base64Substr(str); 49 | } 50 | 51 | TEST_F(TestRoutingUtil, RandomInt32) { 52 | RandomInt32(); 53 | RandomUint32(); 54 | } 55 | 56 | TEST_F(TestRoutingUtil, toupper) { 57 | std::string test_str = "sdfasdfASFasdfsdfa0.HFSDFDS>%$#@*&<]}~`0sdf90"; 58 | toupper(test_str); 59 | ASSERT_EQ(test_str, "SDFASDFASFASDFSDFA0.HFSDFDS>%$#@*&<]}~`0SDF90"); 60 | } 61 | 62 | TEST_F(TestRoutingUtil, tolower) { 63 | std::string test_str = "sdfasdfASFasdfsdfa0.HFSDFDS>%$#@*&<]}~`0sdf90"; 64 | tolower(test_str); 65 | ASSERT_EQ(test_str, "sdfasdfasfasdfsdfa0.hfsdfds>%$#@*&<]}~`0sdf90"); 66 | } 67 | 68 | TEST_F(TestRoutingUtil, GenRandomID_bussiness) { 69 | std::string conuntry = "CN"; 70 | std::string business = "XVPN"; 71 | std::string id = GenRandomID(conuntry, business); 72 | ASSERT_FALSE(id.empty()); 73 | } 74 | 75 | TEST_F(TestRoutingUtil, GenNodeIdType_service_type1) { 76 | uint8_t country_code = 1; 77 | uint8_t service_type = 2; 78 | auto ret = GenNodeIdType(country_code, service_type); 79 | ASSERT_EQ(4u, ret.size()); 80 | } 81 | 82 | TEST_F(TestRoutingUtil, GenNodeIdType_service_type2) { 83 | uint8_t country_code = 1; 84 | uint32_t service_type = 2; 85 | auto ret = GenNodeIdType(country_code, service_type); 86 | ASSERT_EQ(4u, ret.size()); 87 | } 88 | 89 | TEST_F(TestRoutingUtil, GenNodeIdType_bussiness) { 90 | { 91 | std::string country_code; 92 | std::string bussiness; 93 | auto ret = GenNodeIdType(country_code, bussiness); 94 | ASSERT_EQ(0u, ret.size()); 95 | } 96 | 97 | { 98 | std::string country_code = "INVALID"; 99 | std::string bussiness; 100 | auto ret = GenNodeIdType(country_code, bussiness); 101 | ASSERT_EQ(0u, ret.size()); 102 | } 103 | 104 | { 105 | std::string country_code = "CN"; 106 | std::string bussiness; 107 | auto ret = GenNodeIdType(country_code, bussiness); 108 | ASSERT_EQ(0u, ret.size()); 109 | } 110 | 111 | { 112 | std::string country_code = "CN"; 113 | std::string bussiness = "ROOT"; 114 | auto ret = GenNodeIdType(country_code, bussiness); 115 | ASSERT_EQ(4u, ret.size()); 116 | } 117 | } 118 | 119 | TEST_F(TestRoutingUtil, GenRandomID_service) { 120 | uint8_t country_code = 1; 121 | uint8_t service_type = top::kInvalidType; 122 | auto ret = GenRandomID(country_code, service_type); 123 | ASSERT_EQ(kNodeIdSize, ret.size()); // regard country_code as zone_id, service_type as network_id 124 | } 125 | 126 | TEST_F(TestRoutingUtil, GetNetworkId) { 127 | { 128 | std::string id; 129 | uint32_t network_id = 0; 130 | ASSERT_FALSE(GetNetworkId(id, network_id)); 131 | } 132 | 133 | { 134 | std::string id; 135 | id.resize(kNodeIdSize); 136 | id[1] = 0xf0; 137 | uint32_t network_id = 0; 138 | ASSERT_TRUE(GetNetworkId(id, network_id)); 139 | ASSERT_EQ(0xf0, network_id); 140 | } 141 | } 142 | 143 | TEST_F(TestRoutingUtil, GetPublicEndpointsConfig) { 144 | { 145 | TOP_INFO("GetPublicEndpointsConfig_1"); 146 | base::Config config; 147 | std::set> boot_endpoints; 148 | GetPublicEndpointsConfig(config, boot_endpoints); 149 | ASSERT_EQ(0u, boot_endpoints.size()); 150 | } 151 | 152 | { 153 | TOP_INFO("GetPublicEndpointsConfig_2"); 154 | base::Config config; 155 | config.Set("node", "public_endpoints", "1:2, 3:4"); 156 | std::set> boot_endpoints; 157 | GetPublicEndpointsConfig(config, boot_endpoints); 158 | ASSERT_EQ(2u, boot_endpoints.size()); 159 | } 160 | } 161 | 162 | TEST_F(TestRoutingUtil, GetPublicServiceEndpointsConfig) { 163 | { 164 | TOP_INFO("GetPublicServiceEndpointsConfig_1"); 165 | base::Config config; 166 | std::string service_name; 167 | std::set> boot_endpoints; 168 | GetPublicServiceEndpointsConfig(config, service_name, boot_endpoints); 169 | ASSERT_EQ(0u, boot_endpoints.size()); 170 | } 171 | 172 | { 173 | TOP_INFO("GetPublicServiceEndpointsConfig_2"); 174 | base::Config config; 175 | std::string service_name = "vpn"; 176 | config.Set(service_name, "bootstrap", "1:2,3:4"); 177 | std::set> boot_endpoints; 178 | GetPublicServiceEndpointsConfig(config, service_name, boot_endpoints); 179 | ASSERT_EQ(2u, boot_endpoints.size()); 180 | } 181 | } 182 | 183 | TEST_F(TestRoutingUtil, GetAllPublicServiceEndpointsConfig) { 184 | base::Config config; 185 | std::string service_list = "vpn,storage"; 186 | config.Set("vpn", "bootstrap", "1:2,3:4"); 187 | config.Set("storage", "bootstrap", "5:6,7:8"); 188 | std::set> boot_endpoints; 189 | GetAllPublicServiceEndpointsConfig(config, service_list, boot_endpoints); 190 | ASSERT_EQ(4u, boot_endpoints.size()); 191 | } 192 | 193 | TEST_F(TestRoutingUtil, GetXNetworkID_GetZoneID) { 194 | const uint32_t NET_ID = 1; 195 | const uint8_t ZONE_ID = 2; 196 | base::XID xid(NET_ID, ZONE_ID, "pubkey", "prikey"); 197 | auto str_id = xid.ToString(); 198 | auto net_id = GetXNetworkID(str_id); 199 | ASSERT_EQ(NET_ID, net_id); 200 | 201 | auto zone_id = GetZoneID(str_id); 202 | ASSERT_EQ(ZONE_ID, zone_id); 203 | } 204 | 205 | 206 | } // namespace test 207 | 208 | } // namespace kadmlia 209 | 210 | } // namespace top 211 | -------------------------------------------------------------------------------- /src/node_detection_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/node_detection_manager.h" 6 | 7 | #include "xbase/xutl.h" 8 | 9 | #include "xtransport/transport.h" 10 | #include "xpbase/base/top_log.h" 11 | #include "xpbase/base/top_utils.h" 12 | #include "xkad/routing_table/callback_manager.h" 13 | #include "xkad/routing_table/node_info.h" 14 | #include "xtransport/proto/transport.pb.h" 15 | #include "xkad/proto/kadmlia.pb.h" 16 | #include "xkad/routing_table/local_node_info.h" 17 | #include "xkad/routing_table/routing_table.h" 18 | 19 | namespace top { 20 | 21 | namespace kadmlia { 22 | 23 | // static const int kDetectedMapClearCount = 100 * 1024; 24 | static const int32_t kDoDetectionPeriod = 600 * 1000; // 600ms 25 | 26 | NodeDetectionManager::NodeDetectionManager(base::TimerManager* timer_manager, RoutingTable& routing_table) 27 | : detection_nodes_map_(), 28 | detection_nodes_map_mutex_(), 29 | detected_nodes_map_(), 30 | detected_nodes_map_mutex_(), 31 | routing_table_(routing_table) { 32 | timer_manager_ = timer_manager; 33 | timer_ = std::make_shared(timer_manager_, "NodeDetectionManager"); 34 | timer_->Start( 35 | kDoDetectionPeriod, 36 | kDoDetectionPeriod, 37 | std::bind(&NodeDetectionManager::DoTetection, this)); 38 | } 39 | 40 | NodeDetectionManager::~NodeDetectionManager() { 41 | Join(); 42 | TOP_INFO("NodeDetectionManager thread joined!"); 43 | } 44 | 45 | void NodeDetectionManager::Join() { 46 | destroy_ = true; 47 | timer_ = nullptr; 48 | { 49 | std::unique_lock lock(detection_nodes_map_mutex_); 50 | detection_nodes_map_.clear(); 51 | } 52 | { 53 | std::unique_lock lock(detected_nodes_map_mutex_); 54 | detected_nodes_map_.clear(); 55 | } 56 | } 57 | 58 | bool NodeDetectionManager::Detected(const std::string& id) { 59 | std::unique_lock lock(detected_nodes_map_mutex_); 60 | auto no_iter = detected_nodes_map_.find(id); 61 | if (no_iter != detected_nodes_map_.end()) { 62 | if (no_iter->second->detection_count >= 3) { 63 | return true; 64 | } 65 | } 66 | 67 | return false; 68 | } 69 | 70 | int NodeDetectionManager::AddDetectionNode(std::shared_ptr node_ptr) { 71 | if (destroy_) { 72 | return kKadSuccess; 73 | } 74 | 75 | if (node_ptr->nat_type == kNatTypeConeAbnormal) { 76 | node_ptr->detection_delay_count = 3; 77 | } else { 78 | node_ptr->detection_delay_count = 0; 79 | } 80 | 81 | std::unique_lock lock(detection_nodes_map_mutex_); 82 | std::string key = (node_ptr->public_ip + "_" + 83 | base::xstring_utl::tostring(node_ptr->public_port)); 84 | auto ins_iter = detection_nodes_map_.insert(std::make_pair(key, node_ptr)); 85 | if (ins_iter.second) { 86 | return kKadSuccess; 87 | } 88 | 89 | return kKadFailed; 90 | } 91 | 92 | void NodeDetectionManager::RemoveDetection(const std::string& ip, uint16_t port) { 93 | std::unique_lock lock(detection_nodes_map_mutex_); 94 | std::string key = ip + "_" + base::xstring_utl::tostring(port); 95 | auto iter = detection_nodes_map_.find(key); 96 | if (iter != detection_nodes_map_.end()) { 97 | detection_nodes_map_.erase(iter); 98 | } 99 | } 100 | 101 | int NodeDetectionManager::Handshake(std::shared_ptr node_ptr) { 102 | if (destroy_) { 103 | return kKadSuccess; 104 | } 105 | 106 | transport::protobuf::RoutingMessage message; 107 | routing_table_.SetFreqMessage(message); 108 | LocalNodeInfoPtr local_node = routing_table_.get_local_node_info(); 109 | if (!local_node) { 110 | return kKadFailed; 111 | } 112 | message.set_des_service_type(node_ptr->service_type); 113 | message.set_des_node_id(node_ptr->node_id); 114 | message.set_type(kKadHandshake); 115 | if (local_node->client_mode()) { 116 | message.set_client_msg(true); 117 | } 118 | 119 | std::shared_ptr transport_ptr = routing_table_.get_transport(); 120 | if (!transport_ptr) { 121 | TOP_ERROR("service type[%llu] has not register transport.", message.des_service_type()); 122 | return kKadFailed; 123 | } 124 | 125 | protobuf::Handshake handshake; 126 | handshake.set_type(kHandshakeRequest); 127 | handshake.set_local_ip(local_node->local_ip()); 128 | handshake.set_local_port(local_node->local_port()); 129 | handshake.set_public_ip(local_node->public_ip()); 130 | handshake.set_public_port(local_node->public_port()); 131 | handshake.set_nat_type(local_node->nat_type()); 132 | handshake.set_xid(global_xid->Get()); 133 | std::string data; 134 | if (!handshake.SerializeToString(&data)) { 135 | TOP_INFO("ConnectReq SerializeToString failed!"); 136 | return kKadFailed; 137 | } 138 | 139 | message.set_data(data); 140 | std::string msg; 141 | if (!message.SerializeToString(&msg)) { 142 | TOP_INFO("RoutingMessage SerializeToString failed!"); 143 | return kKadFailed; 144 | } 145 | xbyte_buffer_t xdata{msg.begin(), msg.end()}; 146 | 147 | // try vlan connect 148 | //transport_ptr->SendPing(xdata, node_ptr->local_ip, node_ptr->local_port); 149 | // try public connect 150 | transport_ptr->SendPing(xdata, node_ptr->public_ip, node_ptr->public_port); 151 | TOP_DEBUG("sendping sendhandshake from:%s:%d to %s:%d size:%d", 152 | local_node->public_ip().c_str(), 153 | local_node->public_port(), 154 | (node_ptr->public_ip).c_str(), 155 | node_ptr->public_port, 156 | xdata.size()); 157 | return kKadSuccess; 158 | } 159 | 160 | void NodeDetectionManager::DoTetection() { 161 | if (destroy_) { 162 | return; 163 | } 164 | 165 | { 166 | std::unique_lock lock(detection_nodes_map_mutex_); 167 | if (detection_nodes_map_.size() > 1000) { 168 | TOP_WARN("detection_nodes_map_ size: %d", detection_nodes_map_.size()); 169 | } 170 | auto iter = detection_nodes_map_.begin(); 171 | while (iter != detection_nodes_map_.end()) { 172 | if (iter->second->detection_delay_count > 0) { 173 | iter->second->detection_delay_count--; 174 | ++iter; 175 | continue; 176 | } 177 | 178 | if (iter->second->detection_count >= kDetectionTimes) { 179 | detection_nodes_map_.erase(iter++); 180 | continue; 181 | } 182 | 183 | Handshake(iter->second); 184 | iter->second->detection_count++; 185 | ++iter; 186 | } 187 | } 188 | } 189 | 190 | } // namespace kadmlia 191 | 192 | } // namespace top 193 | -------------------------------------------------------------------------------- /bench/util.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "util.h" 6 | #include 7 | #include "xpbase/base/top_utils.h" 8 | #include "xpbase/base/top_log.h" 9 | #include "xpbase/base/line_parser.h" 10 | #include "xpbase/base/top_string_util.h" 11 | #include 12 | 13 | namespace top { 14 | namespace kadmlia { 15 | namespace test { 16 | 17 | // -------------------------------------------------------------------------------- 18 | BenchCommand* BenchCommand::Instance() { 19 | static BenchCommand ins; 20 | return &ins; 21 | } 22 | 23 | void BenchCommand::Init(bool show_cmd) { 24 | show_cmd_ = show_cmd; 25 | } 26 | 27 | void BenchCommand::Run() { 28 | PrintUsage(); 29 | 30 | for (;;) { 31 | if (!show_cmd_) { 32 | SleepUs(200 * 1000); 33 | continue; 34 | } 35 | 36 | std::cout << "\nEnter command > "; 37 | std::string cmdline; 38 | std::getline(std::cin, cmdline); 39 | { 40 | ProcessCommand(cmdline); 41 | } 42 | } 43 | } 44 | 45 | void BenchCommand::ProcessCommand(const std::string& cmdline) { 46 | if (cmdline.empty()) { 47 | return; 48 | } 49 | 50 | std::string cmd; 51 | Arguments args; 52 | try { 53 | top::base::LineParser line_split(cmdline.c_str(), ' ', cmdline.size()); 54 | cmd = ""; 55 | for (uint32_t i = 0; i < line_split.Count(); ++i) { 56 | if (strlen(line_split[i]) == 0) { 57 | continue; 58 | } 59 | 60 | if (cmd == "") 61 | cmd = line_split[i]; 62 | else 63 | args.push_back(line_split[i]); 64 | } 65 | } catch (const std::exception& e) { 66 | TOP_WARN("Error processing command: %s", e.what()); 67 | } 68 | 69 | std::unique_lock lock(map_commands_mutex_); 70 | auto it = map_commands_.find(cmd); 71 | if (it == map_commands_.end()) { 72 | std::cout << "Invalid command : " << cmd << std::endl; 73 | // PrintUsage(); 74 | } else { 75 | (it->second)(args); // call command procedure 76 | } 77 | } 78 | 79 | void BenchCommand::RegisterCommand(const std::string& cmd_name, CommandProc cmd_proc) { 80 | assert(cmd_proc); 81 | std::unique_lock lock(map_commands_mutex_); 82 | 83 | auto it = map_commands_.find(cmd_name); 84 | if (it != map_commands_.end()) { 85 | TOP_WARN("command(%s) exist and ignore new one", cmd_name.c_str()); 86 | return; 87 | } 88 | 89 | map_commands_[cmd_name] = cmd_proc; 90 | TOP_INFO("add command(%s)", cmd_name.c_str()); 91 | } 92 | 93 | void BenchCommand::PrintUsage() { 94 | // std::cout << "\thelp Print options.\n"; 95 | // std::cout << "\tjoin Normal Join.\n"; 96 | // std::cout << "\tprt Print Local Routing Table.\n"; 97 | // std::cout << "\trrt Request Routing Table from peer node with the specified" 98 | // << " identity-index.\n"; 99 | // std::cout << "\tsave save all nodes but nodes in routing table.\n"; 100 | // std::cout << "\trt relay test, this node to other hop count.\n"; 101 | // std::cout << "\tart all nodes relay test, this node to other hop count.\n"; 102 | // std::cout << "\tgroup get groups by target id.\n"; 103 | // std::cout << "\tsync sync all nodes from bootstrap node.\n"; 104 | // std::cout << "\tgets get service nodes of service_type.\n"; 105 | // std::cout << "\tsets set service type for gets.\n"; 106 | 107 | std::cout << "all commands:" << std::endl; 108 | int n = 0; 109 | std::unique_lock lock(map_commands_mutex_); 110 | for (auto& kv : map_commands_) { 111 | auto fmt = base::StringUtil::str_fmt(" [%d] %s: %s", n, kv.first.c_str(), "help?"); 112 | n += 1; 113 | std::cout << fmt << std::endl; 114 | } 115 | } 116 | 117 | // -------------------------------------------------------------------------------- 118 | Util* Util::Instance() { 119 | static Util ins; 120 | return &ins; 121 | } 122 | 123 | bool Util::HandleParamsAndConfig(int argc, char** argv, base::Config& config) { 124 | top::ArgsParser args_parser; 125 | if (!ParseParams(argc, argv, args_parser)) { 126 | TOP_FATAL("parse params failed!"); 127 | return false; 128 | } 129 | 130 | if (args_parser.HasParam("h")) { 131 | std::cout << "Allowed options:" << std::endl; 132 | std::cout << "\t-h [help] print help info" << std::endl; 133 | std::cout << "\t-g [show_cmd] show cmd" << std::endl; 134 | std::cout << "\t-p [peer] bootstrap peer[ip:port]" << std::endl; 135 | std::cout << "\t-i [identity_index] only first node need" << std::endl; 136 | std::cout << "\t-l [local_port] local udp port" << std::endl; 137 | std::cout << "\t-a [local_ip] local ip " << std::endl; 138 | std::cout << "\t-L [log_path] log path" << std::endl; 139 | std::cout << "\t-D [log_level] log level" << std::endl; 140 | exit(0); 141 | } 142 | 143 | if (!ResetConfig(args_parser, config)) { 144 | TOP_FATAL("reset edge config with arg parser failed!"); 145 | return false; 146 | } 147 | 148 | return true; 149 | } 150 | 151 | bool Util::ParseParams(int argc, char** argv, ArgsParser& args_parser) { 152 | args_parser.AddArgType('h', "help", top::kNoValue); 153 | args_parser.AddArgType('g', "show_cmd", top::kMustValue); 154 | args_parser.AddArgType('p', "peer", top::kMustValue); 155 | args_parser.AddArgType('i', "identity_index", top::kMustValue); 156 | args_parser.AddArgType('l', "local_port", top::kMustValue); 157 | args_parser.AddArgType('a', "local_ip", top::kMustValue); 158 | args_parser.AddArgType('L', "log_path", top::kMustValue); 159 | args_parser.AddArgType('D', "log_level", top::kMustValue); 160 | 161 | std::string tmp_params = ""; 162 | for (int i = 1; i < argc; i++) { 163 | if (strlen(argv[i]) == 0) { 164 | tmp_params += static_cast(31); 165 | } else { 166 | tmp_params += argv[i]; 167 | } 168 | tmp_params += " "; 169 | } 170 | 171 | std::string err_pos; 172 | if (args_parser.Parse(tmp_params, err_pos) != top::kadmlia::kKadSuccess) { 173 | std::cout << "parse params failed!" << std::endl; 174 | return false; 175 | } 176 | 177 | return true; 178 | } 179 | 180 | bool Util::ResetConfig(ArgsParser& args_parser, base::Config& config) { 181 | int show_cmd = 1; 182 | if (args_parser.GetParam("g", show_cmd) == top::kadmlia::kKadSuccess) { 183 | if (!config.Set("node", "show_cmd", show_cmd == 1)) { 184 | TOP_FATAL("set config failed [node][show_cmd][%d]", show_cmd); 185 | return false; 186 | } 187 | } 188 | 189 | std::string peer; 190 | args_parser.GetParam("p", peer); 191 | if (!peer.empty()) { 192 | if (!config.Set("node", "public_endpoints", peer)) { 193 | TOP_FATAL("set config failed [node][public_endpoints][%s]", peer.c_str()); 194 | return false; 195 | } 196 | } 197 | 198 | int identity_index = 1; 199 | if (args_parser.GetParam("i", identity_index) == top::kadmlia::kKadSuccess) { 200 | bool first_node = false; 201 | if (identity_index == 0) { 202 | first_node = true; 203 | } 204 | if (!config.Set("node", "first_node", first_node)) { 205 | TOP_FATAL("set config failed [node][first_node][%d]", first_node); 206 | return false; 207 | } 208 | } 209 | 210 | uint16_t local_port = 0; 211 | if (args_parser.GetParam("l", local_port) == top::kadmlia::kKadSuccess) { 212 | if (!config.Set("node", "local_port", local_port)) { 213 | TOP_FATAL("set config failed [node][local_port][%d]", local_port); 214 | return false; 215 | } 216 | } 217 | 218 | std::string local_ip; 219 | args_parser.GetParam("a", local_ip); 220 | if (!local_ip.empty()) { 221 | if (!config.Set("node", "local_ip", local_ip)) { 222 | TOP_FATAL("set config failed [node][local_ip][%s]", local_ip.c_str()); 223 | return false; 224 | } 225 | } 226 | 227 | std::string log_path; 228 | if (args_parser.GetParam("L", log_path) == top::kadmlia::kKadSuccess) { 229 | if (!config.Set("node", "log_path", log_path)) { 230 | TOP_FATAL("set config failed [node][log_path][%s]", log_path.c_str()); 231 | return false; 232 | } 233 | } 234 | 235 | int log_level = 0; 236 | if (args_parser.GetParam("D", log_level) == top::kadmlia::kKadSuccess) { 237 | if (!config.Set("node", "log_level", log_level)) { 238 | TOP_FATAL("set config failed [node][log_level][%d]", log_level); 239 | return false; 240 | } 241 | } 242 | 243 | return true; 244 | } 245 | 246 | } // namespace test 247 | } // namespace kadmlia 248 | } // namespace top 249 | -------------------------------------------------------------------------------- /src/routing_utils.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/routing_utils.h" 6 | 7 | #ifdef _MSC_VER 8 | #define _WINSOCKAPI_ 9 | #include 10 | #endif 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "xpbase/base/top_log.h" 17 | #include "xpbase/base/top_utils.h" 18 | #include "xpbase/base/endpoint_util.h" 19 | #include "xkad/routing_table/routing_table.h" 20 | #include "xkad/routing_table/nodeid_utils.h" 21 | #include "xpbase/base/line_parser.h" 22 | #include "xpbase/base/xid/xid_parser.h" 23 | #include "xpbase/base/xip_parser.h" 24 | #include "xpbase/base/kad_key/get_kadmlia_key.h" 25 | #include "xbase/xhash.h" 26 | 27 | namespace top { 28 | 29 | namespace kadmlia { 30 | 31 | //extern std::shared_ptr global_xid; 32 | 33 | void toupper(std::string& str) { 34 | std::transform(str.begin(), str.end(), str.begin(), ::toupper); 35 | } 36 | 37 | void tolower(std::string& str) { 38 | std::transform(str.begin(), str.end(), str.begin(), ::tolower); 39 | } 40 | 41 | // edge node 42 | std::string GenNodeIdType(uint8_t country_code, uint8_t service_type) { 43 | // 3 bytes network_id(service_type), 1 byte country_code 44 | // after serialize string, xid: [country_code:network_id], eg. [38040000] 45 | uint32_t ser = service_type; 46 | char s[4]; 47 | memcpy(s, &country_code, 1); 48 | memcpy(s + 1, &ser, 3); 49 | std::string str(s, 4); 50 | return str; 51 | } 52 | 53 | std::string GenNodeIdType(const std::string& in_country, const std::string& in_business) { 54 | // NodeId type total kNodeIdType = 4 bytes, 3 bytes network_id + 1 byte country_code 55 | if (in_country.empty() || in_business.empty()) { 56 | return ""; 57 | } 58 | std::string country(in_country); 59 | std::string business(in_business); 60 | top::kadmlia::toupper(country); 61 | top::kadmlia::toupper(business); 62 | 63 | // country_code 64 | uint8_t countrycode = GetWorldCountryID(country); 65 | if (countrycode == std::numeric_limits::max()) { 66 | return ""; 67 | } 68 | 69 | // network_id 70 | uint32_t businesscode = GetBusinessID(business); 71 | if (businesscode >= std::numeric_limits::max()) { 72 | return ""; 73 | } 74 | 75 | return GenNodeIdType(countrycode, businesscode); 76 | } 77 | 78 | std::string GenRandomID(const std::string& country, const std::string& business) { 79 | std::string idtype(GenNodeIdType(country, business)); 80 | if (idtype.empty()) { 81 | return std::string(""); 82 | } 83 | return idtype + RandomString(kNodeIdSize - kNodeIdTypeSize); 84 | } 85 | 86 | std::string GenRandomID(uint8_t country_code, uint8_t service_type) { 87 | /* 88 | std::string idtype(GenNodeIdType(country_code, service_type)); 89 | if (idtype.empty()) { 90 | return std::string(""); 91 | } 92 | return idtype + RandomString(kNodeIdSize - kNodeIdTypeSize); 93 | */ 94 | base::KadmliaKeyPtr kad_key = base::GetKadmliaKey(); 95 | kad_key->set_xnetwork_id(service_type); 96 | kad_key->set_zone_id(country_code); 97 | return kad_key->Get(); 98 | } 99 | 100 | bool GetNetworkId(const std::string& id, uint32_t& network_id) { 101 | if (id.size() != kNodeIdSize) { 102 | return false; 103 | } 104 | 105 | network_id = *((uint8_t*)(id.c_str() + 1)); // NOLINT 106 | return true; 107 | } 108 | 109 | bool GetZoneIdFromConfig(const base::Config& config, uint32_t& zone_id) { 110 | if (!config.Get("node", "zone_id", zone_id)) { 111 | std::string country; 112 | if (!config.Get("node", "country", country)) { 113 | TOP_FATAL("get node country from config failed!"); 114 | return false; 115 | } 116 | zone_id = base::xhash32_t::digest(country); 117 | } 118 | return true; 119 | } 120 | 121 | void GetPublicEndpointsConfig( 122 | const top::base::Config& config, 123 | std::set>& boot_endpoints) { 124 | std::string public_endpoints; 125 | if (!config.Get("node", "public_endpoints", public_endpoints)) { 126 | TOP_INFO("get node.public_endpoints failed"); 127 | return; 128 | } 129 | 130 | top::base::ParseEndpoints(public_endpoints, boot_endpoints); 131 | } 132 | 133 | void GetPublicServiceEndpointsConfig( 134 | const top::base::Config& config, 135 | const std::string& service_name, 136 | std::set>& boot_endpoints) { 137 | std::string service_public_endpoints; 138 | if (!config.Get(service_name, "bootstrap", service_public_endpoints)) { 139 | TOP_ERROR(" node join service p2p network must has bootstrap endpoints"); 140 | return; 141 | } 142 | top::base::ParseEndpoints(service_public_endpoints, boot_endpoints); 143 | } 144 | 145 | void GetAllPublicServiceEndpointsConfig( 146 | const top::base::Config& config, 147 | const std::string& service_list, 148 | std::set>& boot_endpoints) { 149 | top::base::LineParser line_split(service_list.c_str(), ',', service_list.size()); 150 | for (uint32_t i = 0; i < line_split.Count(); ++i) { 151 | const std::string service_name = line_split[i]; 152 | GetPublicServiceEndpointsConfig(config, service_name, boot_endpoints); 153 | } 154 | } 155 | 156 | uint32_t GetXNetworkID(const std::string& id) { 157 | base::XIDParser xid_parse; 158 | xid_parse.ParserFromString(id); 159 | std::shared_ptr xid_ptr = xid_parse.GetXID(); 160 | uint32_t xnetwork_id = xid_ptr->GetXNetworkID(); 161 | //uint8_t zone_id = xid_ptr->GetZoneID(); 162 | return xnetwork_id; 163 | } 164 | 165 | uint8_t GetZoneID(const std::string& id) { 166 | base::XIDParser xid_parse; 167 | xid_parse.ParserFromString(id); 168 | std::shared_ptr xid_ptr = xid_parse.GetXID(); 169 | //uint32_t xnetwork_id = xid_ptr->GetXNetworkID(); 170 | uint8_t zone_id = xid_ptr->GetZoneID(); 171 | return zone_id; 172 | } 173 | 174 | bool CreateGlobalXid(const base::Config& config) try { 175 | assert(!global_node_id.empty()); 176 | global_node_id_hash = GetStringSha128(global_node_id); // NOLINT 177 | global_xid = base::GetKadmliaKey(global_node_id, true); 178 | global_xid->set_xnetwork_id(kRoot); 179 | uint32_t zone_id; 180 | if (!kadmlia::GetZoneIdFromConfig(config, zone_id)) { 181 | TOP_FATAL("get zone id from config failed!"); 182 | return false; 183 | } 184 | global_xid->set_zone_id(check_cast(((zone_id >> 24) & 0xFF))); 185 | return true; 186 | } catch(...) { 187 | TOP_FATAL("catch ..."); 188 | return false; 189 | } 190 | 191 | LocalNodeInfoPtr CreateLocalInfoFromConfig( 192 | const base::Config& config, 193 | base::KadmliaKeyPtr kad_key) try { 194 | uint32_t zone_id = 0; 195 | if (!kadmlia::GetZoneIdFromConfig(config, zone_id)) { 196 | TOP_ERROR("get node zone id from config failed!"); 197 | return nullptr; 198 | } 199 | auto xip = std::make_shared(kad_key->Xip()); 200 | std::string idtype(top::kadmlia::GenNodeIdType( 201 | check_cast(((zone_id >> 24) & 0xFF)), 202 | xip->xnetwork_id())); 203 | if (idtype.empty()) { 204 | TOP_ERROR("get node id is null!"); 205 | return nullptr; 206 | } 207 | bool client_mode = false; 208 | config.Get("node", "client_mode", client_mode); 209 | bool first_node = false; 210 | config.Get("node", "first_node", first_node); 211 | std::string local_ip; 212 | if (!config.Get("node", "local_ip", local_ip)) { 213 | TOP_ERROR("get node local_ip from config failed!"); 214 | return nullptr; 215 | } 216 | kadmlia::LocalNodeInfoPtr local_node_ptr = nullptr; 217 | //uint16_t local_port = transport_ptr_->local_port(); 218 | // reset real local port in routing_table init 219 | uint16_t local_port = 0; 220 | local_node_ptr.reset(new top::kadmlia::LocalNodeInfo()); 221 | if (!local_node_ptr->Init( 222 | local_ip, 223 | local_port, 224 | first_node, 225 | client_mode, 226 | idtype, 227 | kad_key, 228 | kad_key->xnetwork_id(), 229 | kRoleInvalid)) { 230 | TOP_ERROR("init local node info failed!"); 231 | return nullptr; 232 | } 233 | 234 | uint16_t http_port = static_cast(RandomUint32()); 235 | config.Get("node", "http_port", http_port); 236 | uint16_t ws_port = static_cast(RandomUint32()); 237 | config.Get("node", "ws_port", ws_port); 238 | local_node_ptr->set_rpc_http_port(http_port); 239 | local_node_ptr->set_rpc_ws_port(ws_port); 240 | return local_node_ptr; 241 | } catch (std::exception& e) { 242 | TOP_ERROR("catched error[%s]", e.what()); 243 | return nullptr; 244 | } 245 | 246 | } // namespace kadmlia 247 | 248 | } // namespace top 249 | -------------------------------------------------------------------------------- /src/rumor_handler.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/gossip/rumor_handler.h" 6 | 7 | #include "xpbase/base/uint64_bloomfilter.h" 8 | #include "xkad/gossip/rumor_def.h" 9 | #include "xkad/routing_table/local_node_info.h" 10 | #include "xkad/routing_table/routing_utils.h" 11 | #include "xkad/routing_table/routing_table.h" 12 | #include "xkad/routing_table/node_info.h" 13 | #include "xpbase/base/kad_key/get_kadmlia_key.h" 14 | 15 | namespace top { 16 | namespace gossip { 17 | 18 | bool RumorHandler::Init( 19 | kadmlia::RoutingTablePtr kad_routing_table) { 20 | if (inited_) { 21 | TOP_WARN("RumorHandler::Init Already Inited."); 22 | return true; 23 | } 24 | if (!kad_routing_table) { 25 | TOP_WARN("kadmlia::RoutingTable Invalid."); 26 | return false; 27 | } 28 | kad_routing_table_ = kad_routing_table; 29 | inited_ = true; 30 | TOP_DEBUG("RumorHandler::Init Success."); 31 | return true; 32 | } 33 | 34 | bool RumorHandler::UnInit() { 35 | kad_routing_table_.reset(); 36 | inited_ = false; 37 | return true; 38 | } 39 | 40 | bool RumorHandler::AddRumorMessage( 41 | const transport::protobuf::RoutingMessage& message) { 42 | if (!message_manager_ptr_) { 43 | TOP_WARN("RumorMessageManagerSptr Is Empty.", message.type()); 44 | return false; 45 | } 46 | if(!message_manager_ptr_->AddMessage(message)) { 47 | TOP_WARN("RumorHandler::AddRumorMessage Failed.Message Type:%d", message.type()); 48 | return false; 49 | } 50 | return true; 51 | } 52 | 53 | void RumorHandler::RemoveRumorMessage(int32_t message_type) { 54 | return message_manager_ptr_->RemoveMessage(message_type); 55 | } 56 | 57 | bool RumorHandler::FindRumorMessage( 58 | int32_t message_type, 59 | transport::protobuf::RoutingMessage& message) { 60 | if(!message_manager_ptr_->SearchMessage(message_type, message)) { 61 | TOP_WARN("RumorHandler::FindRumorMessage Failed.Message Type:%d", message_type); 62 | return false; 63 | } 64 | return true; 65 | } 66 | 67 | void RumorHandler::GetAllRumorMessage( 68 | std::vector& all_message) { 69 | return message_manager_ptr_->GetAllMessages(all_message); 70 | } 71 | 72 | void RumorHandler::GetAllNeighborNodes( 73 | std::vector& all_neighbors) { 74 | auto local_node_info_ptr = kad_routing_table_->get_local_node_info(); 75 | if (!local_node_info_ptr) { 76 | TOP_WARN("kadmlia::LocalNodeInfo is invalid"); 77 | return; 78 | } 79 | std::string node_id = local_node_info_ptr->id(); 80 | auto tmp_all_neighbors = kad_routing_table_->nodes(); 81 | if (!just_root_) { 82 | all_neighbors.swap(tmp_all_neighbors); 83 | return; 84 | } 85 | 86 | std::set getted_nodes; 87 | for (auto iter = tmp_all_neighbors.begin(); iter != tmp_all_neighbors.end(); ++iter) { 88 | if ((*iter)->xid.empty()) { 89 | continue; 90 | } 91 | 92 | base::KadmliaKeyPtr xid = base::GetKadmliaKey((*iter)->xid); 93 | if (xid->xnetwork_id() != kRoot) { 94 | continue; 95 | } 96 | 97 | auto getted_iter = getted_nodes.find((*iter)->xid); 98 | if (getted_iter != getted_nodes.end()) { 99 | continue; 100 | } 101 | getted_nodes.insert((*iter)->xid); 102 | all_neighbors.push_back(*iter); 103 | } 104 | } 105 | 106 | void RumorHandler::SpreadNeighbors( 107 | transport::protobuf::RoutingMessage& message, 108 | const std::vector& neighbors) { 109 | assert(false); 110 | message.set_broadcast(true); 111 | if (neighbors.empty()) { 112 | TOP_WARN("No neighbors exists.Message Type:%d", 113 | message.type()); 114 | return; 115 | } 116 | if (message.src_node_id().empty()) { 117 | TOP_WARN("src node id is not given.Message Type:%d", 118 | message.type()); 119 | return; 120 | } 121 | auto local_node_info = kad_routing_table_->get_local_node_info(); 122 | if (!local_node_info) { 123 | TOP_WARN("LocalNodeInfo Is Invalid."); 124 | return; 125 | } 126 | std::vector new_bloomfilter_vec; 127 | for (auto i = 0; i < message.bloomfilter_size(); ++i) { 128 | new_bloomfilter_vec.push_back(message.bloomfilter(i)); 129 | } 130 | std::shared_ptr new_bloomfilter; 131 | if (new_bloomfilter_vec.empty()) { 132 | new_bloomfilter = std::make_shared( 133 | kadmlia::kFindNodesBloomfilterBitSize, 134 | kadmlia::kFindNodesBloomfilterHashNum); 135 | } else { 136 | new_bloomfilter = std::make_shared( 137 | new_bloomfilter_vec, 138 | kadmlia::kFindNodesBloomfilterHashNum); 139 | } 140 | base::Uint64BloomFilter old_bloomfilter = *new_bloomfilter; 141 | // (Charlie): filter just by xid 142 | std::string node_id = global_xid->Get(); // local_node_info->id(); 143 | new_bloomfilter->Add(gossip::RumorIdentity(message.id(), node_id).ToString()); 144 | transport::protobuf::RoutingMessage send_message = message; 145 | std::for_each(neighbors.begin(), neighbors.end(), 146 | [&](kadmlia::NodeInfoPtr node_info_ptr) { 147 | if (!node_info_ptr) { 148 | TOP_WARN("kadmlia::NodeInfoPtr Is Empty."); 149 | return false; 150 | } 151 | gossip::RumorIdentity rumor_identity(message.id(), node_info_ptr->xid); 152 | std::string rumor_key = rumor_identity.ToString(); 153 | new_bloomfilter->Add(rumor_key); 154 | return true; 155 | }); 156 | const std::vector& bloomfilter_vec = new_bloomfilter->Uint64Vector(); 157 | send_message.clear_bloomfilter(); 158 | for (uint32_t i = 0; i < bloomfilter_vec.size(); ++i) { 159 | send_message.add_bloomfilter(bloomfilter_vec[i]); 160 | } 161 | std::for_each(neighbors.begin(), neighbors.end(), 162 | [&](kadmlia::NodeInfoPtr node_info_ptr) { 163 | if (!node_info_ptr) { 164 | TOP_WARN("kadmlia::NodeInfoPtr is invalid"); 165 | return false; 166 | } 167 | std::string peer_ip = node_info_ptr->public_ip; 168 | uint16_t peer_port = node_info_ptr->public_port; 169 | if (send_message.src_node_id() == node_info_ptr->xid || 170 | send_message.src_node_id() == node_info_ptr->node_id) { 171 | TOP_DEBUG("filter the id[%s] whitch is same as src node[%s].", 172 | node_info_ptr->node_id.c_str(), 173 | send_message.src_node_id().c_str()); 174 | return true; 175 | } 176 | std::string dest_node_id = node_info_ptr->xid; 177 | if (dest_node_id.empty()) { 178 | return false; 179 | } 180 | gossip::RumorIdentity rumor_identity(send_message.id(), dest_node_id); 181 | std::string rumor_key = rumor_identity.ToString(); 182 | if (old_bloomfilter.Contain(rumor_key)) { 183 | return false; 184 | } 185 | TOP_DEBUG("gossip message ip: %s, port: %d, [%d]", 186 | peer_ip.c_str(), peer_port, message.type()); 187 | if (kadmlia::kKadSuccess != kad_routing_table_->SendData(send_message, peer_ip, peer_port)) { 188 | TOP_WARN("SendData Failed,ip:%s,port:%d", peer_ip.c_str(), peer_port); 189 | return false; 190 | } 191 | return true; 192 | }); 193 | } 194 | 195 | void RumorHandler::SpreadNeighborsRapid( 196 | transport::protobuf::RoutingMessage& message) { 197 | std::vector all_neighbors; 198 | GetAllNeighborNodes(all_neighbors); 199 | return SpreadNeighbors(message, all_neighbors); 200 | } 201 | 202 | void RumorHandler::SpreadNeighborsSelfMessage() { 203 | if (0 == message_manager_ptr_->GetMessageCount()) { 204 | TOP_DEBUG("kadmlia::Rumor Message Is Empty"); 205 | return; 206 | } 207 | std::vector all_messages; 208 | message_manager_ptr_->GetAllMessages(all_messages); 209 | std::vector all_neighbors; 210 | GetAllNeighborNodes(all_neighbors); 211 | for (auto& message : all_messages) { 212 | SpreadNeighbors(message, all_neighbors); 213 | } 214 | } 215 | 216 | bool RumorHandler::SendToClosestNode( 217 | const transport::protobuf::RoutingMessage& in_message) { 218 | if (!kad_routing_table_) { 219 | TOP_WARN("kadmlia::RoutingTable is invalid"); 220 | return false; 221 | } 222 | if (in_message.src_node_id().empty()) { 223 | TOP_WARN("src node id is not given."); 224 | return false; 225 | } 226 | transport::protobuf::RoutingMessage message = in_message; 227 | kad_routing_table_->SendToClosestNode(message); 228 | return true; 229 | } 230 | 231 | std::shared_ptr RumorHandler::LocalNodeInfo() const { 232 | if (!kad_routing_table_) { 233 | TOP_WARN("kadmlia::RoutingTable is invalid"); 234 | return {}; 235 | } 236 | return kad_routing_table_->get_local_node_info(); 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /src/kad_message_handler.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xkad/routing_table/kad_message_handler.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "xpbase/base/line_parser.h" 13 | #include "xpbase/base/top_utils.h" 14 | #include "xpbase/base/top_log.h" 15 | #include "xpbase/base/multirelay_log.h" 16 | #include "xtransport/transport_message_register.h" 17 | #include "xkad/routing_table/routing_utils.h" 18 | #include "xkad/routing_table/callback_manager.h" 19 | #include "xkad/routing_table/node_info.h" 20 | #include "xkad/routing_table/routing_table.h" 21 | #include "xkad/routing_table/node_detection_manager.h" 22 | #include "xkad/routing_table/client_node_manager.h" 23 | #include "xkad/routing_table/local_node_info.h" 24 | 25 | namespace top { 26 | 27 | namespace kadmlia { 28 | 29 | KadMessageHandler::KadMessageHandler() {} 30 | 31 | KadMessageHandler::~KadMessageHandler() {} 32 | 33 | void KadMessageHandler::Init() { 34 | AddBaseHandlers(); 35 | } 36 | 37 | void KadMessageHandler::set_routing_ptr(std::shared_ptr routing_ptr) { 38 | assert(routing_ptr); 39 | routing_ptr_ = routing_ptr; 40 | } 41 | 42 | void KadMessageHandler::AddBaseHandlers() { 43 | message_manager_->RegisterMessageProcessor(kKadConnectRequest, [this]( 44 | transport::protobuf::RoutingMessage& message, 45 | base::xpacket_t& packet){ 46 | HandleConnectRequest(message, packet); 47 | }); 48 | message_manager_->RegisterMessageProcessor(kKadHandshake, [this]( 49 | transport::protobuf::RoutingMessage& message, 50 | base::xpacket_t& packet){ 51 | HandleHandshake(message, packet); 52 | }); 53 | message_manager_->RegisterMessageProcessor(kKadBootstrapJoinRequest, [this]( 54 | transport::protobuf::RoutingMessage& message, 55 | base::xpacket_t& packet){ 56 | HandleBootstrapJoinRequest(message, packet); 57 | }); 58 | message_manager_->RegisterMessageProcessor(kKadBootstrapJoinResponse, [this]( 59 | transport::protobuf::RoutingMessage& message, 60 | base::xpacket_t& packet){ 61 | HandleBootstrapJoinResponse(message, packet); 62 | }); 63 | message_manager_->RegisterMessageProcessor(kKadFindNodesRequest, [this]( 64 | transport::protobuf::RoutingMessage& message, 65 | base::xpacket_t& packet){ 66 | HandleFindNodesRequest(message, packet); 67 | }); 68 | message_manager_->RegisterMessageProcessor(kKadFindNodesResponse, [this]( 69 | transport::protobuf::RoutingMessage& message, 70 | base::xpacket_t& packet){ 71 | HandleFindNodesResponse(message, packet); 72 | }); 73 | message_manager_->RegisterMessageProcessor(kKadHeartbeatRequest, [this]( 74 | transport::protobuf::RoutingMessage& message, 75 | base::xpacket_t& packet){ 76 | HandleHeartbeatRequest(message, packet); 77 | }); 78 | message_manager_->RegisterMessageProcessor(kKadHeartbeatResponse, [this]( 79 | transport::protobuf::RoutingMessage& message, 80 | base::xpacket_t& packet){ 81 | HandleHeartbeatResponse(message, packet); 82 | }); 83 | message_manager_->RegisterMessageProcessor(kKadAck, []( 84 | transport::protobuf::RoutingMessage& message, 85 | base::xpacket_t& packet){ 86 | }); 87 | message_manager_->RegisterMessageProcessor(kKadNatDetectRequest, [this]( 88 | transport::protobuf::RoutingMessage& message, 89 | base::xpacket_t& packet){ 90 | nat_manager_->PushMessage(message, packet); 91 | }); 92 | message_manager_->RegisterMessageProcessor(kKadNatDetectResponse, [this]( 93 | transport::protobuf::RoutingMessage& message, 94 | base::xpacket_t& packet){ 95 | nat_manager_->PushMessage(message, packet); 96 | }); 97 | message_manager_->RegisterMessageProcessor(kKadNatDetectHandshake2Node, [this]( 98 | transport::protobuf::RoutingMessage& message, 99 | base::xpacket_t& packet){ 100 | nat_manager_->PushMessage(message, packet); 101 | }); 102 | message_manager_->RegisterMessageProcessor(kKadNatDetectHandshake2Boot, [this]( 103 | transport::protobuf::RoutingMessage& message, 104 | base::xpacket_t& packet){ 105 | nat_manager_->PushMessage(message, packet); 106 | }); 107 | message_manager_->RegisterMessageProcessor(kKadNatDetectFinish, [this]( 108 | transport::protobuf::RoutingMessage& message, 109 | base::xpacket_t& packet){ 110 | nat_manager_->PushMessage(message, packet); 111 | }); 112 | } 113 | 114 | int KadMessageHandler::HandleClientMessage( 115 | transport::protobuf::RoutingMessage& message, 116 | base::xpacket_t& packet) { 117 | if (!message.has_client_id()) { 118 | return kContinue; 119 | } 120 | 121 | LocalNodeInfoPtr local_node = routing_ptr_->get_local_node_info(); 122 | if (!local_node) { 123 | TOP_ERROR("get routing table by next service type[%llu] failed!", 124 | message.des_service_type()); 125 | return kKadFailed; 126 | } 127 | 128 | if (!message.relay_flag()) { 129 | if (message.client_id() == local_node->id()) { 130 | return kContinue; 131 | } 132 | 133 | ClientNodeInfoPtr client_node_ptr; 134 | client_node_ptr.reset(new ClientNodeInfo(message.client_id())); 135 | client_node_ptr->public_ip = packet.get_from_ip_addr(); 136 | client_node_ptr->public_port = packet.get_from_ip_port(); 137 | ClientNodeManager::Instance()->AddClientNode(client_node_ptr); // just cover 138 | if (message.has_xid() && !message.xid().empty()) { 139 | ClientNodeInfoPtr client_node_ptr; 140 | client_node_ptr.reset(new ClientNodeInfo(message.xid())); 141 | client_node_ptr->public_ip = packet.get_from_ip_addr(); 142 | client_node_ptr->public_port = packet.get_from_ip_port(); 143 | ClientNodeManager::Instance()->AddClientNode(client_node_ptr); // just cover 144 | } 145 | message.set_relay_flag(true); 146 | message.set_src_node_id(local_node->id()); 147 | return kContinue; 148 | } 149 | 150 | if (message.des_node_id() != local_node->id()) { 151 | return kContinue; 152 | } 153 | 154 | // request message arrive des node or response message arrive the first relay node 155 | ClientNodeInfoPtr client_node_ptr = ClientNodeManager::Instance()->FindClientNode( 156 | message.client_id()); 157 | if (!client_node_ptr) { 158 | TOP_DEBUG("client[%s] request message arrive this dest node[%s]", 159 | HexEncode(message.client_id()).c_str(), 160 | HexEncode(local_node->id()).c_str()); 161 | return kContinue; 162 | } 163 | TOP_DEBUG("response message of client[%s] arrive this first relay node[%s]", 164 | HexEncode(message.client_id()).c_str(), 165 | HexEncode(local_node->id()).c_str()); 166 | 167 | std::string client_pub_ip = client_node_ptr->public_ip; 168 | uint16_t client_pub_port = client_node_ptr->public_port; 169 | message.set_relay_flag(false); 170 | message.set_des_node_id(client_node_ptr->node_id); 171 | return routing_ptr_->SendData(message, client_pub_ip, client_pub_port); 172 | } 173 | 174 | void KadMessageHandler::HandleHeartbeatRequest( 175 | transport::protobuf::RoutingMessage& message, 176 | base::xpacket_t& packet) { 177 | routing_ptr_->HandleHeartbeatRequest(message, packet); 178 | } 179 | 180 | void KadMessageHandler::HandleHeartbeatResponse( 181 | transport::protobuf::RoutingMessage& message, 182 | base::xpacket_t& packet) { 183 | routing_ptr_->HandleHeartbeatResponse(message, packet); 184 | } 185 | 186 | void KadMessageHandler::SendAck( 187 | transport::protobuf::RoutingMessage& message, 188 | base::xpacket_t& packet) { 189 | transport::protobuf::RoutingMessage res_message; 190 | routing_ptr_->SetFreqMessage(res_message); 191 | LocalNodeInfoPtr local_node = routing_ptr_->get_local_node_info(); 192 | if (!local_node) { 193 | return; 194 | } 195 | 196 | res_message.set_src_service_type(message.des_service_type()); 197 | res_message.set_des_service_type(message.src_service_type()); 198 | res_message.set_des_node_id(message.src_node_id()); 199 | res_message.set_type(kKadAck); 200 | res_message.set_id(0); 201 | res_message.set_ack_id(message.ack_id()); 202 | routing_ptr_->SendData(res_message, packet.get_from_ip_addr(), packet.get_from_ip_port()); 203 | } 204 | 205 | void KadMessageHandler::HandleFindNodesRequest( 206 | transport::protobuf::RoutingMessage& message, 207 | base::xpacket_t& packet) { 208 | routing_ptr_->HandleFindNodesRequest(message, packet); 209 | } 210 | 211 | void KadMessageHandler::HandleFindNodesResponse( 212 | transport::protobuf::RoutingMessage& message, 213 | base::xpacket_t& packet) { 214 | routing_ptr_->HandleFindNodesResponse(message, packet); 215 | } 216 | 217 | void KadMessageHandler::HandleBootstrapJoinRequest( 218 | transport::protobuf::RoutingMessage& message, 219 | base::xpacket_t& packet) { 220 | routing_ptr_->HandleBootstrapJoinRequest(message, packet); 221 | } 222 | 223 | void KadMessageHandler::HandleBootstrapJoinResponse( 224 | transport::protobuf::RoutingMessage& message, 225 | base::xpacket_t& packet) { 226 | routing_ptr_->HandleBootstrapJoinResponse(message, packet); 227 | } 228 | 229 | void KadMessageHandler::HandleHandshake( 230 | transport::protobuf::RoutingMessage& message, 231 | base::xpacket_t& packet) { 232 | routing_ptr_->HandleHandshake(message, packet); 233 | } 234 | 235 | void KadMessageHandler::HandleConnectRequest( 236 | transport::protobuf::RoutingMessage& message, 237 | base::xpacket_t& packet) { 238 | routing_ptr_->HandleConnectRequest(message, packet); 239 | } 240 | 241 | } // namespace kadmlia 242 | 243 | } // namespace top 244 | --------------------------------------------------------------------------------