bool message_udp::recv::host_list::recv(const net::buffer & recv_buf, const net::endpoint & endpoint) { if(!expect(recv_buf)){ return false; } std::string remote_ID(convert::bin_to_hex(std::string( reinterpret_cast<const char *>(recv_buf.data())+5, 20))); bit_field BF(recv_buf.data()+25, 2, 16); std::list<net::endpoint> hosts; unsigned offset = protocol_udp::host_list_size; for(unsigned x=0; x<16 && offset != recv_buf.size(); ++x){ if(BF[x] == 0){ //IPv4 boost::optional<net::endpoint> ep = net::bin_to_endpoint( recv_buf.str(offset, 4), recv_buf.str(offset + 4, 2)); if(ep){ hosts.push_back(*ep); } offset += 6; }else{ //IPv6 boost::optional<net::endpoint> ep = net::bin_to_endpoint( recv_buf.str(offset, 16), recv_buf.str(offset + 16, 2)); if(ep){ hosts.push_back(*ep); } offset += 18; } } func(endpoint, remote_ID, hosts); return true; }
void connection::write(const net::buffer& data) { if(m_service.check_this_loop()){ write_in_loop(data.data(),data.size()); }else{ m_service.run_task( boost::bind(&connection::write_in_loop,this,data.data(),data.size()) ); } }
bool message_udp::recv::store_node::recv(const net::buffer & recv_buf, const net::endpoint & endpoint) { if(!expect(recv_buf)){ return false; } net::buffer random(recv_buf.data()+1, 4); std::string remote_ID(convert::bin_to_hex(std::string( reinterpret_cast<const char *>(recv_buf.data())+5, 20))); func(endpoint, random, remote_ID); return true; }
bool message_udp::recv::node_list::recv(const net::buffer & recv_buf, const net::endpoint & endpoint) { if(!expect(recv_buf)){ return false; } net::buffer random(recv_buf.data()+1, 4); std::string remote_ID(convert::bin_to_hex(std::string( reinterpret_cast<const char *>(recv_buf.data())+5, 20))); std::list<std::string> nodes; unsigned offset = protocol_udp::node_list_size; for(unsigned x=0; x<16 && offset != recv_buf.size(); ++x){ nodes.push_back(convert::bin_to_hex(std::string( reinterpret_cast<const char *>(recv_buf.data())+offset, 20))); offset += 20; } func(endpoint, random, remote_ID, nodes); return true; }
bool message_udp::recv::pong::expect(const net::buffer & recv_buf) { if(recv_buf.size() != protocol_udp::pong_size){ return false; } if(recv_buf[0] != protocol_udp::pong){ return false; } return std::memcmp(recv_buf.data()+1, random.data(), 4) == 0; }
bool encryption::recv_p_rA(const net::buffer & buf) { assert(enable_recv_p_rA); set_enable_false(); enable_send_rB = true; assert(buf.size() == protocol_tcp::DH_key_size * 2); p = mpa::mpint(buf.data(), protocol_tcp::DH_key_size); if(!mpa::is_prime(p)){ return false; } remote_result = mpa::mpint(buf.data() + protocol_tcp::DH_key_size, protocol_tcp::DH_key_size); local_result = mpa::exptmod(g, s, p); shared_key = mpa::exptmod(remote_result, s, p); std::string bin = shared_key.bin(protocol_tcp::DH_key_size); PRNG_send.seed(reinterpret_cast<const unsigned char *>(bin.data()), bin.size()); PRNG_recv.seed(reinterpret_cast<const unsigned char *>(bin.data()), bin.size()); return true; }
bool message_udp::recv::node_list::expect(const net::buffer & recv_buf) { if(recv_buf.size() < protocol_udp::node_list_size){ return false; } if(recv_buf[0] != protocol_udp::node_list){ return false; } if((recv_buf.size() - protocol_udp::node_list_size) % 20 != 0){ return false; } return std::memcmp(recv_buf.data()+1, random.data(), 4) == 0; }
bool message_udp::recv::host_list::expect(const net::buffer & recv_buf) { //check minimum size if(recv_buf.size() < protocol_udp::host_list_size || recv_buf.size() > 508){ return false; } //check command if(recv_buf[0] != protocol_udp::host_list){ return false; } //check random if(std::memcmp(recv_buf.data()+1, random.data(), 4) != 0){ return false; } //verify address list makes sense bit_field BF(recv_buf.data()+25, 2, 16); unsigned offset = protocol_udp::host_list_size; for(unsigned x=0; x<16 && offset != recv_buf.size(); ++x){ if(BF[x] == 0){ //IPv4 if(recv_buf.size() < offset + 6){ return false; } offset += 6; }else{ //IPv6 if(recv_buf.size() < offset + 18){ return false; } offset += 18; } } //check if longer than expected if(offset != recv_buf.size()){ return false; } return true; }
void encryption::recv_rB(const net::buffer & buf) { assert(enable_recv_rB); set_enable_false(); enable_crypt = true; assert(buf.size() == protocol_tcp::DH_key_size); remote_result = mpa::mpint(buf.data(), protocol_tcp::DH_key_size); shared_key = mpa::exptmod(remote_result, s, p); std::string bin = shared_key.bin(protocol_tcp::DH_key_size); PRNG_send.seed(reinterpret_cast<const unsigned char *>(bin.data()), bin.size()); PRNG_recv.seed(reinterpret_cast<const unsigned char *>(bin.data()), bin.size()); }