1

I've been struggling with this for almost 2 weeks now and I think it's time for me to ask for help.

I need to get data from a server running on a fpga. The server has been written by someone who's unfortunately no longer working with us. Though the server works as expected because when I send a request I can see with wireshark the expected content. Wireshark is running on the computer that executes the c++ udp client.

The five first lines (1..5) in the table are the ones I send. Every other lines, out of ICMP ones, are sent by the server. The server send messages over multiple ports according to the type of message. I think sending data is properly working otherwise I would not get line 6 to xxx.

The problem is that my client never receives anything. The handler is never triggered and I can't find why.

Can you please help me one this one.

Thank you very much for your time.

Olivier

"No." "Source" "Destination" "Protocol" "Length" "Info" "port"
"1" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "1"
"2" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "2"
"3" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "3"
"4" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "4"
"5" "192.168.0.254" "192.168.0.1" "UDP" "50" "44702 → 5 Len=8" "5"
"6" "192.168.0.1" "192.168.0.254" "UDP" "60" "50000 → 32776 Len=8" "6"
"7" "192.168.0.1" "192.168.0.254" "UDP" "74" "51000 → 32776 Len=32" "7"
"8" "192.168.0.254" "192.168.0.1" "ICMP" "102" "Destination unreachable (Communication administratively filtered)" "8"
"9" "192.168.0.1" "192.168.0.254" "UDP" "466" "52000 → 32776 Len=424" "9"
"10" "192.168.0.254" "192.168.0.1" "ICMP" "494" "Destination unreachable (Communication administratively filtered)" "10"
"12" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "12"
"13" "192.168.0.254" "192.168.0.1" "ICMP" "502" "Destination unreachable (Communication administratively filtered)" "13"
"14" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "14"
"15" "192.168.0.254" "192.168.0.1" "ICMP" "502" "Destination unreachable (Communication administratively filtered)" "15"
"17" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "17"
"18" "192.168.0.254" "192.168.0.1" "ICMP" "502" "Destination unreachable (Communication administratively filtered)" "18"
"19" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "19"
"20" "192.168.0.254" "192.168.0.1" "ICMP" "502" "Destination unreachable (Communication administratively filtered)" "20"
"22" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "22"
"23" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "23"
"24" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "24"
"25" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "25"
"26" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "26"
"27" "192.168.0.1" "192.168.0.254" "UDP" "474" "52000 → 32776 Len=432" "27"
#include "udp_client.hxx"
#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
//#include <thread>
#include <boost/bind/bind.hpp>
#include <boost/asio.hpp>
#include <ctime>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "udp_constants.hxx"
using  boost::asio::ip::udp;

udp_client::udp_client(boost::asio::io_context &io) :
  io(io),
  socket(io)
{
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x01, 0x00, 0x7a, 0x11, 0xfe});
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x02, 0x00, 0x7a, 0x11, 0xfe});
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05});
  datagrams.push_back(std::vector<unsigned char>{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
  filename="/home/lemaire/data.dat";
  set_acquisition_and_get_data(datagrams);
}


udp_client::~udp_client()
{
  socket.close();
  // close file
  output_stream.close();
  // inform user
  std::cout << "udp server destructor" << std::endl;
}


std::vector<unsigned char> udp_client::ui64_to_vector(uint64_t w)
{
  std::vector<unsigned char> vec(8, 0x0);
  char c;
  size_t d{0};
  for(int i{0}; i<8; i++)
  {
    d = (8-1-i)*8;
    c = static_cast<unsigned char>(w >> d);
    vec[i] = c;
  }
  return vec;
}

bool udp_client::send_data(std::vector<std::vector<unsigned char>>& datagrams)
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  udp::resolver resolver(io);
  udp::endpoint endpoint_tx =
        *resolver.resolve(udp::v4(),
                          udp_constants::ip::fpga,
                          "5").begin();
  try
  {
    std::cout << "send data" << std::endl;
    socket.open(udp::v4());
    for(auto datagram: datagrams)
      socket.send_to(boost::asio::buffer(datagram), endpoint_tx);
  }
  catch (const boost::system::system_error& e)
  {
    std::cout << e.what() << std::endl;
  }
  socket.close();
  return true;
}

bool udp_client::set_acquisition_and_get_data(std::vector<std::vector<unsigned char>>& datagrams)
{
  std::cout << __PRETTY_FUNCTION__ << " begin" << std::endl;
  send_data(datagrams);
  start_receive();
  return true;
}

void udp_client::start_receive()
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  output_stream.open(filename,
                     std::ofstream::out |
                     std::ofstream::trunc |
                     std::ofstream::binary);
  try {
    socket.open(udp::v4());
  }  catch (std::exception& e) {
    std::cerr << "erreur ouverture: " << e.what() << std::endl;
  }
  receive_data();
  std::cout << __PRETTY_FUNCTION__ << " socket data started" << std::endl;

  return;
}

void udp_client::receive_data()
{
  std::cout << "socket opened: " << socket.is_open() << std::endl;
  socket.async_receive_from
      (boost::asio::buffer(recv_buf),
       endpoint_rx,
       boost::bind(&udp_client::handle_data, this,
                   boost::asio::placeholders::error,
                   boost::asio::placeholders::bytes_transferred));
  std::cout << "async receive from started" << std::endl;
}

void udp_client::handle_data(const boost::system::error_code& error,
                             std::size_t bytes_transferred)
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  if(!error)
  {
    output_stream.write(recv_buf.data(), bytes_transferred);
    receive_data();
  }
  else
  {
    std::cerr << "handle daq start error: " << error.message() << std::endl;
  }
  return;
}
// file: udp_client.hxx 
#ifndef UDP_CLIENT_HXX
#define UDP_CLIENT_HXX
#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
#include <list>
#include <ctime>
#include <string>
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <boost/thread/thread.hpp>
#include <boost/array.hpp>
#include <boost/asio/strand.hpp>
#include <boost/bind/bind.hpp>
using  boost::asio::ip::udp;

class udp_client
{
public:
  udp_client(boost::asio::io_context& io);
  ~udp_client();

  void handle_receive(const boost::system::error_code& error,
                      std::size_t bytes_transferred);
  void start_receive();
  static std::vector<unsigned char> ui64_to_vector(uint64_t);
  bool send_data(std::vector<std::vector<unsigned char>>& datagrams);
  bool set_acquisition_and_get_data(std::vector<std::vector<unsigned char>>& datagrams);
private:
  // strand
  boost::asio::io_context& io;
  std::vector<std::vector<unsigned char>> datagrams;
  std::string filename;
  udp::socket socket;
  udp::endpoint endpoint_rx;
  std::ofstream output_stream;

  boost::array<char, 128> recv_buf;

  std::list<std::vector<char>*> buffer;
  void handle_data(const boost::system::error_code& error,
                   std::size_t bytes_transferred);
  void receive_data();

  const std::string get_data_file_name();
};

#endif // UDP_CLIENT_HXX

// file: main.cxx
#include "udp_client.hxx"
#include <boost/asio.hpp>
#include <signal.h>
#include <chrono>
#include <boost/thread/thread.hpp>
#include <boost/asio/thread_pool.hpp>
int main()
{
  try
  {
    boost::asio::io_context io;
    udp_client client(io);
    boost::thread t{boost::bind(&boost::asio::io_context::run, &io)};
    io.run();
    t.join();
  }
  catch (std::exception& e)
  {
    std::cout << "erreur" << std::endl;
    std::cerr << e.what() << std::endl;
  }
  return 0;
}
sehe
  • 374,641
  • 47
  • 450
  • 633
osfe
  • 61
  • 5
  • Sorry, I forgot to say hello in my message... – osfe Jun 10 '21 at 11:54
  • The good news is, saying hello is [not desired/required](https://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be-removed-from-posts). [SO] is not a forum, but accumulates questions with answers, so we appreciate you being to the point. – sehe Jun 11 '21 at 22:48

2 Answers2

0

Looking at the table of UDP responses (and assuming your C++ programs runs on 192.168.0.254 alright) you should probably bind to port 32776 (which is 0x8008), so e.g. in start_receive:

socket.open(udp::v4());
socket.bind({{}, 0x8008});

That works for me with a simplistic test driver:

netcat -u localhost 32776 -w 0 <<< '01234567'

And that prints e.g.:

bool udp_client::set_acquisition_and_get_data(std::vector<std::vector<unsigned char> >&) begin
bool udp_client::send_data(std::vector<std::vector<unsigned char> >&)
send data
void udp_client::start_receive()
socket opened: true
async receive from started
void udp_client::start_receive() socket data started
void udp_client::handle_data(const boost::system::error_code&, std::size_t)
socket opened: true
async receive from started
void udp_client::handle_data(const boost::system::error_code&, std::size_t)
socket opened: true
async receive from started
...

etc. Also, the data.dat file then contains:

00000000: 3031 3233 3435 3637 0a30 3132 3334 3536  01234567.0123456
00000010: 370a                                     7.
sehe
  • 374,641
  • 47
  • 450
  • 633
  • thank you very much for your answer. I modified my client and the weird thing is that the data coming from the fpga don't trig the handle. But when I send data with nc `echo -ne test | nc -u "192.168.0.254" 32776` it looks like it's working since I enter the handle... – osfe Jun 14 '21 at 13:39
0

I'm so sorry... It was just a firewall issue... I switched the connection from public to trusted zone and now, I receive the data. At least when the client is run standalone (simple udp_client + main). When I try to run it in a qt application, it does not trigger the handle.

osfe
  • 61
  • 5