Multicast - recvfrom()

Discussion to talk about software related topics only.
Post Reply
stephan
Posts: 10
Joined: Fri Feb 26, 2010 1:58 am
Location: Germany

Multicast - recvfrom()

Post by stephan »

Hello again,

as far as I understand, for multicast there is currently only an OS_FIFO available to receive multicast UDP messages. The problem with this is, that I am not able to use select() to wait for multiple I/O streams. As far as I discovered, I have to create a custom I/O driver using file descriptors as it is explained in section 16.2 in the programmers guide. As far as I figured out, the UDP socket code does exactly the same. My UDP socket had the socket 37 according to the programmers guide it is for TCP
5 – 37 for TCP (32 in total)
Is possible that TCP only uses the sockets from 5 to 36? Then they are 32 in total ;)

Back to the multicast select() problem:
The last entry point in the multicast packet handling is the MULTICastProcessFunction *pMultiCastFunc FAST_IP_VAR; callback handler, am I right? Then I have to copy MultiProcessFunc() function from multicast.cpp and modify it, so that is calls my multicast processing function instead of the default process_mcudp(). My function must be similar to the process_udp() function, where after posting the packet to the appropriate fifo the notification "activates" the file descriptor with SetDataAvail().

Does anyone implemented it already or has a better idea? Any comments?

Stephan
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: Multicast - recvfrom()

Post by pbreed »

You can use the same FIFO over and over to register for as many UDP or multicast listeners as you want.

The limit is UDP_DISPATCH_SIZE total UDP receivers, this is a constant in constants.h
If you change it rebuild the system. (defaults to 10)


You can alo use the udp socket stuff to use select with udp.
The function int CreateRxUdpSocket(WORD listening_port);
Actually uses a FIFO down inside, so you could actually add more listeners to that fifo.
You would have to modify the udpsocket.cpp code to do this.

PAul
stephan
Posts: 10
Joined: Fri Feb 26, 2010 1:58 am
Location: Germany

Re: select() for multicast

Post by stephan »

It is not so easy to use select() with multicast. Anyhow, I got it to work and want to share my solution.

First of all the multicast interface just supports to deliver the packets to a fifo. In my application I used a fifo that I am already using for receiving unicast udp packets. Similar to unix sockets, where you have to specify the port and additionally join a multicast group. My function takes the udp file descriptor and the multicast group ip:

Code: Select all

int join_multicast(int fd, IPADDR g_ip) {
  UdpSocketDataSet *pSet = (UdpSocketDataSet *) GetExtraData(fd);
  if (pSet==NULL)
    return -1;
  if (pSet->rxport==0)
    return -2;

  // use my register multicast function
  myRegisterMulticastFifo(g_ip, pSet->rxport, &(pSet->the_fifo));

  return 0;
}
Unfortunately, it is not possible to use the standard RegisterMulticastFifo function. The Problem is, that the multicast delivery function just stores the packet in the fifo and does not notify the select() function. This notification is required for select() to wake up.

The last callback entry point for the multicast packet handling is pMultiCastFunc. First I tried to register my callback function (similar to MultiProcessFunc) and call my version of the process_mcudp() function with the necessary notification. However, this does not works, since the data is stored in static variable inside the multicast.cpp file.

My solution is:
  1. copy the multicast.cpp file
  2. rename the required functions MultiProcessFunc to myMultiProcessFunc, RegisterMulticastFifo to myRegisterMulticastFifo, and UnregisterMulticastFifo to myUnregisterMulticastFifo.
  3. make all other function static to avoid linking problems.
  4. add the notify function declaration
  5. add code for calling the notify function in the process_mcudp function just after OSFifoPost(). For example: notify_fifo(mrecs.pfifo);
  6. in myRegisterMulticastFifo set pMultiCastFunc to myMultiProcessFunc instead of MultiProcessFunc


My notify function searches in all udp fifos if it is the multicast fifo where the packet was posted to and then calls the notifiy function:

Code: Select all

void notify_fifo(OS_FIFO *fifo) {
  register int i = 0;
  for (i = 0; i < UDP_fifos_used; i++) {
    if (udp_fifos[i].pfifo == fifo) {
      printf("udp_fifo found\n");

      if (udp_fifos[i].pNotify) {
        printf("notifing\n");
        udp_fifos[i].pNotify(udp_fifos[i].pfifo, udp_fifos[i].dest_port);
      }

      return;
    }
  }
}
good luck. I hope this helps anybody how wants to use multicast with select().
Stephan
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: Multicast - recvfrom()

Post by pbreed »

Take a look at

int CreateRxUdpSocket(WORD listening_port);


This function creates a udp socket. (that can be used with select read etc...)
Underneath the code is in UdpSocket, it would be pretty easy to modify that function to provide your own
FIFO and or modify it to give you info as to what udp port its actually from.

PAul
stephan
Posts: 10
Joined: Fri Feb 26, 2010 1:58 am
Location: Germany

Re: Multicast - recvfrom()

Post by stephan »

Hi Paul,

I think I do not understand what you want me to say.

As far as I understand the fifo inside the udp socket can only be used for select(), because there is a notify function that is called (see line 1566 in system/udp.cpp) after posting the data in the fifo. In the multicast processing function there is no notify (see line 363 in system/multicast.cpp), the select() will block forever since SetDataAvail() is not called for the file descriptor.

Where am I wrong?

Stephan
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: Multicast - recvfrom()

Post by pbreed »

You are correct. The sockets work for broadcast packets, not multicast.
My error.

Paul
Post Reply