SizedBufferRef HandleIpFragment(IpHeaderStruct* ipHeader) { const time_t now = time(NULL); const int timeoutSec = 60; static time_t lastCheck = 0; static FragmentMap fragmentMap; // Delete previous fragments older than timeoutSec if (now-lastCheck >= timeoutSec) { std::list <FragmentMap::iterator> toBeDeleted; for (FragmentMap::iterator it=fragmentMap.begin(); it!=fragmentMap.end(); ++it) { if (now - it->second->lastUpdate() >= timeoutSec) toBeDeleted.push_back(it); } if (toBeDeleted.size()) { for (std::list <FragmentMap::iterator>::iterator it=toBeDeleted.begin(); it!=toBeDeleted.end();++it) { fragmentMap.erase(*it); } FLOG_WARN(s_log,"%d fragmented packets older than %u seconds has been removed from the map", toBeDeleted.size(), timeoutSec); } lastCheck = now; } FLOG_DEBUG(s_log,"Recieved fragment with packet id:%u, offset:%u, payload length:%u", ipHeader->packetId(), ipHeader->offset(), ipHeader->payloadLen()); FragmentMap::iterator it = fragmentMap.find(ipHeader->packetId()); if (it == fragmentMap.end()) { it = fragmentMap.insert(std::make_pair(ipHeader->packetId(), FragmentationAlgorithmRef(new FRAGMENTATION_ALGORITHM()))).first; } FragmentationAlgorithmRef algorithm = it->second; algorithm->addFragment(ipHeader); if (algorithm->drop()) { fragmentMap.erase(it); FLOG_WARN(s_log,"Dropping fragmented packet data with id:%u", ipHeader->packetId()); } if (algorithm->isComplete()) { fragmentMap.erase(it); IpHeaderStruct *header = reinterpret_cast<IpHeaderStruct*>(algorithm->packetData()->get()); FLOG_INFO(s_log, "Reassembled fragmented packet with id:%u, total payload length:%u", header->packetId(), header->payloadLen()); return algorithm->packetData(); } return SizedBufferRef(); // By default return empty ref }
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 ()); } } }
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; }