10 Replies Latest reply on Aug 10, 2016 3:48 PM by JackH6

    Problem getting remote IP and port from UDP packet

    dpc27

      Hello,

       

      I am trying to connect an Arduino with a Galileo device.

      For doing so, I am sending a broadcast message, which is correctly received by Galileo device. But when I try to get the Arduino's IP and port from UDP packet, I get 255.255.255.255 and 0.

       

      udp.beginPacket(255.255.255.255, 8888);

       

      I should get the IP SRC and PORT using udp.remoteIP() and udp.remotePort(), instead of the destination IP (255.255.255.255) and port 0.

       

      How can I fix this?

       

      Thanks in advance

        • 1. Re: Problem getting remote IP and port from UDP packet
          JPMontero_Intel

          Could you attach the sketches you are using? So we can replicate the issue

          Regards

          JPMontero_Intel

          • 2. Re: Problem getting remote IP and port from UDP packet
            dpc27

            Sure. Here you have, notice that it's not finished yet

             

            GALILEO

            #include <Ethernet.h>

            #include <EthernetUDP.h>

            #include <Udp.h>

             

            // Enter a MAC address and IP address for your controller below.

            // The IP address will be dependent on your local network:

            int led = 13;

            int blinkMode = 0;

            unsigned int localPort = 8888;              // local port to listen on

            byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEE};

             

            // buffers for receiving and sending data

            char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  //buffer to hold incoming packet,

            char  ReplyBuffer[] = "acknowledged";       // a string to send back

             

            // An EthernetUDP instance to let us send and receive packets over UDP

            EthernetUDP Udp;

             

             

            void setup() { 

              // start the Ethernet and UDP

              startGalileo(); 

              Udp.begin(localPort); 

             

              Serial.begin(9600);

            }

             

            void loop() {

                blinkModes(1);

                Serial.println(Ethernet.localIP());

                newArduino();

             

                // send a reply, to the IP address and port that sent us the packet we received

            //    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());

            //    Udp.write(ReplyBuffer);

            //    Udp.endPacket(); 

            }

             

            void blinkModes(int mode){

              switch(mode){

                case 1:    //everything OK

                  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)

                  delay(1000);               // wait for a second

                  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW

                  delay(1000);               // wait for a second

                  blinkMode=1;

                  break;

                case 0:    //failed at getting IP

                  Serial.println("Failed to configure Ethernet using DHCP");

                  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)

                  delay(1000);               // wait for a second

                  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW

                  delay(100);               // wait for a second

                  blinkMode=0;

                  break;

              }

            }

             

            void startGalileo(){

              pinMode(led,OUTPUT);

              blinkModes(0);

              system("ifup eth0");

              delay(1000);

              blinkModes(Ethernet.begin(mac));

            }

             

            int newArduino(){

              // if there's data available, read a packet

              int packetSize = Udp.parsePacket();

              if(Udp.available()){

                // read the packet into packetBufffer

                Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);

                Serial.println("Contents:");

                Serial.println(packetBuffer);

                Serial.println(Udp.remoteIP());          //here I get 255.255.255.255

                Serial.println(Udp.remotePort());       //here I get 0

                delay(10);

                }

            }

             

            ====================================================

             

            ARDUINO

            #include <SPI.h>

            #include <Ethernet.h>

            #include <EthernetUDP.h>

             

            byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

            IPAddress broadcast(255,255,255,255);

            int led = 9;

            int blinkMode = 0;

            unsigned int localPort = 8888;      // local port to listen on 

            EthernetUDP udp;

            IPAddress remote;

            // buffers for receiving and sending data

            char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  //buffer to hold incoming packet,

            char  ReplyBuffer[] = "acknowledged";       // a string to send back

             

            int brightness=0;

            int fadeAmount=5;

             

            void setup() {

            // Open serial communications and wait for port to open:

              Serial.begin(9600);

              startArduino();   

             

               

              // give the Ethernet shield a second to initialize:

              delay(1000);

             

            //  // if you get a connection, report back via serial:

            //  if (client.connect(server, 80)) {

            //    Serial.println("connected");

            //    // Make a HTTP request:

            //    client.println("GET /index.html HTTP/1.1");

            //    client.println("Host: http://192.168.1.34");

            //    client.println("Connection: close");

            //    client.println();

            //  }

            //  else {

            //    // kf you didn't get a connection to the server:

            //    Serial.println("connection failed");

            //  }

            }

             

            void loop(){

              blinkModes(1);

              connectGalileo();

              int packetSize = udp.parsePacket();

              if(packetSize){

                Serial.print("Received packet of size ");

                Serial.println(packetSize);

                Serial.print("From ");

                remote = udp.remoteIP();

                for (int i =0; i < 4; i++){

                  Serial.print(remote[i], DEC);

                  if (i < 3){

                    Serial.print(".");

                  }

                }

                Serial.print(", port ");

                Serial.println(udp.remotePort());

             

                // read the packet into packetBufffer

                udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);

                Serial.println("Contents:");

                Serial.println(packetBuffer);

             

                // send a reply, to the IP address and port that sent us the packet we received

                udp.beginPacket(udp.remoteIP(), udp.remotePort());

                udp.write(ReplyBuffer);

                udp.endPacket();

              }

              delay(10);

            }

             

            void blinkModes(int mode){

              switch(mode){

                case 1:    //everything OK

                  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)

                  delay(1000);               // wait for a second

                  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW

                  delay(1000);               // wait for a second

                  blinkMode=1;

                  break;

                case 0:    //failed at getting IP

                  Serial.println("Failed to configure Ethernet using DHCP");

                  analogWrite(led,brightness);

                  brightness=brightness+fadeAmount;

                  if(brightness == 0 || brightness == 255)

                    fadeAmount=-fadeAmount;

                  delay(30);

                  blinkMode=0;

                  break;

              }

            }

             

            void startArduino(){

              pinMode(led,OUTPUT); 

              while(Ethernet.begin(mac)==0){   

                blinkModes(0);

              }

            }

             

            void connectGalileo(){

              Serial.println("Trying to connect to Galileo...");

              Serial.println(Ethernet.localIP());

              Serial.println(udp.remotePort());

              udp.begin(localPort);

              udp.beginPacket(broadcast, localPort); 

              udp.println(Ethernet.localIP());

              udp.endPacket();

              delay(100);

            }

            • 3. Re: Problem getting remote IP and port from UDP packet
              dpc27

              No any suggestions?

               

              I just need the remote IP and PORT from the received UDP packet, that's all...

              • 4. Re: Problem getting remote IP and port from UDP packet
                JPMontero_Intel

                Hi dpc27

                I believe there might be a bug in the UDP library, we will investigate this. But we successfully transferred a UDP file from one Galileo to another by using python. I’d recommend you to use python in the Linux side of Galileo.
                Regards
                JPMontero_Intel

                • 5. Re: Problem getting remote IP and port from UDP packet
                  dpc27

                  Hi JPMontero_Intel

                   

                  Yes, there is a bug in the EthernetUDP library.

                   

                  Meanwhile the Arduino's library is calling the function "recvfrom" in parsePacket() to get all the information, Galileo's library isn't.

                  Instead, it is called in function read(), but with parameter value NULL where should be the struct for the remote address. This is why it doesn't get any address from the packet.

                  In order to follow the same programming scheme, I think that recvfrom should be called from parsePacket() instead from read().

                   

                  I am trying to fix it by my own and I will post the solution once it works, but I would appreciate a little bit of help

                  • 6. Re: Problem getting remote IP and port from UDP packet
                    dpc27

                    Adding these lines, you are able to get the remote IP with IPAddress format, but I am having problems because using recvfrom freezes the execution program...

                    In order to not read the packet and only get the IP, I tried to give NULL and 0 as parameters, but it still freezes...

                     

                    struct sockaddr_in remoteIP;

                    socklen_t size=sizeof(struct sockaddr_in);

                     

                    int aux=recvfrom(_sock, NULL, 0, 0,(struct sockaddr*) &remoteIP, &size);

                    _remoteIP=(byte *)inet_ntoa(remoteIP.sin_addr);

                     

                    int EthernetUDP::available() {

                    struct pollfd ufds;

                      int ret = 0;

                      extern int errno;

                      int    timeout = 0; // milliseconds

                      struct sockaddr_in remoteIP;

                      socklen_t size = sizeof(struct sockaddr_in);

                      unsigned char bufferAux[500];

                     

                      if (_sock == -1)

                      return 0;

                     

                      ufds.fd = _sock;

                      ufds.events = POLLIN;

                      ufds.revents = 0;

                     

                      ret = poll(&ufds, 1, timeout);

                      if ( ret < 0 ){

                      trace_error("%s error on poll errno %d", __func__, errno);

                      return 0;

                      }

                      if( ret == 0)

                      return 0;

                     

                      // only return available if bytes are present to be read

                      if(ret > 0 && ufds.revents&POLLIN){

                      int bytes = 0;

                      ret = ioctl(_sock, FIONREAD, &bytes);

                     

                      int aux=recvfrom(_sock, NULL, 0, 0,(struct sockaddr*) &remoteIP, &size);     //freezes the execution

                      _remoteIP=(byte *)inet_ntoa(remoteIP.sin_addr);

                     

                      if ( ret < 0){

                      trace_error("ioctl fail on socket!");

                      return 0;

                      }

                      if ( ret == 0 && bytes != 0){

                      return bytes;

                      }

                      }

                      return 0;

                    }

                    • 7. Re: Problem getting remote IP and port from UDP packet
                      dpc27

                      Hello again!

                       

                      Finally I found the problem:

                      When we call recvfrom, the message is "read" from the system, and will not be there anymore, so we were able to get the remote IP but not the message.

                      So in order to get the IP and don't destroy the message, we can add the flag MSG_PEEK to recvfrom, and the message will be intact, waiting to be read.

                       

                      This solution maintains your code scheme and is very simple, we just need to add couple of lines to the existing code:

                       

                      int EthernetUDP::available() {

                        struct pollfd ufds;

                        int ret = 0;

                        extern int errno;

                        int    timeout = 0; // milliseconds

                        struct sockaddr_in remoteIP;     //struct to save the remote IP

                        socklen_t size;                           //size of sockaddr, needed for getting the IP from sockaddr, will save the size of the remote IP

                       

                        if (_sock == -1)

                        return 0;

                       

                        ufds.fd = _sock;

                        ufds.events = POLLIN;

                        ufds.revents = 0;

                       

                        ret = poll(&ufds, 1, timeout);

                        if ( ret < 0 ){

                        trace_error("%s error on poll errno %d", __func__, errno);

                        return 0;

                        }

                        if( ret == 0)

                        return 0;

                       

                        // only return available if bytes are present to be read

                        if(ret > 0 && ufds.revents&POLLIN){

                             size=sizeof(struct sockaddr);

                             int bytes = 0;

                             ret = ioctl(_sock, FIONREAD, &bytes);

                             recvfrom(_sock, NULL, 0, MSG_PEEK ,(struct sockaddr*) &remoteIP, &size);   //call to recvfrom with MSG_PEEK to get the remote IP and don't destroy the message

                             _remoteIP=(byte *)inet_ntoa(remoteIP.sin_addr);                                            //saving ip in _remoteIP library variable

                             if ( ret < 0){

                                  trace_error("ioctl fail on socket!");

                                  return 0;

                             }

                             if ( ret == 0 && bytes != 0){

                                  return bytes;

                             }

                        }

                        return 0;

                      }

                       

                      Hope you like my solution and maybe could be added into your next upgrade

                       

                      Thanks,

                       

                      David

                      2 of 2 people found this helpful
                      • 8. Re: Problem getting remote IP and port from UDP packet
                        JackH6

                        remoteIP() now works! Thank you. However, remotePort is still returning 0. Is there something else I need modify?

                        • 9. Re: Problem getting remote IP and port from UDP packet
                          dpc27

                          Sure,

                           

                          at the end I used this solution instead of the one marked before. I forgot to update it.

                           

                          int EthernetUDP::read(unsigned char* buffer, size_t len){

                               if (_remaining > 0) {

                                    int got;

                                    //***********************************

                                    struct sockaddr_in _saddr;

                                    socklen_t _saddr_len= sizeof (struct sockaddr_in);

                                    //***********************************

                                    if (_remaining <= len) {

                                         // data should fit in the buffer

                                         got = recvfrom(_sock, buffer, _remaining, 0, (struct sockaddr *)&_saddr, &_saddr_len);

                                    } else {

                                    // too much data for the buffer, grab as much as will fit

                                    got = recvfrom(_sock, buffer, len, 0, (struct sockaddr *)&_saddr, &_saddr_len);

                                    }

                                    if (got > 0) {

                                    //***********************************

                                    _remoteIP = ntohl(_saddr.sin_addr.s_addr);

                                    _remotePort = ntohs(_saddr.sin_port);

                                    //***********************************

                                    _remaining -= got;

                                    return got;

                                    }

                               }

                          // If we get here, there's no data available or recv failed

                          return -1;

                          }

                           

                          Notice the fix is at read function, not available

                          1 of 1 people found this helpful
                          • 10. Re: Problem getting remote IP and port from UDP packet
                            JackH6

                            It works! Thank you so much.