void proxy::handle_read_payload(const boost_code& ec, size_t, const heading& heading) { if (stopped()) return; // Ignore read error here, client may have disconnected. if (heading.checksum != bitcoin_checksum(payload_buffer_)) { log_warning(LOG_NETWORK) << "Invalid bitcoin checksum from [" << address() << "]"; stop(error::bad_stream); return; } // We must copy the payload before restarting the reader. const auto payload_copy = payload_buffer_; // We must restart the reader before firing subscription events. if (!ec) read_heading(); start_inactivity(); // Parse and publish the payload to message subscribers. payload_source source(payload_copy); payload_stream istream(source); const auto error = message_subscriber_.load(heading.type(), istream); // Warn about unconsumed bytes in the stream. if (!error && istream.peek() != std::istream::traits_type::eof()) log_warning(LOG_NETWORK) << "Valid message [" << heading.command << "] handled, unused bytes remain in payload."; // Stop the channel if there was a read error. if (ec) { log_warning(LOG_NETWORK) << "Invalid payload of " << heading.command << " from [" << address() << "] (deferred)" << code(error::boost_to_error_code(ec)).message(); stop(ec); return; } // Stop the channel if there was an error from parse. if (error) { log_warning(LOG_NETWORK) << "Invalid stream load of " << heading.command << " from [" << address() << "] " << error.message(); stop(error); } }
void proxy::read_payload(const heading& head) { if (stopped()) return; // This does not cause a reallocation. payload_buffer_.resize(head.payload_size()); // The payload buffer is protected by ordering, not the critial section. // Critical Section (external) /////////////////////////////////////////////////////////////////////////// const auto socket = socket_->get_socket(); using namespace boost::asio; async_read(socket->get(), buffer(payload_buffer_, head.payload_size()), std::bind(&proxy::handle_read_payload, shared_from_this(), _1, _2, head)); /////////////////////////////////////////////////////////////////////////// }
void proxy::handle_read_payload(const boost_code& ec, size_t payload_size, const heading& head) { if (stopped()) return; // TODO: verify client quick disconnect. if (ec) { LOG_DEBUG(LOG_NETWORK) << "Payload read failure [" << authority() << "] " << code(error::boost_to_error_code(ec)).message(); stop(ec); return; } if (head.checksum() != bitcoin_checksum(payload_buffer_)) { LOG_WARNING(LOG_NETWORK) << "Invalid " << head.command() << " payload from [" << authority() << "] bad checksum."; stop(error::bad_stream); return; } /////////////////////////////////////////////////////////////////////////// // TODO: we aren't getting a stream benefit if we read the full payload // before parsing the message. Should just make this a message parse. /////////////////////////////////////////////////////////////////////////// // Notify subscribers of the new message. payload_source source(payload_buffer_); payload_stream istream(source); const auto code = message_subscriber_.load(head.type(), version_, istream); const auto consumed = istream.peek() == std::istream::traits_type::eof(); // For finding agents of bad versions. ////const auto agent = //// ((!code && consumed) || head.command != version::command) ? "" : " " + //// std::string(payload_buffer_.begin(), payload_buffer_.end()); if (code) { LOG_WARNING(LOG_NETWORK) << "Invalid " << head.command() << " payload from [" << authority() << "] " << code.message(); stop(code); return; } if (!consumed) { LOG_WARNING(LOG_NETWORK) << "Invalid " << head.command() << " payload from [" << authority() << "] trailing bytes."; stop(error::bad_stream); return; } LOG_DEBUG(LOG_NETWORK) << "Valid " << head.command() << " payload from [" << authority() << "] (" << payload_size << " bytes)"; handle_activity(); read_heading(); }
void proxy::handle_read_payload(const boost_code& ec, size_t, const heading& head) { if (stopped()) return; ////// Ignore read error here, client may have disconnected. ////if (ec) ////{ //// log::debug(LOG_NETWORK) //// << "Payload read failure [" << authority() << "] " //// << code(error::boost_to_error_code(ec)).message(); //// stop(ec); //// return; ////} ////log::debug(LOG_NETWORK) //// << "Read (" << size << ") payload bytes from [" << authority() << "] "; if (head.checksum != bitcoin_checksum(payload_buffer_)) { log::warning(LOG_NETWORK) << "Invalid " << head.command << " checksum from [" << authority() << "]"; stop(error::bad_stream); return; } // Parse and publish the payload to message subscribers. payload_source source(payload_buffer_); payload_stream istream(source); // Notify subscribers of the new message. const auto parse_error = message_subscriber_.load(head.type(), istream); const auto unconsumed = istream.peek() != std::istream::traits_type::eof(); if (stopped()) return; if (!parse_error) { if (unconsumed) log::warning(LOG_NETWORK) << "Valid " << head.command << " payload from [" << authority() << "] unused bytes remain."; else log::debug(LOG_NETWORK) << "Valid " << head.command << " payload from [" << authority() << "] (" << payload_buffer_.size() << " bytes)"; } if (ec) { log::debug(LOG_NETWORK) << "Payload read failure [" << authority() << "] " << code(error::boost_to_error_code(ec)).message(); stop(ec); return; } if (parse_error) { log::warning(LOG_NETWORK) << "Invalid " << head.command << " stream from [" << authority() << "] " << parse_error.message(); stop(parse_error); } handle_activity(); read_heading(); }