Example #1
0
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
}
Example #2
0
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 ());
    }
  }
}
Example #3
0
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;
}