Chat here about code rewrites, mods, etc... with respect to the github project https://github.com/esp8266/Arduino

Moderator: igrr

User avatar
By jwatte
#17105 I'm using WiFiUDP from the Arduino-like wrapper.

For network programming, generally a client will create a local socket, and optionally bind it to a known address.

Then, the client will send many packets from the same socket. If it wasn't already bound to a port, the UDP implementation will bind to a randomly chosen free port, and the socket will then stay bound to that port.

The implementation in WiFiUDP is entirely wrong:

Code: Select allint WiFiUDP::beginPacket(IPAddress ip, uint16_t port)
{
    ip_addr_t addr;
    addr.addr = ip;

    if (_ctx)
        _ctx->unref();
    _ctx = new UdpContext;
    return (_ctx->connect(addr, port)) ? 1 : 0;
}


This will create a new socket, that binds to a new port, for every single packet!

This breaks how UDP is supposed to work, because the other end will call recvfrom() to receive an incoming packet, and then return the response to the IP/port found as the source of that packet. If the ESP8266 has sent another packet to anyone, that port is no longer bound.

Also, if I begin with a port number, the socket should stay bound to that port until I dispose it. Trying to return a datagram that I received on this port should not mysteriously unbind the server and make it unable to receive more datagrams!

Similarly, trying to create a new UDP instance to return packets received from a remote end will break, because the remote end likely has a NAT gateway that expects the return traffic to come from the same IP/port that it sent the data to.
User avatar
By jwatte
#17108 Ha. So I cloned the github version to apply my patch, and someone else already worked around this.
The way it's worked around is by using connect() and disconnect() for each packet.

This is still wrong, because it means that packets coming in from endpoints other than the one currently being sent to are filtered out.
The appropriate implementation would remember the IP and port from beginPacket(), and use the targeted send() function in endPacket().
User avatar
By spacejunkie
#17128 If I understand your question correctly, you are trying to send UDP packets from ESP8266 and expecting them to be sent from the same port every time.

That is not how it is supposed to work on ESP8266 or any computer for that matter. Outgoing packets can leave from any port. In case of TCP the receiver uses the source port to identify the TCP session. In case of UDP, there is no session, there is no response or acknowledgement mechanism at transport layer, so source port is generally not of any use to the receiver.

Source Port is an optional field, when meaningful, it indicates the port
of the sending process, and may be assumed to be the port to which a
reply should be addressed in the absence of any other information. If
not used, a value of zero is inserted.

https://tools.ietf.org/html/rfc768