コード例 #1
0
ファイル: ist.cpp プロジェクト: latinovic/galera
void galera::ist::Receiver::interrupt()
{
    gu::URI uri(recv_addr_);
    try
    {
        asio::ip::tcp::resolver::iterator i;
        try
        {
            asio::ip::tcp::resolver resolver(io_service_);
            asio::ip::tcp::resolver::query
                query(unescape_addr(uri.get_host()),
                      uri.get_port(),
                      asio::ip::tcp::resolver::query::flags(0));
            i = resolver.resolve(query);
        }
        catch (asio::system_error& e)
        {
            gu_throw_error(e.code().value())
                << "failed to resolve host '"
                << uri.to_string()
                << "', asio error '" << e.what() << "'";
        }
        if (use_ssl_ == true)
        {
            asio::ssl::stream<asio::ip::tcp::socket>
                ssl_stream(io_service_, ssl_ctx_);
            ssl_stream.lowest_layer().connect(*i);
            set_fd_options(ssl_stream.lowest_layer());
            ssl_stream.handshake(asio::ssl::stream<asio::ip::tcp::socket>::client);
            Proto p(version_,
                    conf_.get(CONF_KEEP_KEYS, CONF_KEEP_KEYS_DEFAULT));
            p.recv_handshake(ssl_stream);
            p.send_ctrl(ssl_stream, Ctrl::C_EOF);
            p.recv_ctrl(ssl_stream);
        }
        else
        {
            asio::ip::tcp::socket socket(io_service_);
            socket.connect(*i);
            set_fd_options(socket);
            Proto p(version_,
                    conf_.get(CONF_KEEP_KEYS, CONF_KEEP_KEYS_DEFAULT));
            p.recv_handshake(socket);
            p.send_ctrl(socket, Ctrl::C_EOF);
            p.recv_ctrl(socket);
        }
    }
    catch (asio::system_error& e)
    {
        // ignore
    }
}
コード例 #2
0
ファイル: ist.cpp プロジェクト: latinovic/galera
galera::ist::Sender::Sender(const gu::Config&  conf,
                            gcache::GCache&    gcache,
                            const std::string& peer,
                            int                version)
    :
    conf_(conf),
    io_service_(),
    socket_(io_service_),
    ssl_ctx_(io_service_, asio::ssl::context::sslv23),
    ssl_stream_(io_service_, ssl_ctx_),
    use_ssl_(false),
    gcache_(gcache),
    version_(version)
{
    gu::URI uri(peer);
    try
    {
        asio::ip::tcp::resolver resolver(io_service_);
        asio::ip::tcp::resolver::query
            query(unescape_addr(uri.get_host()),
                  uri.get_port(),
                  asio::ip::tcp::resolver::query::flags(0));
        asio::ip::tcp::resolver::iterator i(resolver.resolve(query));
        if (uri.get_scheme() == "ssl")
        {
            use_ssl_ = true;
        }
        if (use_ssl_ == true)
        {
            log_info << "IST sender using ssl";
            prepare_ssl_ctx(conf, ssl_ctx_);
            ssl_stream_.lowest_layer().connect(*i);
            set_fd_options(ssl_stream_.lowest_layer());
            ssl_stream_.handshake(asio::ssl::stream<asio::ip::tcp::socket>::client);
        }
        else
        {
            socket_.connect(*i);
            set_fd_options(socket_);
        }
    }
    catch (asio::system_error& e)
    {
        gu_throw_error(e.code().value()) << "IST sender, failed to connect '"
                                         << peer.c_str() << "': " << e.what();
    }
}
コード例 #3
0
void gcomm::AsioUdpSocket::connect(const gu::URI& uri)
{
    gcomm_assert(state() == S_CLOSED);
    Critical<AsioProtonet> crit(net_);
    asio::ip::udp::resolver resolver(net_.io_service_);

    asio::ip::udp::resolver::query query(unescape_addr(uri.get_host()),
                                   uri.get_port());
    asio::ip::udp::resolver::iterator conn_i(resolver.resolve(query));

    target_ep_ = conn_i->endpoint();

    socket_.open(conn_i->endpoint().protocol());
    socket_.set_option(asio::ip::udp::socket::reuse_address(true));
    socket_.set_option(asio::ip::udp::socket::linger(true, 1));
    set_fd_options(socket_);
    asio::ip::udp::socket::non_blocking_io cmd(true);
    socket_.io_control(cmd);

    const std::string if_addr(
        unescape_addr(
            uri.get_option("socket.if_addr",
                           anyaddr(conn_i->endpoint().address()))));
    asio::ip::address local_if(asio::ip::address::from_string(if_addr));

    if (is_multicast(conn_i->endpoint()) == true)
    {
        join_group(socket_, conn_i->endpoint(), local_if);
        socket_.set_option(
            asio::ip::multicast::enable_loopback(
                gu::from_string<bool>(uri.get_option("socket.if_loop", "false"))));
        socket_.set_option(
            asio::ip::multicast::hops(
                gu::from_string<int>(uri.get_option("socket.mcast_ttl", "1"))));
        socket_.bind(*conn_i);
    }
    else
    {
        socket_.bind(
            asio::ip::udp::endpoint(
                local_if,
                gu::from_string<unsigned short>(uri.get_port())));
    }

    async_receive();
    state_ = S_CONNECTED;
}
コード例 #4
0
ファイル: ist.cpp プロジェクト: latinovic/galera
void galera::ist::Receiver::run()
{
    asio::ip::tcp::socket socket(io_service_);
    asio::ssl::context ssl_ctx(io_service_, asio::ssl::context::sslv23);
    asio::ssl::stream<asio::ip::tcp::socket> ssl_stream(io_service_, ssl_ctx_);
    try
    {
        if (use_ssl_ == true)
        {
            acceptor_.accept(ssl_stream.lowest_layer());
            set_fd_options(ssl_stream.lowest_layer());
            ssl_stream.handshake(asio::ssl::stream<asio::ip::tcp::socket>::server);
        }
        else
        {
            acceptor_.accept(socket);
            set_fd_options(socket);
        }
    }
    catch (asio::system_error& e)
    {
        gu_throw_error(e.code().value()) << "accept() failed"
                                         << "', asio error '"
                                         << e.what() << "'";
    }
    acceptor_.close();
    int ec(0);
    try
    {
        Proto p(version_, conf_.get(CONF_KEEP_KEYS, CONF_KEEP_KEYS_DEFAULT));
        if (use_ssl_ == true)
        {
            p.send_handshake(ssl_stream);
            p.recv_handshake_response(ssl_stream);
            p.send_ctrl(ssl_stream, Ctrl::C_OK);
        }
        else
        {
            p.send_handshake(socket);
            p.recv_handshake_response(socket);
            p.send_ctrl(socket, Ctrl::C_OK);
        }
        while (true)
        {
            TrxHandle* trx;
            if (use_ssl_ == true)
            {
                trx = p.recv_trx(ssl_stream);
            }
            else
            {
                trx = p.recv_trx(socket);
            }
            if (trx != 0)
            {
                if (trx->global_seqno() != current_seqno_)
                {
                    log_error << "unexpected trx seqno: " << trx->global_seqno()
                              << " expected: " << current_seqno_;
                    ec = EINVAL;
                    goto err;
                }
                ++current_seqno_;
            }
            gu::Lock lock(mutex_);
            while (ready_ == false || consumers_.empty())
            {
                lock.wait(cond_);
            }
            Consumer* cons(consumers_.top());
            consumers_.pop();
            cons->trx(trx);
            cons->cond().signal();
            if (trx == 0)
            {
                log_debug << "eof received, closing socket";
                break;
            }
        }
    }
    catch (asio::system_error& e)
    {
        log_error << "got error while reading ist stream: " << e.code();
        ec = e.code().value();
    }
    catch (gu::Exception& e)
    {
        ec = e.get_errno();
        if (ec != EINTR)
        {
            log_error << "got exception while reading ist stream: " << e.what();
        }
    }

err:
    gu::Lock lock(mutex_);
    if (use_ssl_ == true)
    {
        ssl_stream.lowest_layer().close();
        // ssl_stream.shutdown();
    }
    else
    {
        socket.close();
    }

    running_ = false;
    if (ec != EINTR && current_seqno_ - 1 < last_seqno_)
    {
        log_error << "IST didn't contain all write sets, expected last: "
                  << last_seqno_ << " last received: " << current_seqno_ - 1;
        ec = EPROTO;
    }
    if (ec != EINTR)
    {
        error_code_ = ec;
    }
    while (consumers_.empty() == false)
    {
        consumers_.top()->cond().signal();
        consumers_.pop();
    }
}
コード例 #5
0
ファイル: ist.cpp プロジェクト: latinovic/galera
std::string
galera::ist::Receiver::prepare(wsrep_seqno_t first_seqno,
                               wsrep_seqno_t last_seqno,
                               int           version)
{
    ready_ = false;
    version_ = version;
    recv_addr_ = IST_determine_recv_addr(conf_);
    gu::URI     const uri(recv_addr_);
    try
    {
        if (uri.get_scheme() == "ssl")
        {
            log_info << "IST receiver using ssl";
            use_ssl_ = true;
            prepare_ssl_ctx(conf_, ssl_ctx_);
        }

        asio::ip::tcp::resolver resolver(io_service_);
        asio::ip::tcp::resolver::query
            query(unescape_addr(uri.get_host()),
                  uri.get_port(),
                  asio::ip::tcp::resolver::query::flags(0));
        asio::ip::tcp::resolver::iterator i(resolver.resolve(query));
        acceptor_.open(i->endpoint().protocol());
        acceptor_.set_option(asio::ip::tcp::socket::reuse_address(true));
        set_fd_options(acceptor_);
        acceptor_.bind(*i);
        acceptor_.listen();
        // read recv_addr_ from acceptor_ in case zero port was specified
        recv_addr_ = uri.get_scheme()
            + "://"
            // + 
            + uri.get_host()
            + ":"
            + gu::to_string(acceptor_.local_endpoint().port());
    }
    catch (asio::system_error& e)
    {
        recv_addr_ = "";
        gu_throw_error(e.code().value())
            << "Failed to open IST listener at "
            << uri.to_string()
            << "', asio error '" << e.what() << "'";
    }

    current_seqno_ = first_seqno;
    last_seqno_    = last_seqno;
    int err;
    if ((err = pthread_create(&thread_, 0, &run_receiver_thread, this)) != 0)
    {
        recv_addr_ = "";
        gu_throw_error(err) << "Unable to create receiver thread";
    }

    running_ = true;

    log_info << "Prepared IST receiver, listening at: "
             << (uri.get_scheme()
                 + "://"
                 + escape_addr(acceptor_.local_endpoint().address())
                 + ":"
                 + gu::to_string(acceptor_.local_endpoint().port()));
    return recv_addr_;
}