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::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; }
void encryption::crypt_send(net::buffer & send_buff, const int index) { assert(enable_crypt); for(int x=index; x<send_buff.size(); ++x){ send_buff[x] ^= PRNG_send.byte(); } }
void encryption::crypt_recv(net::buffer & recv_buff, const int index) { assert(enable_crypt); for(int x=index; x<recv_buff.size(); ++x){ recv_buff[x] ^= PRNG_recv.byte(); } }
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; }
//BEGIN send::host_list message_udp::send::host_list::host_list(const net::buffer & random, const std::string & local_ID, const std::list<net::endpoint> & hosts) { assert(random.size() == 4); assert(hosts.size() <= protocol_udp::host_list_elements); bit_field BF(16); unsigned cnt = 0; for(std::list<net::endpoint>::const_iterator it_cur = hosts.begin(), it_end = hosts.end(); it_cur != it_end; ++it_cur) { if(it_cur->version() == net::IPv4){ BF[cnt] = 0; }else{ BF[cnt] = 1; } ++cnt; } buf.append(protocol_udp::host_list) .append(random) .append(convert::hex_to_bin(local_ID)) .append(BF.get_buf()); //append addresses for(std::list<net::endpoint>::const_iterator it_cur = hosts.begin(), it_end = hosts.end(); it_cur != it_end; ++it_cur) { buf.append(it_cur->IP_bin()) .append(it_cur->port_bin()); } }
//BEGIN send::store_node message_udp::send::store_node::store_node(const net::buffer & random, const std::string & local_ID) { assert(random.size() == 4); assert(local_ID.size() == SHA1::hex_size); buf.append(protocol_udp::store_node) .append(random) .append(convert::hex_to_bin(local_ID)); }
bool message_udp::recv::find_node::expect(const net::buffer & recv_buf) { if(recv_buf.size() != protocol_udp::find_node_size){ return false; } if(recv_buf[0] != protocol_udp::find_node){ return false; } 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; }
//BEGIN send::query_file message_udp::send::query_file::query_file(const net::buffer & random, const std::string & local_ID, const std::string & hash) { assert(random.size() == 4); assert(local_ID.size() == SHA1::hex_size); assert(hash.size() == SHA1::hex_size); buf.append(protocol_udp::query_file) .append(random) .append(convert::hex_to_bin(local_ID)) .append(convert::hex_to_bin(hash)); }
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()); }
//BEGIN send::node_list message_udp::send::node_list::node_list(const net::buffer & random, const std::string & local_ID, const std::list<std::string> & nodes) { assert(random.size() == 4); assert(local_ID.size() == SHA1::hex_size); assert(nodes.size() <= protocol_udp::node_list_elements); buf.append(protocol_udp::node_list) .append(random) .append(convert::hex_to_bin(local_ID)); for(std::list<std::string>::const_iterator it_cur = nodes.begin(), it_end = nodes.end(); it_cur != it_end; ++it_cur) { assert(it_cur->size() == SHA1::hex_size); buf.append(convert::hex_to_bin(*it_cur)); } }
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 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::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; }
bool message_udp::recv::ping::expect(const net::buffer & recv_buf) { return recv_buf.size() == protocol_udp::ping_size && recv_buf[0] == protocol_udp::ping; }