1

I wrote a small protocol stack to connect to KNX/IP routers. The mechanism is as follows:

  • Discovery_Channel: For discovery the client sends out an UDP/IP packet to multicast address 224.0.23.12. KNX/IP routers listen to this multicast address and reply. The KNX/IP router can potentially be connected to multiple KNX media, so the answer contains a list of services with IP addresses and port, the client can connect to.
  • Communication_Channel: The discovered services from all KNX/IP routers are presented to the user to select which service a connection should be made to.

The problem is that the answer from the KNX/IP routers sometimes doesn't contain a valid IP address, but just 0.0.0.0. In this case I need to take the IP address from where the packet came from. But how can I get this with (non-boost version of) asio?

My code looks like this:

/** client socket */
asio::ip::udp::socket m_socket;

/** search request */
void search_request(
    const IP_Host_Protocol_Address_Information & remote_discovery_endpoint = IP_Host_Protocol_Address_Information({224, 0, 23, 12}, Port_Number),
    const std::chrono::seconds search_timeout = SEARCH_TIMEOUT);

/** search response initiator */
void Discovery_Channel::async_receive_response() {
    /* prepare a buffer */
    m_response_data.resize(256);

    /* async receive */
    m_socket.async_receive(
        asio::buffer(m_response_data),
        std::bind(&Discovery_Channel::response_received, this, std::placeholders::_1, std::placeholders::_2));
}

/** response received handler */
void Discovery_Channel::response_received(const std::error_code & error, std::size_t bytes_transferred) {
    // here the answer provided in m_response_data gets interpreted.
    // @todo how to get the IP address of the sender?

    /* start initiators */
    async_receive_response();
}

So how can I retrieve the IP address of the sender in the Discovery_Channel::response_received method? I basically only have the packet data in m_response_data available.

1 Answers1

2

On datagram sockets you can (should, likely) use async_receive_from.

It takes a reference to an endpoint variable that will be set to the remote endpoint on success.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • But isn't this to receive packets from a known endpoint? I don't know who is answering to my multicast discovery request. – Tobias Lorenz Mar 20 '21 at 13:42
  • @TobiasLorenz no, `sender_endpoint` is an *output* parameter, it will be filled with the sender address (did you read the answer?:) – rustyx Mar 20 '21 at 14:22
  • Ah, ok. Got it. I'll give it a try and hopefully will report success ;-) Thank you both. – Tobias Lorenz Mar 20 '21 at 14:36
  • I still don't get it. The async_receive_from function takes a remote endpoint, ok. But this is a multicast address in my case. The receive handler however has the same signature as with the async_receive function. So still the handler doesn't know from which specific ip address the reply came from. Can you provide an example and how this should work? – Tobias Lorenz Mar 20 '21 at 14:47
  • Ah, you mean the multicast endpoint address will be replaced by the sender ip. Ok, I'll try. – Tobias Lorenz Mar 20 '21 at 14:48
  • Legendary @sehe yet again in action.. – Vega4 Nov 29 '22 at 09:00