-
Notifications
You must be signed in to change notification settings - Fork 2k
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
shell/cord_ep: Add user guidance & prevent accidental crash #18053
Conversation
sys/shell/commands/sc_cord_ep.c
Outdated
@@ -63,6 +63,10 @@ int _cord_ep_handler(int argc, char **argv) | |||
} | |||
if (argc > 3) { | |||
regif = argv[3]; | |||
if (regif[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.
Perhaps it makes sense just to change the command and accept an URI, which we parse with https://doc.riot-os.org/group__sys__uri__parser.html ?
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.
Hm. A reasonable suggestion but should the shell command enforce that the registration interface
is a valid uri?
At the moment the chain of responsibility is:
registration interface
-> defined somewhere in some coap related rfcgcoap_req_init()
-> uses aregistration interface
gcoap_req_init()
-> enforces some bare minimal expectation how aregistration interface
should look like (mostly for programming safety I assume, didn't look deeply at it)cord_ep_register()
-> passes aregistration interface
(without any checks on it, beside a convenience NULL handling) togcoap_req_init()
_cord_ep_handler()
-> callscord_ep_register()
with a user givenregistration interface
(without any checks on it)the user
-> "Generates" aregistration interface
and calls_cord_ep_handler()
with it (maybe with checks, maybe without, users tend to be unreliable 😬)
Given this chain & your proposal, I think I could look up in coap / the rfc how exactly a registration interface
may and or must look like (URI...). After that is clarified (at least for me :p) one should enforce that as close to the rfc as possible (in the chain). One aspect that is important for deciding this is performance / code size etc. E.g. a heavy URI check may not be wanted in 3. gcoap, assuming that only other software interacts with it(but not users). This would delegate that responsibility to 4. cord_ep_register()
.
Enforcing the registration interface
to be compliant with a given uri parser inside the shell command, while the e.g. cord_ep_register()
could perfectly work with a non uri compliant registration interface
, could become confusing.
E.g. A user could find that a given registration interface
works in his/her own code but not in the shell. This is also the reason why I tried to match the assert as close as possible and didn't add any other checks.
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.
Given this chain & your proposal, I think I could look up in coap / the rfc how exactly a
registration interface
may and or must look like (URI...). After that is clarified (at least for me :p) one should enforce that as close to the rfc as possible (in the chain). One aspect that is important for deciding this is performance / code size etc. E.g. a heavy URI check may not be wanted in 3. gcoap, assuming that only other software interacts with it(but not users). This would delegate that responsibility to 4.cord_ep_register()
. Enforcing theregistration interface
to be compliant with a given uri parser inside the shell command, while the e.g.cord_ep_register()
could perfectly work with a non uri compliantregistration interface
, could become confusing.E.g. A user could find that a given
registration interface
works in his/her own code but not in the shell. This is also the reason why I tried to match the assert as close as possible and didn't add any other checks.
As I understand this will always end up being a valid URI. We need to get from the command the RD address (maybe port) pointing to a CoAP endpoint, and CoAP path (i.e. the interface). I think unifying the shell commands through our examples is a big gain, then we don't re-implement parsers each time. My proposal is to merge the argument 2 and 3 (remote and interface) into a single URI.
d34dcdb
to
6a11a81
Compare
The RFC is of little help here -- it only deals in URIs (and not URI references); the argument to cord_ep register is neither. (We could make it a limited URI reference, but #18622 shows it's not there now). Going through a full URI here is one solution, but then it should be applied consistently both here and to the (I think we should also do that for the gcoap example. Doesn't need to be, probably even shouldn't be, in this PR -- setting an example here puts a bit of pressure on the other example). One important distinction is getting a bit lost here, though: With an RD, you can either start with a host (and then perform autodiscovery) or with a resource (like, the user did the discovery, here's the URI to go to). That resource could even be By the way, is this still WIP? |
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.
Looks good; see above for nits and comments.
If you remove the WIP and declare it done from your side, I think this can go in.
sys/shell/cmds/cord_ep.c
Outdated
if (uri_result.ipv6addr == NULL) { | ||
puts("error: Only ipv6 addresses are supported"); | ||
return 1; | ||
} | ||
|
||
sock_udp_ep_t remote; | ||
if (make_sock_ep(&remote, argv[2]) < 0) { | ||
printf("error: unable to parse address\n"); | ||
remote.family = AF_INET6; | ||
remote.netif = SOCK_ADDR_ANY_NETIF; | ||
if (!ipv6_addr_from_buf((ipv6_addr_t *)&remote.addr.ipv6, uri_result.ipv6addr, | ||
uri_result.ipv6addr_len)) { | ||
puts("error: IPv6 address malformed"); | ||
return 1; | ||
} | ||
if (argc > 3) { | ||
regif = argv[3]; | ||
|
||
if (uri_result.port == 0) { | ||
remote.port = COAP_PORT; | ||
} | ||
else { | ||
remote.port = uri_result.port; | ||
} |
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 could go into a helper function (possibly part of the URI parsing module) that extracts a sock_udp_ep_t
from a parsed URI (being provided a default port).
(Then, also, that'd be a unified place where handling DNS names could be done, or legacy IP versions could be handled if anyone cared).
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.
Pssssst 🤫 you are leaking my secret plans for the uri parser.
I'm going to move the uri_parser discussion in separate issue. :)
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.
Fine with me; all the more reason to get this done, so you can follow up, and #18622 will become easy :-)
What ever we do, I strongly suggest to unify the ux/ui - as already pointed out by Leandro. "I think unifying the shell commands through our examples is a big gain, then we don't re-implement parsers each time."
😈
Don't forget that
Yes! Since this file is now outdated. I would have fixed it yesterday but sadly this part of riot is either completely undocumented or I couldn't find documentation about it. This caused me to waste so much time on getting this "test" to run & understand that I lost motivation and called it a day.... |
6a11a81
to
d73ef97
Compare
I did indeed miss it. It's good to have it around so users are able to introspect what's happening -- and if I understand your sentiment right, things will still Just Work especially for users who don't provide a path and get auto-discovery.
I feel this, riotctl is a cluster of things (configuration? building? CLI abstraction?) that I don't get myself either, and only fix superficially whenever something breaks. Before you get stuck, don't hesitate to ping is authors for help. Tests should keep software good, but not at the cost of keeping it from getting better. |
d73ef97
to
b83dce0
Compare
I don't think that RD registration via CoAPS was ever tested with this
implementation. (And how would it have been set -- it never took an
indictor).
Just working for `coap` initially is probably a good start. Once not
only the set-the-socket-from-the-parsed-URI but also its caller,
prepare-the-request-from-the-parsed-URI (which passes in the default
port) are factored out, we can still think of those.
|
b83dce0
to
14087a0
Compare
One more request before I ACK this: Please ensure the commit message is current; I suggest something like "shell/cord_ep: Take full URIs instead of IP and path" / / "This fixes a crash when the path was not entered with a leading slash." [note to self: And then there's the case of riotctrl_shell/tests that I have no clue how to go about other than pinging people on Matrix] |
Having spent some time with the riotctrl_shell/cord_ep, I don't think that file needs changes. Given that it does nothing to abstract, and where it does (by naming arguments) it does wrongly (it says "uri", which is correct now but wasn't correct before), it can stay as it is, and its callers will need to adjust. As the release tests are maintained out-of-tree, this will only happen after this PR is in. (It may also happen to be practical to just move this test in-tree). |
This fixes a crash when the path was not entered with a leading slash.
14087a0
to
3dc3110
Compare
Ping @chrysn - |
Thanks for fixing this! |
The argument regif was removed from the shell command in RIOT-OS#18053, so there is not much need to keep it in the ShellInteraction for that command.
The argument regif was removed from the shell command in RIOT-OS#18053, so there is not much need to keep it in the ShellInteraction for that command.
Contribution description
cord_ep
cord_ep register
just slightly wrong, an assertion in gcoap.c would get triggered - resulting in a RIOT kernel panic.Testing procedure
For reproducing the bug do:
RIOT/examples/cord_ep/
and runmake all flash term
for a board of your choicecord_ep register [fd00::1]:1234 foo
(the exact host:port combination does not matter, just have to be valid)foo
) does not start with a/
*** RIOT kernel panic: FAILED ASSERTION.
After applying my suggested fix:
RIOT/examples/cord_ep/
and runmake all flash term
for a board of your choicecord_ep register [fd00::1]:1234 foo
(the exact host:port combination does not matter, just have to be valid)foo
) does not start with a/
error: registration interface must start with '/'