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 } }
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(); } }
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; }
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(); } }
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_; }