-
Notifications
You must be signed in to change notification settings - Fork 3k
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
nsapi - Standardize support of NSAPI_UNSPEC #2897
Conversation
Part of the problem is the naming has not existing prefix in the enum, to say what enum it is. NSAPI_AF_UNSPEC, NSAPI_AF_IPV4, NSAPI_AF_IPV6 would make sense. "nsapi_version_t" is also horrible, as it's not the version of nsapi_t. It's really nsapi_address_family_t. "Unspec" came from POSIX, where that is the specific code for an unspecified address family. Asking for "None" from a resolution function doesn't make a huge amount of sense. "IP None" makes even less sense - conceptually it isn't necessarily IP. Always seems like a good idea to use standard names for standard concepts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to attempt to add support for UNSPEC in SocketAddress, you really have to extend that to all the actual socket implementations.
This does really not seem like a one-day-after-freeze change.
} else if (_addr.version == NSAPI_IPv6) { | ||
ipv6_to_address(ip_address, _addr.bytes); | ||
ipv6_to_address(_ip_address, _addr.bytes); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make sense. "None/Unspec" in a socket address is not "0.0.0.0" - that could be inferred as a statement that it's IPv4. Suggest "*", which is what you see in inetstat for unbound sockets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering what to return here. I don't think "*" is something users would expect.
"0.0.0.0" does have the benifit that it's compatible with current code and also parsable as an address.
An alternative is to simply return a null pointer, since the representation doesn't really exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure that compatibility with current code or being parsable as such is actually desirable. If you pass "unspec" to someone, do you really want them to silently treat it as if it was IPv4?
It kind of extends the somewhat undesirable behaviour of treating IPv4 0.0.0.0 as NULL and vice versa. (Nanostack had to have a special check to permit IPv4 iff it was 0.0.0.0...) I'd prefer it if binary->text->binary round-tripping preserved value+type. (The stack doesn't do that as much as it used to, but it still can happen).
An unspec SocketAddress is only appropriate to a few quite limited cases - error returns, and bind are all I can currently think of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like a null-pointer from get_ip_address
is reasonable if set_ip_address
accepts this as NSAPI_UNSPEC
.
This strategy would satisfy your concerns with ipv4 as null, round-trip preservation, and forces users to consider NSAPI_UNSPEC
as a special case.
You make a good point. I'll switch back to I agree. This isn't the time socket API changes, but unfortunately NSAPI_UNSPEC was introduced with inconsistent support in the socket API. I understand the motivation for adding the option, but currently most of the socket API has undefined behavior when NSAPI_UNSPEC is passed. This patch attempts to remedy that, and if it doesn't make it in to this next release, at least it is available for the next minor release. |
We did consider working this through - it would be generally useful to have "unspec" in the socket, but we decided to limit the scope to just the gethostbyname for now, and left the comment that it was not applicable to the SocketAddress. We didn't feel we had time to work out the design or consequences for that. I would suggest just blocking the attempt in the few SocketAddress APIs that accept naspi_version_t, if you want to make sure people don't do it. The moment you explicitly allow it in SocketAddress, I'm fairly confident quite a few lwip_stack APIs will go a bit weird. There is an assumption throughout that the SocketAddress being received is IPv4 or IPv6. |
ac36124
to
d7f44f4
Compare
Inconsistent support of
Do you think we should make the SocketAddress treat Alternatively we can update lwip (the EDIT: I've updated lwip with support for |
0314f2f
to
9bbb793
Compare
/morph test |
/morph test |
1d6174a
to
32e0e81
Compare
Result: FAILUREYour command has finished executing! Here's what you wrote!
Outputmbed Build Number: 1049 Test failed! |
The test failure was caused by an issue with the latest version of mbed-ls. mbed-ls was recently updated, however the latest release has an issue detecting NUCLEO boards. This is a regression and is logged here: ARMmbed/mbed-ls#137. I have since pinned mbed-ls in CI to use version 1.2.4, however past PRs may already be affected. All other boards passed, and since this wasn't a nightly, networking tests weren't even run. So should be fine |
Tested locally with K64F, NUCLEO_F429ZI, and NUMAKER_PFM_NUC472 |
Agreed, but this is very much a first pass of non-IPv4 support. I'd argue there's no huge rush to define behaviour here, particularly if it ends up locking in API. If you effectively specify what UNSPEC does in a SocketAddress by implementation now, can we change it later?
My feeling is that lack of unspec was always a mistake, as was treating IPv4 0.0.0.0 as "unset". Ideally unspec takes over from IPv4 0.0.0.0 as the NULL respresentation. So, yes, UNSPEC should be treated as IPv4 0.0.0.0 currently is, but ultimately we should withdraw IPv4 0.0.0.0 from being the default and null value. |
ip_addr_set_zero_ip4(out); | ||
return true; | ||
} | ||
#endif | ||
#endif | ||
|
||
#if LWIP_IPV4 && LWIP_IPV6 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this flopping towards IPV4. Could it at least follow the IPv4/IPv6 preference? Ideally we'd convert to lwip's own IPADDR_TYPE_ANY, but that isn't fully supported in their ip_addr_t either - it's used internally, but I don't believe it's valid for external users.
Jesus, this ifdeffing is confusing. Not sure we can do better though.
@@ -100,25 +90,13 @@ class NetworkStackWrapper : public NetworkStack | |||
return address->get_ip_address(); | |||
} | |||
|
|||
virtual int gethostbyname(const char *name, SocketAddress *address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This removal breaks gethostbyname(literal, UNSPEC) - gethostbyname(version = AF_UNSPEC) doesn't actually work. Need to extend that too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it's worse than that. The original code called the dns library with version omitted, which meant it defaulted to IPv4. (The DNS library does not accept UNSPEC). This now means that you call the DNS library with UNSPEC, which it interprets as "not IPv4, so IPv6". So gethostbyname is now doing AAAA lookups by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does work with LWIP though, because LWIP is providing its own gethostbyname, which does work with AF_UNSPEC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops good catch, should be updated
@@ -215,17 +215,19 @@ void SocketAddress::set_port(uint16_t port) | |||
|
|||
const char *SocketAddress::get_ip_address() const | |||
{ | |||
char *ip_address = (char *)_ip_address; | |||
if (_addr.version == NSAPI_UNSPEC) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So UNSPEC SocketAddress round-trips via NULL string pointer, if I read correctly. Seems fine. But would still vaguely prefer a real string, so users don't have to take care when doing printf("%s", foo->get_ip_address())
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does have the benefit of matching the behaviour of iface->get_ip_address()
when not connected.
int count = 0; | ||
if (a._addr.version == NSAPI_IPv4 && b._addr.version == NSAPI_IPv4) { | ||
count = NSAPI_IPv4_BYTES; | ||
if (a._addr.version == NSAPI_UNSPEC && b._addr.version == NSAPI_UNSPEC) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could check different versions first and return false.
But should UNSPEC be equal to IPv4 0.0.0.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, should be updated to compare equal for "null" ip addresses
32e0e81
to
d6b3cb5
Compare
- Reordered nsapi_version_t to make defaule nsapi_addr_t NSAPI_UNSPEC - Added support to NSAPI_UNSPEC in SocketAddress
d6b3cb5
to
6d9ac9f
Compare
@kjbracey-arm Happy with this patch? |
I think it looks okay, but I'd want @mikaleppanen to cast an eye over it. Does it achieve the wanted results when, say, IP preference is IPv4, but we only have an IPv6 address? Or at least, does it work as well as it currently does? |
Tested this with dual stack configuration and works ok. Looks good to me. |
Standardize support of NSAPI_UNSPEC (renamed to NSAPI_IP_NONE)
Introduced in #2767
cc @sg-, @c1728p9, @kjbracey-arm, @mikaleppanen