예제 #1
0
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"));
}
예제 #2
0
파일: IPpbox.cpp 프로젝트: uvbs/MyProjects
    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);
    }
예제 #3
0
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));
}
예제 #4
0
파일: IPpbox.cpp 프로젝트: uvbs/MyProjects
    error::errors stop_p2p_engine()
    {
        LOG_SECTION();

        error_code ec;
        if (!is_started()) {
            ec = not_start;
        } else {
            stop();
        }

        return last_error(__FUNCTION__, ec);
    }
예제 #5
0
        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;
            }
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
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."));
}
예제 #8
0
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));
}