Skip to content

UDP bidirectional communication not working #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gerardwr opened this issue Apr 11, 2015 · 12 comments
Closed

UDP bidirectional communication not working #64

gerardwr opened this issue Apr 11, 2015 · 12 comments

Comments

@gerardwr
Copy link

Hello Ivan,

The UDP library works OK for unidirectional communication (either as Client or Server).

It does NOT work as expected for bidirectional communication, therefore getting time from an NTP server is not possible.

There was an issue #53 opened, but this was closed without a solution.

Looks like a bug.

Have a look at background findings from various users here:
http://www.esp8266.com/viewtopic.php?f=28&t=2295&hilit=udp
http://www.esp8266.com/viewtopic.php?f=29&t=2390&hilit=udp

Regards,
Gerard.

@tim-in-oakton
Copy link

Apparently nerds of a feather flock together- I just found the same issue -
The root cause appears to be that the UDP lib is ignoring the source port provided:

my router/GW is 2.1, the ESP8266 is at 2.123, the target NTP server was resolved to 129.6.15.30.
ntp port is 123, I told my ESP to originate the packets from port 8888 (with code "unsigned int localPort = 8888;")
The TCPDump below shows my 8266 happily sending out NTP requests from port 4138 instead of the 8888 that I specified... so the replies are going to the bit-bucket instead of my NTP reply parser.

*** How do I raise this specific bug wrt #include <WiFiUdp.h> using the wrong source port?

root@knightswhosayni:~# tcpdump -nvX host 192.168.2.123
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:47:58.717981 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 192.168.2.123 tell 192.168.2.1, length 28
0x0000: 0001 0800 0604 0001 98fc 116b 3d3f c0a8 ...........k=?..
0x0010: 0201 0000 0000 0000 c0a8 027b ...........{
14:47:58.720125 ARP, Ethernet (len 6), IPv4 (len 4), Reply 192.168.2.123 is-at 18:fe:34:9b:f8:ad, length 28
0x0000: 0001 0800 0604 0002 18fe 349b f8ad c0a8 ..........4.....
0x0010: 027b 98fc 116b 3d3f c0a8 0201 .{...k=?....

// OK - looks like ARP is working.... that's a start

14:47:59.718364 IP (tos 0x0, ttl 255, id 52, offset 0, flags [none], proto UDP (17), length 76)
192.168.2.123.4138 > 129.6.15.30.123: NTPv4, length 48 <---- WRONG PORT, DONKEY
Client, Leap indicator: clock unsynchronized (192), Stratum 0 (unspecified), poll 6s, precision -20
Root Delay: 0.000000, Root dispersion: 0.000000, Reference-ID: (unspec)
Reference Timestamp: 0.000000000
Originator Timestamp: 0.000000000
Receive Timestamp: 0.000000000
Transmit Timestamp: 0.000000000
Originator - Receive Timestamp: 0.000000000
Originator - Transmit Timestamp: 0.000000000
0x0000: 4500 004c 0034 0000 ff11 6825 c0a8 027b E..L.4....h%...{
0x0010: 8106 0f1e 102a 007b 0038 4f22 e300 06ec ......{.8O"....
0x0020: 0000 0000 0000 0000 314e 3134 0000 0000 ........1N14....
0x0030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0040: 0000 0000 0000 0000 0000 0000 ............
14:47:59.723823 IP (tos 0x10, ttl 59, id 9403, offset 0, flags [none], proto UDP (17), length 76)
129.6.15.30.123 > 192.168.2.123.4138: NTPv4, length 48
Server, Leap indicator: (0), Stratum 1 (primary reference), poll 6s, precision -29
Root Delay: 0.000000, Root dispersion: 0.000000, Reference-ID: ACTS
Reference Timestamp: 3637745236.119249433 (2015/04/11 12:47:16)
Originator Timestamp: 0.000000000
Receive Timestamp: 3637745279.761269211 (2015/04/11 12:47:59)
Transmit Timestamp: 3637745279.761277019 (2015/04/11 12:47:59)
Originator - Receive Timestamp: 3637745279.761269211 (2015/04/11 12:47:59)
Originator - Transmit Timestamp: 3637745279.761277019 (2015/04/11 12:47:59)
0x0000: 4510 004c 24bb 0000 3b11 078f 8106 0f1e E..L$...;.......
0x0010: c0a8 027b 007b 102a 0038 302a 2401 06e3 ...{.{.
.80*$...
0x0020: 0000 0000 0000 0000 4143 5453 d8d3 9654 ........ACTS...T
0x0030: 1e87 218f 0000 0000 0000 0000 d8d3 967f ..!.............
0x0040: c2e2 8a00 d8d3 967f c2e3 0d40 ...........@

@tim-in-oakton
Copy link

Also - from repetition and trying different ports, it looks like regardless of the originating port specified, that the UDP is allocating a dynamic port from 4096 to (some higher number) -
The following code is roughly what is called-
unsigned int localPort = 8888;
Udp_s.begin(localPort);
Udp_s.beginPacket(address, 123);
Udp_s.write(packetBuffer, NTP_PACKET_SIZE);
Udp_s.endPacket();

the resulting packet originates from some port above 4096 (and the reply comes back to that same bogus port).

Any ideas?

@gerardwr
Copy link
Author

@tim-in-oakton That's excellent additional information for IGRR to get this thing sorted. He's probably the only one to get to the bottom of this.

@gerardwr gerardwr reopened this Apr 11, 2015
@tim-in-oakton
Copy link

For what it's worth (haven't been a C jockey since 1990, muscles are weak and flabby.....), It looks like the originating port info is tight through the code that I can read - in the UdpContext there is a call made to udp_bind which appears to be supported via a precomplied binary called "liblwip.a" .

The call made to udp_bind passes three parameters -
err_t err = udp_bind(_pcb, &addr, port);
and the application interface in udp.h says:
err_t udp_bind (struct udp_pcb *pcb, ip_addr_t *ipaddr,
u16_t port)ICACHE_FLASH_ATTR;

It looks like the right origination port info is making it to the call to the lib, maybe it's getting after this point...

@tim-in-oakton
Copy link

One more small observation as I try to hack something workable -
the outgoing port are dynamically picked starting at 4096, incrementing by one each time I call on NTP.
If I pick port 4100 as the localport that the system SHOULD send from, the dynamically assigned ports "skip" 4100 - they go 4097, 4098, 4099, 4101 -
SO - my request to use port 4100 IS being heard, the port is taken out of the "free pool", but the call to send a UDP packet is apparently dynamically allocating every time instead of using the requested port -

HTH!
tim-in-oakton (who will have an 8266 wifi kegerator talking to the AWS cloud shortly!)

@igrr
Copy link
Member

igrr commented Apr 11, 2015

hold on guys, I'm on it...

@igrr
Copy link
Member

igrr commented Apr 11, 2015

Yay!
NTP works now

Connecting to BestWestern
scandone
scandone
.add 0
aid 7
pm open phy_2,type:2 0 0
cnt 

connected with BestWestern, channel 1
dhcp client start...
................ip:172.16.15.123,mask:255.255.252.0,gw:172.16.12.1
.
WiFi connected
IP address: 
172.16.15.123

Starting connection to server...
0
48
packet received
Seconds since Jan 1 1900 = 3637759328
Unix time = 1428770528
The UTC time is 16:42:08
0

Now just a small cleanup and I'll push the fix.

@gerardwr
Copy link
Author

Good show Ivan!

Could you share the code snippet too?

Greetings,
Gerard.

@tim-in-oakton
Copy link

WOW!  You Rock Ivan!!

On 4/11/2015 12:44 PM, Ivan Grokhotkov
  wrote:


  Yay!
    NTP works now
  Connecting to BestWestern

scandone
scandone
.add 0
aid 7
pm open phy_2,type:2 0 0
cnt

connected with BestWestern, channel 1
dhcp client start...
................ip:172.16.15.123,mask:255.255.252.0,gw:172.16.12.1
.
WiFi connected
IP address:
172.16.15.123

Starting connection to server...
0
48
packet received
Seconds since Jan 1 1900 = 3637759328
Unix time = 1428770528
The UTC time is 16:42:08
0

  Now just a small cleanup and I'll push the fix.
  —
    Reply to this email directly or view
      it on GitHub.

@igrr igrr closed this as completed in 00247bb Apr 11, 2015
@gerardwr
Copy link
Author

@igrr Does the fix also apply to the beginMulticast procedure?

igrr added a commit that referenced this issue Oct 29, 2015
UdpClient used to create a new socket for each begin/beginPacket call. This made bidirectional communication impossible.
Fix #64, fix #53.
@alfonsohera
Copy link

I'm having a related problem. I have two sketches running on two different ESP's.
Sketch1 is mostly @gerardwr 's bidirectional communication sketch. Tested with Packet Sender, it works. If I upload this sketch to my other ESP it also behaves as expected after sending a multicast packet from Packet sender.
Sketch2 is my attempt at having a bidirectional communication between 2 (or more if available) ESP's . It basically sends a multicast message to the network, waits for a reply, and sends an acknowledge to the reply. Sketch1 is running on 1 ESP1, and Sketch2 is running in another ESP2. The problem is that the multicast message sent by ESP2 is received by ESP1, but no reply is sent by ESP1. I have debugged the transactions with wireshark and no reply is sent from ESP1 to ESP2, even though if I send a multicast from my PC using Packet Sender, ESP1 replies automatically to it.
ESP1: 192.168.0.150
ESP2: 192.168.0.184
PC: 192.168.0.151
image

Sketch1

void setup() {
.
.
.
Udp.beginMulticast(WiFi.localIP(),ipMulti,localPort);
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}

void loop()
{
  int packetSize = Udp.parsePacket();
  // Serial.println(packetSize);
  if (packetSize)
  {
    int len = Udp.read(packetBuffer, 255);
    if (len > 0) packetBuffer[len] = 0;
    Serial.println(packetBuffer);

    //Unicast response to sender
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write("ESP-");
    Udp.print(ESP.getChipId(),HEX);
    Udp.print(":");
    Udp.print(WiFi.localIP());
    Udp.endPacket();

  }

Sketch2

void loop()
{
  Serial.println("Sending UDP multicast packet");
  //Sending a multicast packet
  Udp.beginPacketMulticast(ipMulti, portMulti,WiFi.localIP());
  Udp.write("UDP Multicast packet sent by ");
  Udp.print(WiFi.localIP() );
  Udp.endPacket();
  Udp.stop();
  //set port to listen to multicast packets
  Serial.println("Waiting for response");
  Udp.beginMulticast(WiFi.localIP(),ipMulti,portMulti);
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.println("Response received");
    int len = Udp.read(packetBuffer, 255);
    if (len > 0) packetBuffer[len] = 0;
    Serial.println(packetBuffer);
    //Unicast response to sender
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write("Response to packet received");
    Udp.endPacket();
  }

  delay(1000);
}

I have doubts on my implementation on sketch2. Is it ok? @igrr

@alexnieva
Copy link

@alfonsohera Hi Alfonso, did you ever get this to work? I'm having the same problem trying to make a bidirectional UDP communication between two ESPs. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants