void TunTapComponent::rxThreadFunction()
{
  //LOG(LINFO) << "RX thread started, listening on tun/tap device " << x_tunTapDevice;
  fd_set socketSet;
  struct timeval selectTimeout;
  char buffer[MAX_BUF_SIZE];
  int nread;

  try
  {
    // read data coming from the kernel
    while(true)
    {
      boost::this_thread::interruption_point();

      // reset socket set and add tap descriptor
      FD_ZERO(&socketSet);
      FD_SET(tunFd_, &socketSet);

      // initialize timeout
      selectTimeout.tv_sec = 1;
      selectTimeout.tv_usec = 0;

      // suspend thread until we receive a packet or timeout
      if (select(tunFd_ + 1, &socketSet, NULL, NULL, &selectTimeout) == 0) {
        //LOG(LDEBUG) << "Timeout while waiting for incoming packet.";
      } else {
        if (FD_ISSET(tunFd_, &socketSet)) {
          if ((nread = read(tunFd_, buffer, MAX_BUF_SIZE)) < 0)
          {
            LOG(LFATAL) << "Error while reading from tun/tap interface.";
            continue;
          }
          LOG(LDEBUG) << "Read " << nread << " bytes from device "
            << tunName_;

          // copy received data into new StackDataSet
          shared_ptr<StackDataSet> packetBuffer(new StackDataSet);
          packetBuffer->data.assign(buffer, buffer + nread);

          // send downwards
          sendDownwards(packetBuffer);
        }
      }
    } // while (true)
    throw SystemException("Rx thread stopped unexpectedly.");
  }
  catch(IrisException& ex)
  {
    LOG(LFATAL) << "Error in TunTap component: " << ex.what()
      << " - TX thread exiting.";
  }
  catch(boost::thread_interrupted)
  {
    LOG(LINFO) << "Thread " << boost::this_thread::get_id()
      << " in stack component interrupted.";
  }
}
示例#2
0
unsigned int WINAPI RecvThreadProc(LPVOID argv)
{
	SOCKET hServSock = (SOCKET) argv;
	CustomBuffer packetBuffer(BUF_SIZE);
	char* message = new char[BUF_SIZE];
	unsigned short packetSize = 0;
	unsigned short messageLength = 0;
	PacketType packetType = PACKET_NONE;

	while(true)
	{
		memset(message, 0, sizeof(char)*BUF_SIZE);
		packetSize = GetPacketSize(hServSock);
		if(RecvMessage(hServSock, packetBuffer.GetBuffer(), packetSize) == SOCKET_ERROR)
		{
			ErrorHandling("RecvMessage(): error!", GetLastError());
			getchar();
			exit(1);
		}
		packetBuffer.Commit(packetSize);
		packetBuffer.Read((char*)&packetType, 1);
		packetBuffer.Read(message, packetSize - 1);
		switch(packetType)
		{
			case PACKET_ENTER:
				Log("Enter CSTalk");
				break;
			case PACKET_CHAT:
				Log(message);
				break;
			case PACKET_EXIT:
				break;
			default:
				break;
		}
	}
	return 0;
}
示例#3
0
void TopicSender::sendWithFEC()
{
#if WITH_OPENFEC
	uint16_t msg_id = m_sender->allocateMessageID();
	uint64_t dataSize = sizeof(FECHeader) + m_buf.size();

	// If the message fits in a single packet, use that as the buffer size
	uint64_t symbolSize;
	uint64_t sourceSymbols;

	if(dataSize <= FECPacket::MaxDataSize)
	{
		sourceSymbols = 1;
		symbolSize = dataSize;
	}
	else
	{
		// We need to pad the data to a multiple of our packet payload size.
		sourceSymbols = div_round_up(dataSize, FECPacket::MaxDataSize);
		symbolSize = FECPacket::MaxDataSize;
	}

	ROS_DEBUG("dataSize: %lu, symbol size: %lu, sourceSymbols: %lu", dataSize, symbolSize, sourceSymbols);

	uint64_t packetSize = sizeof(FECPacket::Header) + symbolSize;

	ROS_DEBUG("=> packetSize: %lu", packetSize);

	uint64_t repairSymbols = std::ceil(m_sender->fec() * sourceSymbols);

	uint64_t numPackets = sourceSymbols + repairSymbols;

	of_session_t* ses = 0;
	uint32_t prng_seed = rand();
	if(sourceSymbols >= MIN_PACKETS_LDPC)
	{
		ROS_DEBUG("%s: Choosing LDPC-Staircase codec", m_topicName.c_str());

		if(of_create_codec_instance(&ses, OF_CODEC_LDPC_STAIRCASE_STABLE, OF_ENCODER, 1) != OF_STATUS_OK)
		{
			ROS_ERROR("%s: Could not create LDPC codec instance", m_topicName.c_str());
			return;
		}

		of_ldpc_parameters_t params;
		params.nb_source_symbols = sourceSymbols;
		params.nb_repair_symbols = std::ceil(m_sender->fec() * sourceSymbols);
		params.encoding_symbol_length = symbolSize;
		params.prng_seed = prng_seed;
		params.N1 = 7;

		ROS_DEBUG("LDPC seed: 7, 0x%X", params.prng_seed);

		if(of_set_fec_parameters(ses, (of_parameters_t*)&params) != OF_STATUS_OK)
		{
			ROS_ERROR("%s: Could not set FEC parameters", m_topicName.c_str());
			of_release_codec_instance(ses);
			return;
		}
	}
	else
	{
		ROS_DEBUG("%s: Choosing Reed-Solomon codec", m_topicName.c_str());

		if(of_create_codec_instance(&ses, OF_CODEC_REED_SOLOMON_GF_2_M_STABLE, OF_ENCODER, 0) != OF_STATUS_OK)
		{
			ROS_ERROR("%s: Could not create REED_SOLOMON codec instance", m_topicName.c_str());
			return;
		}

		of_rs_2_m_parameters params;
		params.nb_source_symbols = sourceSymbols;
		params.nb_repair_symbols = std::ceil(m_sender->fec() * sourceSymbols);
		params.encoding_symbol_length = symbolSize;
		params.m = 8;

		if(of_set_fec_parameters(ses, (of_parameters_t*)&params) != OF_STATUS_OK)
		{
			ROS_ERROR("%s: Could not set FEC parameters", m_topicName.c_str());
			of_release_codec_instance(ses);
			return;
		}
	}

	std::vector<uint8_t> packetBuffer(numPackets * packetSize);
	std::vector<void*> symbols(sourceSymbols + repairSymbols);

	uint64_t writtenData = 0;

	// Fill the source packets
	for(uint64_t i = 0; i < sourceSymbols; ++i)
	{
		uint8_t* packetPtr = packetBuffer.data() + i * packetSize;

		FECPacket::Header* header = reinterpret_cast<FECPacket::Header*>(packetPtr);

		header->msg_id = msg_id;
		header->symbol_id = i;
		header->symbol_length = symbolSize;
		header->source_symbols = sourceSymbols;
		header->repair_symbols = repairSymbols;
		header->prng_seed = prng_seed;

		uint8_t* dataPtr = packetPtr + sizeof(FECPacket::Header);
		uint64_t remainingSpace = symbolSize;

		symbols[i] = dataPtr;

		if(i == 0)
		{
			// First packet includes the FECHeader
			FECHeader* msgHeader = reinterpret_cast<FECHeader*>(dataPtr);

			// Fill in header fields
			msgHeader->flags = m_flags;
			msgHeader->topic_msg_counter = m_inputMsgCounter;

			strncpy(msgHeader->topic_name, m_topicName.c_str(), sizeof(msgHeader->topic_name));
			if(msgHeader->topic_name[sizeof(msgHeader->topic_name)-1] != 0)
			{
				ROS_ERROR("Topic '%s' is too long. Please shorten the name.", m_topicName.c_str());
				msgHeader->topic_name[sizeof(msgHeader->topic_name)-1] = 0;
			}

			strncpy(msgHeader->topic_type, m_topicType.c_str(), sizeof(msgHeader->topic_type));
			if(msgHeader->topic_type[sizeof(msgHeader->topic_type)-1] != 0)
			{
				ROS_ERROR("Topic type '%s' is too long. Please shorten the name.", m_topicType.c_str());
				msgHeader->topic_type[sizeof(msgHeader->topic_type)-1] = 0;
			}

			for(int i = 0; i < 4; ++i)
				msgHeader->topic_md5[i] = m_md5[i];

			dataPtr += sizeof(FECHeader);
			remainingSpace -= sizeof(FECHeader);
		}

		uint64_t chunkSize = std::min(remainingSpace, m_buf.size() - writtenData);
		memcpy(dataPtr, m_buf.data() + writtenData, chunkSize);
		writtenData += chunkSize;

		// Set any padding to zero
		if(chunkSize < remainingSpace)
			memset(dataPtr + chunkSize, 0, remainingSpace - chunkSize);
	}

	// Fill the repair packets
	for(uint64_t i = sourceSymbols; i < sourceSymbols + repairSymbols; ++i)
	{
		uint8_t* packetPtr = packetBuffer.data() + i * packetSize;

		FECPacket::Header* header = reinterpret_cast<FECPacket::Header*>(packetPtr);

		header->msg_id = msg_id;
		header->symbol_id = i;
		header->symbol_length = symbolSize;
		header->source_symbols = sourceSymbols;
		header->repair_symbols = repairSymbols;
		header->prng_seed = prng_seed;

		uint8_t* dataPtr = packetPtr + sizeof(FECPacket::Header);
		symbols[i] = dataPtr;
	}
	for(uint64_t i = sourceSymbols; i < sourceSymbols + repairSymbols; ++i)
	{
		if(of_build_repair_symbol(ses, symbols.data(), i) != OF_STATUS_OK)
		{
			ROS_ERROR("%s: Could not build repair symbol", m_topicName.c_str());
			of_release_codec_instance(ses);
			return;
		}
	}

	// FEC work is done
	of_release_codec_instance(ses);

	std::vector<unsigned int> packetOrder(numPackets);
	std::iota(packetOrder.begin(), packetOrder.end(), 0);

	// Send the packets in random order
	unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
	std::mt19937 mt(seed);
	std::shuffle(packetOrder.begin(), packetOrder.end(), mt);

	ROS_DEBUG("Sending %d packets", (int)packetOrder.size());
	for(unsigned int idx : packetOrder)
	{
		if(!m_sender->send(packetBuffer.data() + idx * packetSize, packetSize, m_topicName))
			return;
	}
#else
	throw std::runtime_error("Forward error correction requested, but I was not compiled with FEC support...");
#endif
}