Skip to content

Commit

Permalink
added nat detection
Browse files Browse the repository at this point in the history
  • Loading branch information
bytemaster committed Sep 10, 2012
1 parent aaaff0f commit 8295a82
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 30 deletions.
3 changes: 2 additions & 1 deletion include/tornet/connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace tn {
node_id get_remote_id()const;
uint8_t get_remote_rank()const;
state_enum get_state()const;
bool is_behind_nat()const;

// return false if state transitioned to failed, otherwise true
bool auto_advance();
Expand Down Expand Up @@ -121,7 +122,7 @@ namespace tn {
void goto_state( state_enum s );

class impl;
fc::fwd<impl,680> my;
fc::fwd<impl,696> my;
};
}

Expand Down
6 changes: 4 additions & 2 deletions include/tornet/host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ namespace tn {
struct host {
host(){}
host( const fc::sha1& _id, const fc::ip::endpoint& _ep ):id(_id),ep(_ep){}
fc::sha1 id;
fc::ip::endpoint ep;
fc::sha1 id;
fc::ip::endpoint ep;
// any hosts required to perform nat handshake on intro.
fc::vector<fc::ip::endpoint> nat_hosts;
};
}
#endif
5 changes: 5 additions & 0 deletions include/tornet/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ namespace tn {
*/
void close_service( uint16_t service_channel_num );

/**
* @return the endpoint that our UDP packets come from.
*/
fc::ip::endpoint local_endpoint( const fc::ip::endpoint& dest = fc::ip::endpoint() )const;

private:
friend class connection;
void update_dist_index( const id_type& id, connection* c );
Expand Down
80 changes: 56 additions & 24 deletions src/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@

namespace tn {

typedef std::map<fc::sha1,fc::ip::endpoint> route_table;
typedef fc::vector<host> route_table;
class connection::impl {
public:
impl( node& n ):_node(n){}
impl( node& n ):_node(n),_behind_nat(false){}

uint16_t _advance_count;
node& _node;
Expand All @@ -38,15 +38,17 @@ namespace tn {

node_id _remote_id;
fc::ip::endpoint _remote_ep;
fc::ip::endpoint _public_ep; // endpoint remote host reported seeing from us
bool _behind_nat;


std::map<node_id,fc::promise<route_table>::ptr> _route_lookups;
std::map<node_id,fc::promise<route_table>::ptr> _route_lookups;


boost::unordered_map<std::string,fc::any> _cached_objects;
boost::unordered_map<uint32_t,channel> _channels;
db::peer::ptr _peers;
db::peer::record _record;
boost::unordered_map<std::string,fc::any> _cached_objects;
boost::unordered_map<uint32_t,channel> _channels;
db::peer::ptr _peers;
db::peer::record _record;
};
const db::peer::record& connection::get_db_record()const { return my->_record; }

Expand Down Expand Up @@ -326,7 +328,8 @@ bool connection::decode_packet( const tn::buffer& b ) {
return true;
}

/// sha1(target_id) << uint32_t(num)
/// Message In: sha1(target_id) << uint32_t(num)
/// Message Out: sha1(target_id) << uint32_t(num) << *(dist << ip << port << uin8_t(is_nat) )
bool connection::handle_lookup_msg( const tn::buffer& b ) {
node_id target; uint32_t num; uint8_t l=0; node_id limit;
{
Expand All @@ -337,6 +340,8 @@ bool connection::handle_lookup_msg( const tn::buffer& b ) {
// if( l ) ds >> limit;
}
fc::vector<host> r = my->_node.find_nodes_near( target, num, limit );

// TODO: put this on the stack to eliminate heap alloc
fc::vector<char> rb; rb.resize(2048);

num = r.size();
Expand All @@ -349,13 +354,16 @@ bool connection::handle_lookup_msg( const tn::buffer& b ) {
for( uint32_t i = 0; i < num; ++i ) {
// slog( "Reply with %1% @ %2%:%3%", itr->first, itr->second.address().to_string(), itr->second.port() );
ds << itr->id << uint32_t(itr->ep.get_address()) << uint16_t(itr->ep.port());
ds << uint8_t( itr->nat_hosts.size() );
++itr;
}
send( &rb.front(), ds.tellp(), route_msg );

return true;
}
// uint16_t(num) << (sha1(distance) << uint32_t(ip) << uint16_t(port))*


/// Message IN: sha1(target_id) << uint32_t(num) << *(dist << ip << port << uin8_t(is_nat) )
bool connection::handle_route_msg( const tn::buffer& b ) {
node_id target; uint32_t num;
fc::datastream<const char*> ds(b.data(), b.size() );
Expand All @@ -369,10 +377,13 @@ bool connection::handle_route_msg( const tn::buffer& b ) {

// unpack the routing table
route_table rt;
rt.reserve(num);
node_id dist; uint32_t ip; uint16_t port;
uint8_t is_nat = 0;
for( uint32_t i = 0; i < num; ++i ) {
ds >> dist >> ip >> port;
rt[dist] = fc::ip::endpoint( ip, port );
ds >> dist >> ip >> port >> is_nat;
rt.push_back( host( dist, fc::ip::endpoint( ip, port ) ) );
if( is_nat ) rt.back().nat_hosts.push_back( my->_remote_ep );
// slog( "Response of dist: %1% @ %2%:%3%", dist, boost::asio::ip::address_v4((unsigned long)(ip)).to_string(), port );
}
slog( "set_value..." );
Expand Down Expand Up @@ -413,7 +424,9 @@ bool connection::handle_data_msg( const tn::buffer& b ) {
}

/**
* Returning false, is will send us back to uninit state
* Returning false, it will send us back to uninit state
*
* sig pub_key utc nonce[2] ip port
*/
bool connection::handle_auth_msg( const tn::buffer& b ) {
slog( "" );
Expand All @@ -424,6 +437,10 @@ bool connection::handle_auth_msg( const tn::buffer& b ) {

fc::datastream<const char*> ds( b.data(), b.size() );
ds >> sig >> pubk >> utc_us >> remote_nonce[0] >> remote_nonce[1];
uint32_t rip;
uint16_t rport;
ds >> rip >> rport;
my->_public_ep = fc::ip::endpoint( fc::ip::address(rip), rport );


fc::sha1::encoder sha;
Expand All @@ -437,6 +454,21 @@ bool connection::handle_auth_msg( const tn::buffer& b ) {
send_close();
return false;
} else {
if( my->_public_ep.get_address() != my->_remote_ep.get_address() ) {
wlog( "Behind NAT remote side reported %s but we received %s",
fc::string(my->_public_ep).c_str(),
fc::string(my->_remote_ep).c_str()
);
if( rport != my->_remote_ep.port() ) {
wlog( "Warning: NAT Port Rewrite!!" );
}
my->_behind_nat = true;
} else {
slog( "Public IP" );
my->_behind_nat = false;
}


slog( "Authenticated!" );

fc::sha1::encoder pkds; pkds << pubk;
Expand Down Expand Up @@ -506,7 +538,11 @@ void connection::send_dh() {
}

/**
* Creates a node authentication message.
* Creates a node authentication message. This message is used to prove that the
* node owns the public_key it claims. It also is used to report the IP:PORT
*
* sign( sha1(shared_key + utc) ) + pub_key + utc + nonce[2] + uint32_t(local_ip) + uint16_t(local_port)
*
*/
void connection::send_auth() {
slog("");
Expand All @@ -520,14 +556,15 @@ void connection::send_auth() {

fc::signature_t s = my->_node.sign( sha.result() );

char buf[sizeof(s)+sizeof(my->_node.pub_key())+sizeof(utc_us)+16];
char buf[sizeof(s)+sizeof(my->_node.pub_key())+sizeof(utc_us)+16 + 6];
//BOOST_ASSERT( sizeof(tmp) == ps.tellp() );

fc::datastream<char*> ds(buf,sizeof(buf));

// allocate buffer with unused space in front for header info and back for padding, send() will then use
// the extra space to put the encryption, pad, and type info.
ds << s << my->_node.pub_key() << utc_us << my->_node.nonce()[0] << my->_node.nonce()[1];
ds << uint32_t(my->_node.local_endpoint(my->_remote_ep).get_address()) << my->_node.local_endpoint().port();
send( buf, sizeof(buf), auth_msg );
}

Expand Down Expand Up @@ -684,6 +721,10 @@ void connection::send_auth() {

fc::ip::endpoint connection::get_endpoint()const { return my->_remote_ep; }

bool connection::is_behind_nat()const {
return my->_behind_nat;
}

/**
* Sends a message requesting a node lookup and waits up to 1s for a response. If no
* response in 1 second, then a timeout exception is thrown.
Expand Down Expand Up @@ -713,16 +754,7 @@ void connection::send_auth() {

assert( my->_route_lookups.end() == my->_route_lookups.find(target) );

fc::vector<tn::host> hosts;
hosts.reserve(rt.size());

auto i = rt.begin();
auto e = rt.end();
while( i != e ) {
hosts.push_back( tn::host( i->first, i->second ) );
++i;
}
return hosts;
return rt;
} catch( ... ) {
elog( "%s", fc::current_exception().diagnostic_information().c_str() );
auto ritr = my->_route_lookups.find(target);
Expand Down
4 changes: 2 additions & 2 deletions src/kad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ namespace tn {
void kad_search::search_thread() {
slog( "search thread.... queue size %d", m_search_queue.size() );
while( m_search_queue.size() && m_cur_status == kad_search::searching ) {
fc::ip::endpoint ep = m_search_queue.begin()->second;
fc::sha1 nid = m_search_queue.begin()->first ^ m_target;
fc::ip::endpoint ep = m_search_queue.begin()->second;
fc::sha1 nid = m_search_queue.begin()->first ^ m_target;
m_search_queue.erase(m_search_queue.begin());

try {
Expand Down
16 changes: 16 additions & 0 deletions src/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ namespace tn {
slog( " near push back .. " );
auto dist = (itr->first^my->_id)^target;
near.push_back( tn::host( dist, itr->second->get_endpoint() ) );
if( itr->second->is_behind_nat() ) {
near.back().nat_hosts.resize(1);
}
// TODO: apply search limit filter?
// if( limit != node::id_type() || dist < limit ) {
//slog( "dist: %1% target: %2%", dist, target );
Expand All @@ -171,6 +174,9 @@ namespace tn {
slog( " near push back .. " );
auto dist = (lb->first^my->_id)^target;
near.push_back( tn::host( dist, lb->second->get_endpoint() ) );
if( itr->second->is_behind_nat() ) {
near.back().nat_hosts.resize(1);
}
// TODO: apply search limit filter?
// if( limit != node::id_type() || dist < limit ) {
//slog( "dist: %1% target: %2%", dist, target );
Expand All @@ -191,6 +197,16 @@ namespace tn {



fc::ip::endpoint node::local_endpoint( const fc::ip::endpoint& dst )const {
auto ep = dst;
if( dst == fc::ip::endpoint() ) {
ep = fc::ip::endpoint( fc::ip::address("74.125.228.40"), 8000 );
}
my->_lookup_sock.connect( ep );
auto lp = my->_lookup_sock.local_endpoint();
lp.set_port( my->_sock.local_endpoint().port() );
return lp;
}


fc::vector<host> node::remote_nodes_near( const id_type& rnode, const id_type& target, uint32_t n,
Expand Down
4 changes: 3 additions & 1 deletion src/node_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace tn {
_done = false;
_rank = 0;
_nonce[0] = _nonce[1] = 0;
_lookup_sock.connect( fc::ip::endpoint( fc::ip::address("74.125.228.40"), 8000 ) );
}

node& _self;
Expand All @@ -65,11 +66,12 @@ namespace tn {
fc::public_key_t _pub_key;
service_set _services;
fc::udp_socket _sock;
fc::udp_socket _lookup_sock;
fc::future<void> _read_loop_complete;
ep_to_con_map _ep_to_con;
bool _done;
fc::path _datadir;
std::map<fc::sha1,connection*> _dist_to_con;
std::map<fc::sha1,connection*> _dist_to_con;

db::peer::ptr _peers;
db::publish::ptr _publish_db;
Expand Down

0 comments on commit 8295a82

Please sign in to comment.