int UdpTransport::setup_read_socket(void) { if(BasicASIOTransport::setup_read_socket() < 0) { return -1; } try { socket_.non_blocking(true); socket_.bind(udp::endpoint(ip::address_v4::any(), addresses_[0].port())); madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "UdpTransport::setup_read_socket:" " Bound to port: %d\n", (int)addresses_[0].port()); } catch (const boost::system::system_error& e) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "UdpTransport::setup:" " Error setting up read socket: %s\n", e.what()); this->invalidate_transport(); return -1; } return 0; }
long UdpTransport::receive_buffer( char* buf, size_t & bytes_read, udp::endpoint& remote) { boost::system::error_code err; bytes_read = socket_.receive_from( asio::buffer((void*)buf, settings_.queue_length), remote, udp::socket::message_flags{}, err); if (err == asio::error::would_block || bytes_read == 0) { madara_logger_log(context_.get_logger(), logger::LOG_MINOR, "UdpTransport::receive_buffer: " " no bytes to read. Proceeding to next wait\n"); return 1; } else if (err) { madara_logger_log(context_.get_logger(), logger::LOG_MINOR, "UdpTransport::receive_buffer: unexpected error: %s. " "Proceeding to next wait\n", err.message().c_str()); return 2; } return 0; }
int BasicASIOTransport::setup_read_threads() { if (!settings_.no_receiving) { double hertz = settings_.read_thread_hertz; if (hertz < 0.0) { // we need to maintain backwards compatibility // people should be capable of bursting reads especially hertz = 0.0; } madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " starting %d threads at %f hertz\n", settings_.read_threads, hertz); for (uint32_t i = 0; i < settings_.read_threads; ++i) { std::stringstream thread_name; thread_name << "read"; thread_name << i; madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " starting thread %s at %f hertz\n", thread_name.str().c_str(), hertz); setup_read_thread(hertz, thread_name.str()); } } return 0; }
void madara::transport::UdpRegistryClientReadThread::init ( knowledge::KnowledgeBase & knowledge) { context_ = &(knowledge.get_context ()); // setup the receive buffer if (settings_.queue_length > 0) buffer_ = new char [settings_.queue_length]; if (context_) { // check for an on_data_received ruleset if (settings_.on_data_received_logic.length () != 0) { #ifndef _MADARA_NO_KARL_ madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "UdpRegistryClientReadThread::init:" \ " setting rules to %s\n", settings_.on_data_received_logic.c_str ()); madara::expression::Interpreter interpreter; on_data_received_ = context_->compile (settings_.on_data_received_logic); #endif // _MADARA_NO_KARL_ } else { madara_logger_log (context_->get_logger (), logger::LOG_MINOR, "UdpRegistryClientReadThread::init:" \ " no permanent rules were set\n"); } } }
bool madara::knowledge::containers::IntegerVector::is_true (void) const { bool result (false); madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "IntegerVector::is_true: Checking for truth\n"); if (context_) { ContextGuard context_guard (*context_); MADARA_GUARD_TYPE guard (mutex_); result = true; madara_logger_log (context_->get_logger (), logger::LOG_MINOR, "IntegerVector::is_true: context was not null. Result changed to %d\n", (int)result); for (size_t index = 0; index < vector_.size (); ++index) { madara_logger_log (context_->get_logger (), logger::LOG_DETAILED, "IntegerVector::is_true: checking index %d, is_false of %d. \n", (int)result, (int)context_->get (vector_[index]).is_false ()); if (context_->get (vector_[index]).is_false ()) { madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "IntegerVector::is_true: result is false, breaking\n"); result = false; break; } } if (vector_.size () == 0) result = false; } madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "IntegerVector::is_true: final result is %d\n", (int)result); return result; }
int UdpTransport::setup_read_thread(double hertz, const std::string& name) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "UdpTransport::setup_read_thread:" " Starting UdpTransport read thread: %s\n", name.c_str()); read_threads_.run(hertz, name, new UdpTransportReadThread(*this)); return 0; }
/** * Checks if the value in the record is not false (0) * @return true if value is not false **/ bool madara::knowledge::containers::FlexMap::is_true(void) const { ContextGuard context_guard(*context_); bool result(false); KnowledgeUpdateSettings keep_local(true); madara_logger_log(context_->get_logger(), logger::LOG_MAJOR, "Vector::is_true: checking for non-zero value\n"); if (variable_.is_valid()) { result = context_->get(variable_, keep_local).is_true(); } madara_logger_log(context_->get_logger(), logger::LOG_MAJOR, "FlexMap::is_true: final result is %d\n", (int)result); return result; }
int madara::transport::SpliceDDSTransport::check_status( DDS::ReturnCode_t status, const char* info) { // if the status is okay, then return without issue if ((status == DDS::RETCODE_OK) || (status == DDS::RETCODE_NO_DATA)) return 0; madara_logger_log(context_.get_logger(), logger::LOG_ERROR, "SpliceDDSTransport::check_status:" " error in %s: Creation failed: %s\n", info, get_error_name(status)); return -2; }
bool madara::knowledge::containers::NativeDoubleVector::is_true (void) const { bool result (false); madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "NativeDoubleVector::is_true: %s: Checking for non-zero value\n", this->name_.c_str ()); if (context_) { ContextGuard context_guard (*context_); MADARA_GUARD_TYPE guard (mutex_); result = context_->get (vector_, settings_).is_true (); } madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "NativeDoubleVector::is_true: %s: final result is %d\n", this->name_.c_str (), (int)result); return result; }
int madara::transport::SpliceDDSTransport::check_handle( void* handle, const char* info) { if (!handle) { madara_logger_log(context_.get_logger(), logger::LOG_ERROR, "SpliceDDSTransport::check_handle:" " error in %s: Creation failed: invalid handle\n", info); return -2; } return 0; }
long madara::transport::SpliceDDSTransport::send_data( const knowledge::KnowledgeMap& updates) { long result = 0; if (!settings_.no_sending) { result = prep_send(updates, "SpliceDDSTransport::send_data:"); // get the maximum quality from the updates uint32_t quality = knowledge::max_quality(updates); /// get current lamport clock. unsigned long long cur_clock = context_.get_clock(); DDS::ReturnCode_t dds_result; DDS::InstanceHandle_t handle; Knowledge::Update data; data.buffer = Knowledge::seq_oct(result, result, (unsigned char*)buffer_.get_ptr()); data.clock = cur_clock; data.quality = quality; data.updates = DDS::ULong(updates.size()); data.originator = DDS::string_dup(id_.c_str()); data.type = madara::transport::MULTIASSIGN; data.ttl = settings_.get_rebroadcast_ttl(); data.timestamp = utility::get_time(); data.madara_id = DDS::string_dup(MADARA_IDENTIFIER); madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "SpliceDDSTransport::send:" " sending multiassignment: %d updates, time=llu, quality=%d\n", data.updates, cur_clock, quality); handle = update_writer_->register_instance(data); dds_result = update_writer_->write(data, handle); result = (long)dds_result; // update_writer_->unregister_instance (data, handle); } return result; }
void madara::filters::EndpointClear::filter(knowledge::KnowledgeMap& records, const transport::TransportContext& transport_context, knowledge::Variables& vars) { if (!initialized_) { knowledge::KnowledgeUpdateSettings settings(true); endpoints_.set_settings(settings); endpoints_.set_name(prefix_, vars); initialized_ = true; } endpoints_.sync_keys(); madara_logger_log(vars.get_context()->get_logger(), logger::LOG_MAJOR, "EndpointClear::filter:" " Processing a new update from %s with %d records\n", transport_context.get_originator().c_str(), (int)records.size()); // if a trusted originator has been added, and this is the originator if (trusted_originators_.size() != 0 && (trusted_originators_.find(transport_context.get_originator()) != trusted_originators_.end())) { madara_logger_log(vars.get_context()->get_logger(), logger::LOG_MAJOR, "EndpointClear::filter:" " Sender is trusted. Clearing endpoints.\n"); // then clear the endpoints endpoints_.clear(); if (vars.get_context()->get_logger().get_level() >= logger::LOG_DETAILED) { vars.print(); } } else { bool found = false; const std::string prefix(endpoints_.get_name()); if (prefix != "") { // iterate through all records looking for the common prefix for (knowledge::KnowledgeMap::const_iterator i = records.begin(); i != records.end() && !found; ++i) { // if we've found the prefix, then clear the endpoints if (utility::begins_with(i->first, prefix)) { madara_logger_log(vars.get_context()->get_logger(), logger::LOG_MAJOR, "EndpointClear::filter:" " Prefix is match. Clearing endpoints.\n"); endpoints_.clear(); found = true; if (vars.get_context()->get_logger().get_level() >= logger::LOG_DETAILED) { vars.print(); } } // if we're past where the prefix would be, quit else if (prefix[0] < i->first[0]) { madara_logger_log(vars.get_context()->get_logger(), logger::LOG_MAJOR, "EndpointClear::filter:" " Prefix is not a match. Not clearing endpoints.\n"); found = true; } } } } }
int BasicASIOTransport::setup(void) { // call base setup method to initialize certain common variables if (Base::setup() < 0) { return -1; } // resize addresses to be the size of the list of hosts addresses_.clear(); addresses_.reserve(this->settings_.hosts.size()); if (settings_.hosts.size() == 0) { madara_logger_log(context_.get_logger(), logger::LOG_MINOR, "BasicASIOTransport::setup:" " No host addresses. Aborting setup.\n"); this->invalidate_transport(); return -1; } // convert the string host:port into an asio address for (unsigned int i = 0; i < settings_.hosts.size(); ++i) { try { auto addr_parts = utility::parse_address(settings_.hosts[i]); auto addr = ip::address::from_string(addr_parts.first); addresses_.emplace_back(addr, addr_parts.second); madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " settings address[%d] to %s:%d\n", i, addresses_.back().address().to_string().c_str(), addresses_.back().port()); } catch (const boost::system::system_error& e) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " Error parsing address %s: %s\n", settings_.hosts[i].c_str(), e.what()); } } if (addresses_.size() == 0) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " No valid addresses. Aborting setup.\n"); this->invalidate_transport(); return -1; } try { socket_.open(addresses_[0].protocol()); } catch (const boost::system::system_error& e) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " Error opening sockets: %s\n", e.what()); this->invalidate_transport(); return -1; } int ret = setup_sockets(); if (ret < 0) { return ret; } ret = setup_read_threads(); if (ret < 0) { return ret; } return this->validate_transport(); }
int madara::transport::SpliceDDSTransport::setup(void) { Base::setup(); DDS::ReturnCode_t status; this->is_valid_ = false; // reset the valid setup flag // valid_setup_ = false; madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Creating a participant for topic (%s)\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Participant settings are being read from the OSPL_URI environment" " variable\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); // get the domain participant factory domain_factory_ = DDS::DomainParticipantFactory::get_instance(); domain_factory_->get_default_participant_qos(part_qos_); domain_participant_ = domain_factory_->create_participant( domain_, part_qos_, NULL, DDS::STATUS_MASK_NONE); // if dp == NULL, we've got an error if (domain_participant_ == NULL) { madara_logger_log(context_.get_logger(), logger::LOG_ERROR, "\nSpliceDDSTransport::setup:" " splice daemon not running. Try 'ospl start'...\n"); return -2; } domain_participant_->get_default_topic_qos(topic_qos_); if (madara::transport::RELIABLE == this->settings_.reliability) { topic_qos_.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; topic_qos_.history.depth = this->settings_.queue_length; topic_qos_.resource_limits.max_samples_per_instance = this->settings_.queue_length; topic_qos_.resource_limits.max_samples = this->settings_.queue_length; topic_qos_.destination_order.kind = DDS::BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS; // topic_qos_. } // topic_qos_.resource_limits.max_samples_per_instance= 10; domain_participant_->set_default_topic_qos(topic_qos_); madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Registering type support\n"); // Register Update type status = this->update_type_support_.register_type( domain_participant_, "Knowledge::Update"); if (int ret = check_status( status, "Knowledge::UpdateTypeSupport::register_type") < 0) return ret; // Register Mutex type // status = this->mutex_type_support_.register_type ( // domain_participant_, "Knowledge::Mutex"); // check_status(status, "Knowledge::MutexTypeSupport::register_type"); madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Setting up knowledge domain via topic (%s)\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); // Create Update topic update_topic_ = domain_participant_->create_topic( madara::utility::dds_topicify(settings_.write_domain).c_str(), "Knowledge::Update", topic_qos_, NULL, DDS::STATUS_MASK_NONE); if (int ret = check_handle(update_topic_, "DDS::DomainParticipant::create_topic (KnowledgeUpdate)") < 0) return ret; // Get default qos for publisher status = domain_participant_->get_default_publisher_qos(pub_qos_); if (int ret = check_status(status, "DDS::DomainParticipant::get_default_publisher_qos") < 0) return ret; if (madara::transport::RELIABLE == this->settings_.reliability) { pub_qos_.presentation.access_scope = DDS::TOPIC_PRESENTATION_QOS; pub_qos_.presentation.coherent_access = true; pub_qos_.presentation.ordered_access = false; // topic_qos_. } madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Creating publisher for topic (%s)\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); // Create publisher pub_qos_.partition.name.length(1); pub_qos_.partition.name[0] = DDS::string_dup(partition_); publisher_ = domain_participant_->create_publisher( pub_qos_, NULL, DDS::STATUS_MASK_NONE); if (int ret = check_handle( publisher_, "DDS::DomainParticipant::create_publisher") < 0) return ret; // Create subscriber status = domain_participant_->get_default_subscriber_qos(sub_qos_); if (int ret = check_status(status, "DDS::DomainParticipant::get_default_subscriber_qos") < 0) return ret; if (madara::transport::RELIABLE == this->settings_.reliability) { sub_qos_.presentation.access_scope = DDS::TOPIC_PRESENTATION_QOS; sub_qos_.presentation.coherent_access = true; sub_qos_.presentation.ordered_access = false; } madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Creating subscriber for topic (%s)\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); sub_qos_.partition.name.length(1); sub_qos_.partition.name[0] = DDS::string_dup(partition_); subscriber_ = domain_participant_->create_subscriber( // sub_qos_, &sub_listener_, DDS::DATA_AVAILABLE_STATUS | // DDS::DATA_ON_READERS_STATUS); sub_qos_, NULL, DDS::STATUS_MASK_NONE); if (int ret = check_handle(subscriber_, "DDS::DomainParticipant::create_subscriber") < 0) return ret; if (!subscriber_ || !publisher_) { madara_logger_log(context_.get_logger(), logger::LOG_ERROR, "SpliceDDSTransport::setup:" " pub or sub could not be created. Try 'ospl stop; ospl start'...\n"); return -2; } // Create datawriter publisher_->get_default_datawriter_qos(datawriter_qos_); publisher_->copy_from_topic_qos(datawriter_qos_, topic_qos_); if (madara::transport::RELIABLE == this->settings_.reliability) { madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Enabling reliable transport for (%s) datawriters\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); datawriter_qos_.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; datawriter_qos_.history.depth = this->settings_.queue_length; datawriter_qos_.resource_limits.max_samples = this->settings_.queue_length; datawriter_qos_.resource_limits.max_samples_per_instance = this->settings_.queue_length; datawriter_qos_.destination_order.kind = DDS::BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS; } else { madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Enabling unreliable transport for (%s) datawriters\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); } madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Creating datawriter for topic (%s)\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); // Create Update writer datawriter_ = publisher_->create_datawriter( update_topic_, datawriter_qos_, NULL, DDS::STATUS_MASK_NONE); if (int ret = check_handle(datawriter_, "DDS::Publisher::create_datawriter (Update)") < 0) return ret; update_writer_ = dynamic_cast<Knowledge::UpdateDataWriter_ptr>(datawriter_.in()); if (int ret = check_handle(update_writer_, "Knowledge::UpdateDataWriter_ptr::narrow") < 0) return ret; // Create Latency Update writer for Read Thread latencywriter_ = publisher_->create_datawriter( update_topic_, datawriter_qos_, NULL, DDS::STATUS_MASK_NONE); if (int ret = check_handle(latencywriter_, "DDS::Publisher::create_datawriter (Update)") < 0) return ret; latency_update_writer_ = dynamic_cast<Knowledge::UpdateDataWriter_ptr>(latencywriter_.in()); if (int ret = check_handle(latency_update_writer_, "Knowledge::UpdateDataWriter_ptr::narrow") < 0) return ret; // Create datareader status = subscriber_->get_default_datareader_qos(datareader_qos_); subscriber_->copy_from_topic_qos(datareader_qos_, topic_qos_); // publisher_->copy_from_topic_qos(datawriter_qos_, topic_qos_); if (int ret = check_status( status, "DDS::Subscriber::get_default_datareader_qos") < 0) return ret; datareader_qos_.reader_data_lifecycle.enable_invalid_samples = FALSE; if (madara::transport::RELIABLE == this->settings_.reliability) { madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Enabling reliable transport for (%s) datareaders\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); datareader_qos_.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; datareader_qos_.history.depth = this->settings_.queue_length; datareader_qos_.resource_limits.max_samples = this->settings_.queue_length; datareader_qos_.destination_order.kind = DDS::BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS; // unlike the other qos, we do not set max_samples_per_instance here. // that shouldn't be as necessary, since we are using take on the reader } else { madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Enabling unreliable transport for (%s) datareaders\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); } madara_logger_log(context_.get_logger(), logger::LOG_DETAILED, "SpliceDDSTransport::setup:" " Creating datareader for topic (%s)\n", madara::utility::dds_topicify(settings_.write_domain).c_str()); // Create Update datareader datareader_ = subscriber_->create_datareader(update_topic_, // datareader_qos_, &dr_listener_, DDS::STATUS_MASK_NONE); datareader_qos_, NULL, DDS::STATUS_MASK_NONE); // notes: we set the mask to none because the listener will be called // by the subscriber listener with notify_datareaders. This is the Splice // way of doing this, since we require subscription information and they // have so far not implemented on_subscription_matched. if (int ret = check_handle(datareader_, "DDS::Subscriber::create_datareader (Update)") < 0) return ret; update_reader_ = dynamic_cast<Knowledge::UpdateDataReader_ptr>(datareader_.in()); if (int ret = check_handle(update_reader_, "Knowledge::UpdateDataReader_ptr::narrow") < 0) return ret; if (!settings_.no_receiving) { double hertz = settings_.read_thread_hertz; if (hertz < 0.0) { hertz = 0.0; } madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "UdpTransportReadThread::setup:" " starting %d threads at %f hertz\n", settings_.read_threads, hertz); for (uint32_t i = 0; i < settings_.read_threads; ++i) { std::stringstream thread_name; thread_name << "read"; thread_name << i; read_threads_.run(hertz, thread_name.str(), new madara::transport::SpliceReadThread(id_, this->settings_, context_, update_reader_, latency_update_writer_, send_monitor_, receive_monitor_, packet_scheduler_)); } } return this->validate_transport(); }
long UdpTransport::send_message(const char* buf, size_t packet_size, uint64_t clock) { static const char print_prefix[] = "UdpTransport::send_message"; uint64_t bytes_sent = 0; if(packet_size > settings_.max_fragment_size) { FragmentMap map; madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "%s:" " fragmenting %" PRIu64 " byte packet (%" PRIu32 " bytes is max fragment size)\n", print_prefix, packet_size, settings_.max_fragment_size); // fragment the message frag(buf, packet_size, id_.c_str (), settings_.write_domain.c_str(), clock, utility::get_time(), 0, 0, settings_.max_fragment_size, map); int j(0); for(FragmentMap::iterator i = map.begin(); i != map.end(); ++i, ++j) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "%s:" " Sending fragment %d\n", print_prefix, j); for(const auto& address : addresses_) { if(pre_send_buffer(&address - &*addresses_.begin())) { bytes_sent += send_buffer( address, i->second.get(), (size_t)MessageHeader::get_size(i->second.get())); } } // sleep between fragments, if such a slack time is specified if(settings_.slack_time > 0) utility::sleep(settings_.slack_time); } madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "%s:" " Sent fragments totalling %" PRIu64 " bytes\n", print_prefix, bytes_sent); delete_fragments(map); } else { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "%s:" " Sending packet of size %ld\n", print_prefix, packet_size); for(const auto& address : addresses_) { size_t addr_index = &address - &*addresses_.begin(); bool should_send = pre_send_buffer(addr_index); madara_logger_log(context_.get_logger(), logger::LOG_MINOR, "%s:" " Deciding to send to %s:%d (index %d): %d\n", print_prefix, address.address().to_string().c_str(), (int)address.port(), addr_index, should_send); if(should_send) { bytes_sent += send_buffer(address, buf, (size_t)packet_size); } } } if(bytes_sent > 0) { send_monitor_.add((uint32_t)bytes_sent); } madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "%s:" " Send bandwidth = %" PRIu64 " B/s\n", print_prefix, send_monitor_.get_bytes_per_second()); return (long)bytes_sent; }
long UdpTransport::send_buffer( const udp::endpoint& target, const char* buf, size_t size) { uint64_t bytes_sent = 0; int send_attempts = -1; ssize_t actual_sent = -1; while (actual_sent < 0 && (settings_.resend_attempts < 0 || send_attempts < settings_.resend_attempts)) { if(settings_.max_send_hertz > 0) { enforcer_.sleep_until_next(); } // send the fragment try { actual_sent = socket_.send_to(asio::buffer(buf, size), target); } catch (const boost::system::system_error& e) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "UdpTransport::send_buffer:" " Error sending packet to %s:%d: %s\n", target.address().to_string().c_str(), (int)target.port(), e.what()); // ensure erroneous data is not being used actual_sent = -1; } ++send_attempts; if(settings_.debug_to_kb_prefix != "") { ++sent_packets; } if(actual_sent > 0) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "UdpTransport::send_buffer: Sent %d byte packet to %s:%d\n", (int)actual_sent, target.address().to_string().c_str(), (int)target.port()); bytes_sent += actual_sent; if(settings_.debug_to_kb_prefix != "") { sent_data += actual_sent; if(sent_data_max < actual_sent) { sent_data_max = actual_sent; } if(sent_data_min > actual_sent || sent_data_min == 0) { sent_data_min = actual_sent; } } } else { if(settings_.debug_to_kb_prefix != "") { ++failed_sends; } } } return (long)bytes_sent; }
void madara::transport::UdpRegistryClientReadThread::run (void) { if (!settings_.no_receiving) { ACE_Time_Value wait_time (1); ACE_INET_Addr remote; // allocate a buffer to send char * buffer = buffer_.get_ptr (); const char * print_prefix = "UdpRegistryClientReadThread::run"; int64_t buffer_remaining = settings_.queue_length; madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " entering main service loop.\n", print_prefix); knowledge::KnowledgeMap rebroadcast_records; if (buffer == 0) { madara_logger_log (context_->get_logger (), logger::LOG_MINOR, "%s:" \ " Unable to allocate buffer of size " PRIu32 ". Exiting thread.\n", print_prefix, settings_.queue_length); return; } madara_logger_log (context_->get_logger (), logger::LOG_MINOR, "%s:" \ " entering a recv on the socket.\n", print_prefix); // read the message ssize_t bytes_read = socket_.recv ((void *)buffer, (size_t)settings_.queue_length, remote, 0, &wait_time); if (bytes_read > 0) { if (remote.get_host_addr () != 0) { madara_logger_ptr_log (logger::global_logger.get (), logger::LOG_MAJOR, "%s:" \ " received a message header of %lld bytes from %s:%d\n", print_prefix, (long long)bytes_read, remote.get_host_addr (), (int)remote.get_port_number ()); } else { madara_logger_ptr_log (logger::global_logger.get (), logger::LOG_WARNING, "%s:" \ " received %lld bytes from unknown host\n", print_prefix, (long long)bytes_read); } MessageHeader * header = 0; std::stringstream remote_host; remote_host << remote.get_host_addr (); remote_host << ":"; remote_host << remote.get_port_number (); process_received_update (buffer, bytes_read, id_, *context_, settings_, send_monitor_, receive_monitor_, rebroadcast_records, #ifndef _MADARA_NO_KARL_ on_data_received_, #endif // _MADARA_NO_KARL_ print_prefix, remote_host.str ().c_str (), header); if (header) { if (header->ttl > 0 && rebroadcast_records.size () > 0 && settings_.get_participant_ttl () > 0) { --header->ttl; header->ttl = std::min ( settings_.get_participant_ttl (), header->ttl); rebroadcast (print_prefix, header, rebroadcast_records); } // delete header delete header; } } else { madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " wait timeout on new messages. Proceeding to next wait\n", print_prefix); } } }
void madara::transport::UdpRegistryClientReadThread::rebroadcast ( const char * print_prefix, MessageHeader * header, const knowledge::KnowledgeMap & records) { int64_t buffer_remaining = (int64_t) settings_.queue_length; char * buffer = buffer_.get_ptr (); int result (0); if (!settings_.no_sending) { result = prep_rebroadcast (*context_, buffer, buffer_remaining, settings_, print_prefix, header, records, packet_scheduler_); if (result > 0) { uint64_t bytes_sent = 0; uint64_t packet_size = (uint64_t)result; if (packet_size > settings_.max_fragment_size) { FragmentMap map; madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " fragmenting %" PRIu64 " byte packet (%" PRIu32 " bytes is max fragment size)\n", print_prefix, packet_size, settings_.max_fragment_size); // fragment the message frag (buffer_.get_ptr (), settings_.max_fragment_size, map); int j (0); for (FragmentMap::iterator i = map.begin (); i != map.end (); ++i, ++j) { size_t frag_size = (size_t)MessageHeader::get_size (i->second); for (std::map <std::string, ACE_INET_Addr>::const_iterator addr = addresses_.begin (); addr != addresses_.end (); ++addr) { if (addr->first != settings_.hosts[0]) { madara_logger_log (this->context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " Sending fragment %d\n", print_prefix, j); int send_attempts = -1; ssize_t actual_sent = -1; while (actual_sent < 0 && (settings_.resend_attempts < 0 || send_attempts < settings_.resend_attempts)) { // send the fragment actual_sent = socket_.send ( i->second, frag_size, addr->second); ++send_attempts; if (actual_sent > 0) { bytes_sent = (uint64_t)actual_sent; madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " Sent packet of size %" PRIu64 "\n", print_prefix, bytes_sent); send_monitor_.add ((uint32_t)actual_sent); } else if (actual_sent == ECONNRESET) { madara_logger_log (context_->get_logger (), logger::LOG_WARNING, "%s:" \ " WARNING: Remote socket disappeared during send (ECONNRESET)\n", print_prefix); } else if (actual_sent == EINTR) { madara_logger_log (context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Local socket was interrupted during send (EINTR)\n", print_prefix); } else if (actual_sent == EWOULDBLOCK) { madara_logger_log (context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Send would have blocked (EWOULDBLOCK)\n", print_prefix); } else if (actual_sent == ENOTCONN) { madara_logger_log (context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Send reports socket is not connected (ENOTCONN)\n", print_prefix); } else if (actual_sent == EADDRINUSE) { madara_logger_log (context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Send reports the interface is busy (EADDRINUSE)\n", print_prefix); } else if (actual_sent == EBADF) { madara_logger_log (context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Send socket is invalid (EBADF)\n", print_prefix); } else { madara_logger_log (context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Packet was not sent due to unknown error (%d)\n", print_prefix, (int)actual_sent); } } // sleep between fragments, if such a slack time is specified if (settings_.slack_time > 0) madara::utility::sleep (settings_.slack_time); } } } madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " Sent fragments totalling %" PRIu64 " bytes\n", print_prefix, bytes_sent); delete_fragments (map); } else { for (std::map <std::string, ACE_INET_Addr>::const_iterator i = addresses_.begin (); i != addresses_.end (); ++i) { if (i->first != settings_.hosts[0]) { madara_logger_log (this->context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " Sending packet of size %ld\n", print_prefix, result); int send_attempts = -1; ssize_t actual_sent = -1; while (actual_sent < 0 && (settings_.resend_attempts < 0 || send_attempts < settings_.resend_attempts)) { // send the fragment actual_sent = socket_.send (buffer_.get_ptr (), (ssize_t)result, i->second); ++send_attempts; if (actual_sent > 0) { bytes_sent += actual_sent; madara_logger_log (this->context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " Sent packet of size %" PRIu64 "\n", print_prefix, (int)actual_sent); send_monitor_.add ((uint32_t)actual_sent); } else if (actual_sent == ECONNRESET) { madara_logger_log (this->context_->get_logger (), logger::LOG_WARNING, "%s:" \ " WARNING: Remote socket disappeared during send (ECONNRESET)\n", print_prefix); } else if (actual_sent == EINTR) { madara_logger_log (this->context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Local socket was interrupted during send (EINTR)\n", print_prefix); } else if (actual_sent == EWOULDBLOCK) { madara_logger_log (this->context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Send would have blocked (EWOULDBLOCK)\n", print_prefix); } else if (actual_sent == ENOTCONN) { madara_logger_log (this->context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Send reports socket is not connected (ENOTCONN)\n", print_prefix); } else if (actual_sent == EADDRINUSE) { madara_logger_log (this->context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Send reports the interface is busy (EADDRINUSE)\n", print_prefix); } else if (actual_sent == EBADF) { madara_logger_log (this->context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Send socket is invalid (EBADF)\n", print_prefix); } else { madara_logger_log (this->context_->get_logger (), logger::LOG_WARNING, "%s:" \ " Packet was not sent due to unknown error (%d)\n", print_prefix, (int)actual_sent); } } } } madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " Sent %d total bytes via rebroadcast\n", print_prefix, bytes_sent); } madara_logger_log (context_->get_logger (), logger::LOG_MAJOR, "%s:" \ " Send bandwidth = %" PRIu64 " B/s\n", print_prefix, send_monitor_.get_bytes_per_second ()); } } }
int BasicASIOTransport::setup_socket(udp::socket& socket) { int tar_buff_size(settings_.queue_length); asio::socket_base::send_buffer_size send_buffer_option; asio::socket_base::receive_buffer_size receive_buffer_option; try { socket.get_option(send_buffer_option); int send_buff_size = send_buffer_option.value(); socket.get_option(receive_buffer_option); int rcv_buff_size = receive_buffer_option.value(); madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " default socket buff size is send=%d, rcv=%d\n", send_buff_size, rcv_buff_size); if (send_buff_size < tar_buff_size) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " setting send buff size to settings.queue_length (%d)\n", tar_buff_size); send_buffer_option = tar_buff_size; socket.set_option(send_buffer_option); socket.get_option(send_buffer_option); send_buff_size = send_buffer_option.value(); madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " current socket buff size is send=%d, rcv=%d\n", send_buff_size, rcv_buff_size); } if (rcv_buff_size < tar_buff_size) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " setting rcv buff size to settings.queue_length (%d)\n", tar_buff_size); receive_buffer_option = tar_buff_size; socket.set_option(receive_buffer_option); socket.get_option(receive_buffer_option); rcv_buff_size = receive_buffer_option.value(); madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " current socket buff size is send=%d, rcv=%d\n", send_buff_size, rcv_buff_size); } } catch (const boost::system::system_error& e) { madara_logger_log(context_.get_logger(), logger::LOG_MAJOR, "BasicASIOTransport::setup:" " Error setting up sockets: %s\n", e.what()); this->invalidate_transport(); return -1; } return 0; }