void SearchTask::start() { WriteLog(LOG_SECTION("Start search task ID #" << _id)); if (_possible_contacts.empty()) { const uint128_t distance = _id ^ Kad::get_instance().get_client_id(); RoutingTable::get_instance().get_nearest_contacts(JUST_CREATED, _id, distance, 50, _possible_contacts); } // If we have some contacts to send the request to, let's do it if (!_possible_contacts.empty()) { std::list<const Contact *>::iterator contIt = _possible_contacts.begin(); for (uint32_t i = 0; i < get_req_count(); i++) { const Contact *contact = *contIt++; // Move the contact to the used ones _possible_contacts.pop_front(); _used_contacts.push_back(contact); Kad::get_instance().send_request(contact, get_res_count(), _id); } } else { WriteLog("We have no contacts to send the request to"); } WriteLog(LOG_SECTION("Start search task is over")); }
error::errors start_p2p_engine( char const * gid, char const * pid, char const * auth) { LOG_SECTION(); error_code ec; if (is_started()) { ec = already_start; } else { #ifndef PPBOX_DISABLE_CERTIFY ppbox::certify::Certifier & cert = util::daemon::use_module<ppbox::certify::Certifier>(*this); cert.set_auth_code(gid, pid, auth); #endif #ifndef PPBOX_DISABLE_DAC ppbox::dac::DacModule & dac = util::daemon::use_module<ppbox::dac::DacModule>(*this); dac.set_auth_code(gid, pid, auth); #endif ec = start(1); } return last_error(__FUNCTION__, ec); }
void SearchTask::push_search() { WriteLog(LOG_SECTION("Pushing search task ID #" << _id)); if(!_possible_contacts.empty()) { const Contact* contact = *(_possible_contacts.begin()); _possible_contacts.erase(_possible_contacts.begin()); _used_contacts.push_back(contact); Kad::get_instance().send_request(contact, get_res_count(), _id); } else { // By changing the creation time, we'll cheat in order to get deleted WriteLog("We have no contacts to send the request to"); _creation_time = get_current_time() - get_timeout(); } WriteLog(LOG_SECTION("End pushing search task ID #" << _id)); }
error::errors stop_p2p_engine() { LOG_SECTION(); error_code ec; if (!is_started()) { ec = not_start; } else { stop(); } return last_error(__FUNCTION__, ec); }
void HttpProxy::handle_watch( boost::system::error_code const & ec) { LOG_SECTION(); LOG_DEBUG("[handle_watch] (id = %u, status = %s, ec = %s)" %id_ % state_str[state_] % ec.message()); if (state_ == exiting) { delete this; } else if (state_ == stopped) { // restart watch_state_ = watch_stopped; start(); } else if (ec && ec != boost::asio::error::eof && ec != boost::asio::error::operation_aborted) { watch_state_ = broken; on_broken_pipe(); } else { watch_state_ = watch_stopped; } }
void HttpProxy::handle_async( boost::system::error_code const & ec, Size const & bytes_transferred) { LOG_SECTION(); LOG_DEBUG("[handle_async] (id = %u, status = %s, ec = %s, bytes_transferred = %s)" %id_ % state_str[state_] % ec.message() % bytes_transferred.to_string()); if (watch_state_ == broken) { on_finish(); delete this; return; } if (ec) { if (state_ == receiving_request_head) { error_code ec1; response_.clear_data(); bool block = !get_non_block(ec1); if (block) set_non_block(true, ec1); boost::asio::read(*this, response_.data(), boost::asio::transfer_at_least(4096), ec1); if (block) set_non_block(false, ec1); LOG_DATA(framework::logger::Debug, ("receiving_request_head", response_.data().data())); } on_error(ec); switch (state_) { case receiving_request_head: case transferring_request_data: case sending_response_head: case transferring_response_data: on_finish(); state_ = exiting; if (watch_state_ == watching) { error_code ec1; HttpSocket::cancel(ec1); } else { delete this; } break; case local_processing: if (is_local() && !response_.head().content_length.is_initialized() && bytes_transferred.is_size_t()) { response_.head().content_length.reset(bytes_transferred.get_size_t()); } case preparing: case connectting: case sending_request_head: case receiving_response_head: state_ = sending_response_head; response_error(ec, boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; default: assert(0); break; } return; } switch (state_) { case stopped: state_ = receiving_request_head; response_.head() = HttpResponseHead(); async_read(request_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case receiving_request_head: state_ = preparing; if (watch_state_ == watch_stopped && request_.head().content_length.get_value_or(0) == 0) { watch_state_ = watching; async_read_some(boost::asio::null_buffers(), boost::bind(&HttpProxy::handle_watch, this, _1)); } on_receive_request_head( request_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case preparing: if (bytes_transferred.get_bool()) { if (!http_to_server_) http_to_server_ = new HttpSocket(get_io_service()); state_ = connectting; http_to_server_->async_connect(request_.head().host.get(), boost::bind(&HttpProxy::handle_async, this, _1, Size())); } else { state_ = transferring_request_data; transfer_request_data( boost::bind(&HttpProxy::handle_async, this, _1, _2)); } break; case connectting: state_ = sending_request_head; http_to_server_->async_write(request_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case sending_request_head: state_ = transferring_request_data; transfer_request_data( boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case transferring_request_data: if (is_local()) { on_receive_request_data(transfer_buf_); transfer_buf_.consume(transfer_buf_.size()); } state_ = local_processing; if (watch_state_ == watch_stopped) { watch_state_ = watching; async_read_some(boost::asio::null_buffers(), boost::bind(&HttpProxy::handle_watch, this, _1)); } response_.head().connection = request_.head().connection; local_process( boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case local_processing: if (is_local()) { state_ = receiving_response_head; on_receive_response_head(response_.head()); if (!response_.head().content_length.is_initialized()) { if (bytes_transferred.is_size_t()) response_.head().content_length.reset(bytes_transferred.get_size_t()); else response_.head().connection.reset(http_field::Connection()); } if (!response_.head().connection.is_initialized()) { response_.head().connection.reset(http_field::Connection()); } handle_async(ec, Size()); } else { state_ = receiving_response_head; http_to_server_->async_read(response_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); } break; case receiving_response_head: if (!is_local()) { on_receive_response_head(response_.head()); if (!response_.head().connection.is_initialized()) { response_.head().connection.reset(http_field::Connection()); } if (response_.head().err_msg.empty()) response_.head().err_msg = "OK"; } state_ = sending_response_head; async_write(response_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case sending_response_head: state_ = transferring_response_data; transfer_response_data( boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case transferring_response_data: on_finish(); if (!response_.head().connection || response_.head().connection.get() == http_field::Connection::close) { state_ = exiting; if (watch_state_ != watching) { delete this; } else { error_code ec; shutdown(boost::asio::socket_base::shutdown_send, ec); boost::asio::ip::tcp::socket::cancel(ec); } } else { state_ = stopped; if (watch_state_ != watching) { // restart watch_state_ = watch_stopped; handle_async(ec, Size()); } else { error_code ec; boost::asio::ip::tcp::socket::cancel(ec); } } break; default: assert(0); break; } }
void RoutingTable::maintain_table() { WriteLog(LOG_SECTION("Routing table maintenance")); time_t now = get_current_time(); std::list<KBucket *> kBuckets_list; RoutingTable::get_instance().get_all_kBuckets(kBuckets_list); /* * Remove all the expired contacts */ for(std::list<KBucket *>::iterator kIt = kBuckets_list.begin(); kIt != kBuckets_list.end(); kIt++) { KBucket *kBucket = *kIt; std::list<Contact *> contact_list; kBucket->get_contact_list(contact_list); for(std::list<Contact *>::const_iterator contIt = contact_list.begin(); contIt != contact_list.end(); contIt++) { // Perfect, we have a contact: is it still alive? const Contact *contact = *contIt; // Is this contact doomed to deletion? Is the expiration date already gone? if((contact->get_type() == PROMPTED_FOR_DELETION) && ((contact->get_expiration() > 0) && (contact->get_expiration() <= now))) { WriteLog(*contact << " expired. Removing!"); // It was: delete it kBucket->remove(contact); continue; } } // Looking for the oldest one: maybe it's time to refresh it Contact *contact = kBucket->get_oldest_contact(); // Maybe we already sent a request to this one or, anyway, it has an expiration date if(contact != NULL && (contact->get_expiration() >= now || contact->get_type() == PROMPTED_FOR_DELETION)) { // "Promote" it in order to not catch it again at the next step kBucket->make_youngest(contact); contact = NULL; } if(contact != NULL) { Kad::get_instance().send_hello_request(contact, false); // It has 2 minutes to reply, otherwise there's the accelerated aging contact->fast_aging(); } } /* * Try to merge leaves every 45 minutes */ if(now - _last_leaves_merge >= 45 * 60) { _last_leaves_merge = now; _root->merge_leaves(); } WriteLog(LOG_SECTION("Routing table maintenance is over: " << LOG_CYAN << RoutingTable::get_instance().get_num_contacts() << LOG_RESETCOLOR << " contacts in the RT.")); }
void SearchTask::process_response(uint32_t ip_address, uint16_t udp_port, std::list<Contact*>& results) { WriteLog(LOG_SECTION("Start processing search ID #" << _id)); uint128_t distance; const Contact *from_contact = NULL; for(std::list<const Contact*>::const_iterator contIt = _used_contacts.begin(); contIt != _used_contacts.end(); contIt++) { const Contact *contact = *contIt; if(contact->get_ip_address() == ip_address && contact->get_udp_port() == udp_port) { distance = contact->get_distance(); from_contact = contact; break; } } // As the results have been already inserted by the Kad process, we're not interested in results (here) if(_type == FIND_NODE) { _possible_contacts.clear(); return; } if(from_contact == NULL || from_contact != NULL) assert(false); /* std::list<const Contact*> alpha; for(std::list<Contact*>::const_iterator contIt = results.begin(); contIt != results.end(); contIt++) { const Contact* contact = *contIt; bool should_be_skipped = false; for(std::list<const Contact*>::const_iterator usedContIt = _used_contacts.begin(); usedContIt != _used_contacts.end(); usedContIt++) { if((*usedContIt)->get_contact_id() == contact->get_contact_id()) should_be_skipped = true; } // If this one should be skipped, then skip it if(should_be_skipped) continue; for(std::list<const Contact*>::const_iterator possContIt = _possible_contacts.begin(); possContIt != _possible_contacts.end(); possContIt++) { if((*possContIt)->get_contact_id() == contact->get_contact_id()) should_be_skipped = true; } // If this one should be skipped, then skip it if(should_be_skipped) continue; if(in_tolerance_zone(contact->get_contact_id() ^ Kad::get_instance().get_client_id(), _id ^ Kad::get_instance().get_client_id(), TOLERANCE)) { alpha.push_back(contact); } else { WriteLog("Adding " << *contact << " to the contactable ones list"); _possible_contacts.push_back(contact); } } // Send again the request to these guys if(alpha.size() > 0) { for(std::list<const Contact*>::const_iterator contIt = alpha.begin(); contIt != alpha.end(); contIt++) { _used_contacts.push_back(*contIt); Kad::get_instance().send_request(*contIt, get_res_count(), _id); } } */ WriteLog(LOG_SECTION("End processing search ID #" << _id)); }