-
Notifications
You must be signed in to change notification settings - Fork 75
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
UDP send() does not clear esp32 write buffer #135
Comments
Personal opinion part: I think that more generally the attempt to implement udp traffic under the api designed for tcp is maybe not a great long term solution. The current implementation implements udp with patches on functions originally designed for tcp connections. So it runs This doesn't really align with how UDP actually works as a connectionless protocol. Additionally, because a udp socket calls In the long term it may be good to implement an API specifically for UDP that aligns more with how UDP works to allow users to better take advantage of the strengths UDP. I would be happy to help implement that as well. |
You have hit the nail on the head. Correct on all points. My goal with the original UDP PR #97 was to simply get it working enough for my use case, knowing very little of what the "general" UDP use case would be. Also there were pre-existing stubs in the code labeled as "not implemented", I assumed this was the desired api and just filled it in. I'm not the networking person whatsoever. To get this working in general, it may require changes to both nina-fw as well as this library, but maybe not. WiFiNINA is another client of nina-fw that would need to be kept in sync. Those dependency chains are the reason I didn't want to mess with nina-fw. My recommendation would be as you suggest, to break the interface between tcp and udp. Thus making a separate and more explicit beginPacket / write / endPacket interface. WiFiUdpSendReceiveString would me my canonical example starting place, using the interface in WiFiUdp If you do take this up, I'd be more than happy to lend a set of eyes for code review, though I technically have no power here. |
Yeah I don't think I wrote it down how I had it in my head but the initial patch made a lot of sense as a low-impact way of initially getting some functionality in place.
Oh hey I was actually just about to write something to this extent. yeah this is the big challenge is the question of where to implement the change. I think the cleanest / most efficient solution would involve changes to nina-fw. But putting those things aside for practicality, I do think a proper UDP API can absolutely be implemented purely in esp32spi. I think all of the raw components of the underlying API that you'd need are already exposed:
And all of these are already used on the existing UDP implementation, so we know they work. So it may be possible to implement most or all of an ideal UDP-specific API in terms of these without changing nina-fw, in a way that would also allow future changes to nina-fw to make it better. Basing it on the current WiFiNINA UDP API makes a lot of sense to me, thanks for pointing that out. Something I want to note so I don't forget is I'm happy to write a draft implementation in a PR when I get some time for it. |
That's what I keep telling myself.. |
Ran into this exact problem, unfortunately only found this issue after following all the threads myself.. Given nobody seems to have had the time to fix it in the meantime (totally understandable) maybe it'd be good to at least document this pitfall for now |
@f0x52 you interested in submitting a PR with a warning added to the readme file or documentation? |
This issue also seems to affect UDP server. This UDP server code works: I've tried a number of variations, and it doesn't seem to work to close and re-open the socket before sending, or to create a new socket to send the reply. |
Tested:
returns the same socket number and still sends the old data too. |
Given it's 3 years on now and my life circumstances have changed, I ought to say I'm not likely to find time to write a fix for this. I may be able to help review someone else's PR if they write one. |
Later today, I will try the beta firmware and see if it works or does something different. |
Verified this still happens with the cc @dhalbert |
My Platform:
The problem:
udp.send() appends to the write buffer instead of replacing it. This results in the following behavior:
will actually send
and this continues until the esp32's internal write buffer is full. at which point calls to send() will only send the buffer and not append anything new.
The expected behavior is that a call to
write()
will send the provided data as a datagram packet and nothing else.Why this happens
In the nina-fw WiFiUdp.c implementation we can see the following:
_sndSize
tracks the write buffer size for the current packetbeginPacket()
sets_sndSize
to 0. This is the only place where_sndSize
is set to 0.endPacket()
does not set_sndSize
to 0.The only nina-fw command that calls
beginPacket()
is the startTcpClient() command which, despite the outdated name, is also used to initialize UDP sockets.sendUDPData() only calls
endPacket()
. It does not callbeginPacket()
.socket_write()
has code roughly equivalent (with simplification and no handling of large buffers) to this:_INSERT_DATABUF_TCP_CMD
writes data to the UDP socket buffer, and then_SEND_UDP_DATA_CMD
callsendPacket()
which sends the current buffer as a datagram packet.beginPacket()
is never called during asocket_write()
.Workaround
Currently you can work around this problem by closing and re-opening the socket before every write. So every
write()
now becomesThe
close()
is necessary becauseconnect()
also opens a "server" port for receiving responses, and soconnect()
will fail if that server port is already open.Potential fixes
It's not entirely clear to me whether this is a bug in esp32spi or in nina-fw. Changing esp32spi's
socket_write
to send a_START_SERVER_TCP_CMD
message after sending_SEND_UDP_DATA_CMD
would fix this issue. Changing nina-fw'ssendUDPData()
command to callbeginPacket()
again afterendPacket()
would also solve this issue. So would changing both to add a new command specifically to callbeginPacket()
into nina-fw and using it in esp32wifi.So I'm happy to write a patch to fix this, but I don't know which project i should be writing the patch for.
Example code to cause this problem
The text was updated successfully, but these errors were encountered: