0
votes

I am writing a C program using GTK+ on a raspberry pi. There is a device coupled to it via the Ethernet port (all UDP communication). This device sends a heartbeat to the pi , which I'm able to receive. Now I need to send something back to the device. Therefore I need to know its IP address. I want my program to autodetect the IP address from the message, but I have no clue how to get it. Here is the code to setup the socket:

  gd->gXctlServer = G_SOCKET_ADDRESS(g_inet_socket_address_new(g_inet_address_new_any(G_SOCKET_FAMILY_IPV4),XCTLPORT));
  gd->gXctlSocket = g_socket_new(G_SOCKET_FAMILY_IPV4,G_SOCKET_TYPE_DATAGRAM,G_SOCKET_PROTOCOL_UDP,&err);
  if (gd->gXctlSocket == NULL)
  {
    g_print("Error creating Xctl socket: %s\n",err->message);
    g_assert(err == NULL);
  }
  if (g_socket_bind(gd->gXctlSocket,gd->gXctlServer,TRUE,&err) == FALSE)
  {
    g_print("Error binding Xctl socket:%s\n",err->message);
    g_assert(err == NULL);
  }

  // add receiver watch for Xctl messages:
  gd->xctlChannel = g_io_channel_unix_new(g_socket_get_fd(gd->gXctlSocket));
  // set channel encoding to NULL for binary data:
  g_io_channel_set_encoding(gd->xctlChannel,NULL,&err);
  if (err != NULL) g_print("error setting encoding: %s\n",err->message);
  gd->xctlRrcvEvent = g_io_add_watch(gd->xctlChannel,G_IO_IN,(GIOFunc) xctlreceiver, NULL);
  g_io_channel_unref(gd->xctlChannel);

gd is a pointer to some global data, among which the server, socket and channel

Here is the code of my listener:

// this function listens to all Xctl messages
static gboolean xctlreceiver(GIOChannel *channel, GIOCondition condition, gpointer data)
{
  char buf[1024];
  gsize read;
  GError *err = NULL;
  g_print("xctlreceiver\n");

  if (condition & G_IO_HUP) return FALSE;

  g_io_channel_read_chars(channel,buf,sizeof(buf),&read,&err);
  if (err != NULL) g_print("error receiving xctl: %s\n",err->message);
  g_print("received %d bytes\n",read);
  if (isXtouchHeartbeat(buf,read))
  {
    g_print("received heartbeat from X-touch\n");
  }
  return TRUE;
}

The receiver is working and indicates that the heartbeat is received. But the question is: How do I get the IP address of the device that sent me the heartbeat. Can someone please help me out here? Thanks, Bart.
EDIT: The solution may be simpler than I thought. Maybe I do not need to know the IP address of the sender. If I use the function g_io_channel_write_chars and I use the same channel as in the g_io_channel_read_chars function, it might work.
I will try this and will come back to it later.

1

1 Answers

0
votes

I found a solution to my problem
My receiver function now looks like this:

static gboolean xctlreceiver(GIOChannel *channel, GIOCondition condition, gpointer data)
{
  char buf[1024];
  gsize read;
  GError *err = NULL;
  g_print("xctlreceiver\n");
  GSocketAddress *addr;

  if (condition & G_IO_HUP) return FALSE;

  if (gd->connectedToController == -1)
  {
    read = g_socket_receive_from(gd->gXctlSocket,&gd->gXctlController,buf,sizeof(buf),NULL,&err);    
    g_print("received %d bytes from XCTL socket on address %s\n",read,g_inet_address_to_string(g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(gd->gXctlController))));
    for (int i=0; i<read; i++)
    {
      g_print("0x%02X ",buf[i]);
    }
    g_print("\n");
    if (isXtouchHeartbeat(buf,read))
    {
      g_print("received heartbeat from X-touch\n");
      gd->connectedToController = 1;
      sendXtouchHeartbeat(NULL);
      g_timeout_add_seconds(2,sendXtouchHeartbeat,NULL);

    }
  }
  else
  {
    g_io_channel_read_chars(channel,buf,sizeof(buf),&read,&err);
    if (err != NULL) g_print("error receiving xctl: %s\n",err->message);
    g_print("received %d bytes from XCTL channel\n",read);
    if (gd->connectedToController == -1)
    {
      //g_print("X-touch found on ip address: %s\n",inet_ntoa(si_recv.sin_addr));
      gd->connectedToController = 1;
    }

  }
  return TRUE;
}

The function g_socket_receive_from gives me the address of the sender in the second argument.
I put it into my gd struct, for later use. Hope this helps anyone with the same problem.
Kr,
Bart.