Skip to content
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

nanocoap_vfs: add nanocoap_vfs_get() #17937

Merged
merged 4 commits into from
May 24, 2022
Merged

Conversation

benpicco
Copy link
Contributor

@benpicco benpicco commented Apr 13, 2022

Contribution description

This adds a convenience function nanocoap_vfs_get() to download a file from a CoAP server and store it on the local filesystem.

In addition a shell command ncget is provided that makes use of the function.

Testing procedure

Run the tests/nanocoap_cli example. If you are on native you want to enable the vfs_auto_format module to automatically create a file system on the auto-generated virtual storage.

Run aiocoap-fileserver . in e.g. the RIOT root directory.

main(): This is RIOT! (Version: 2022.07-devel-20-g7d76a-nanocoap_vfs)
nanocoap test app
All up, running the shell now
> ls /nvm0
./
../
total 0 files

> ncget coap://[fe80::90a7:a6ff:fe4b:2e32%5]/
/.git
/CODE_OF_CONDUCT.md
/LICENSE
/.github/
/boards/
/dist/
/examples/
/sys/
/build/
/bootloaders/
/core/
/cpu/
/doc/
/drivers/
/makefiles/
/pkg/
/tests/
/.bandit
/.circleci/
/.drone.yml
/.gitattributes
/.gitignore
/.mailmap
/CITATION.cff
/CODEOWNERS
/CODING_CONVENTIONS.md
/CODING_CONVENTIONS_C++.md
/CONTRIBUTING.md
/Kconfig
/LOSTANDFOUND.md
/Makefile
/Makefile.base
/Makefile.dep
/README.md
/SECURITY.md
/Vagrantfile
/doc.txt
/fuzzing/
/kconfigs/
/release-notes.txt
/uncrustify-riot.cfg
/MAINTAINING.md
/keys/
/.murdock
/Makefile.features
/Makefile.include
/coaproot/

> ncget coap://[fe80::90a7:a6ff:fe4b:2e32%5]/LICENSE
> ls /nvm0
./
../
LICENSE	24310 B
total 1 files

> vfs r /nvm0/LICENSE 256
00000000: 2020 2020 2020 2020 2020 2020 2020 2020                  
00000010: 2020 474e 5520 4c45 5353 4552 2047 454e    GNU LESSER GEN
00000020: 4552 414c 2050 5542 4c49 4320 4c49 4345  ERAL PUBLIC LICE
00000030: 4e53 450a 2020 2020 2020 2020 2020 2020  NSE.            
00000040: 2020 2020 2020 2020 2020 2056 6572 7369             Versi
00000050: 6f6e 2032 2e31 2c20 4665 6272 7561 7279  on 2.1, February
00000060: 2031 3939 390a 0a20 436f 7079 7269 6768   1999.. Copyrigh
00000070: 7420 2843 2920 3139 3931 2c20 3139 3939  t (C) 1991, 1999
00000080: 2046 7265 6520 536f 6674 7761 7265 2046   Free Software F
00000090: 6f75 6e64 6174 696f 6e2c 2049 6e63 2e0a  oundation, Inc..
000000a0: 2035 3120 4672 616e 6b6c 696e 2053 7472   51 Franklin Str
000000b0: 6565 742c 2046 6966 7468 2046 6c6f 6f72  eet, Fifth Floor
000000c0: 2c20 426f 7374 6f6e 2c20 4d41 2020 3032  , Boston, MA  02
000000d0: 3131 302d 3133 3031 2020 5553 410a 2045  110-1301  USA. E
000000e0: 7665 7279 6f6e 6520 6973 2070 6572 6d69  veryone is permi
000000f0: 7474 6564 2074 6f20 636f 7079 2061 6e64  tted to copy and

Issues/PRs references

@benpicco benpicco requested review from chrysn and maribu April 13, 2022 22:11
@github-actions github-actions bot added Area: CoAP Area: Constrained Application Protocol implementations Area: network Area: Networking Area: OTA Area: Over-the-air updates Area: sys Area: System Area: tests Area: tests and testing framework labels Apr 13, 2022
@github-actions github-actions bot added the Area: examples Area: Example Applications label Apr 13, 2022
@benpicco benpicco added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed Area: OTA Area: Over-the-air updates labels Apr 13, 2022
@github-actions github-actions bot added the Area: OTA Area: Over-the-air updates label Apr 15, 2022
Copy link
Member

@chrysn chrysn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any plans for nput (cvfs-put, coap upload?) as well?

return -EINVAL;
}

if (_is_dir(url)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is too much relying on the file system semantics -- or whether it's just a practical default, especially as the trailing slash gives no practical local file name anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what if someone tries to download coap://host/path/? If they give an output file name, that might be fully OK (given that host doesn't necessarily have file system semantics). If they do not given an output file name, strrchr(url, '/') later will find the trailing slash, set dst = "/default-data/", and vfs_open will fail to open that as a file for writing.

So I don't see a good reason for that check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean if someone wanted to actually store the resource behind coap://host/path/ instead of doing a directory listing?

I'm not sure, is this really a use case for the shell utility? Maybe I have a narrow view because I only used few CoAP servers, but I thought <path>/ would always give a resource listing, not an actual resource.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's only a directory listing if what is behind that is a file server. If it's a pubsub broker it could be a topic, or on an RD it could be part of lookup. CoAP by itself has no concepts of files and directories, and even when acting as a client that saves data to a file system, we shouldn't make assumptions on the server.

Copy link
Member

@maribu maribu May 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I bet that in every second CoAP implementation a trailing slash would not survive the encoding / parsing process. See https://datatracker.ietf.org/doc/html/rfc7252#section-6.4 for details.

My understanding is that a trailing / should result in an additional empty URI-Path option. But I have the feeling that many implementation will just "normalize" that out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There have been some, but they have been fixed. Servers for HTTP are more lax in that area, but a) CoAP tries to avoid some mistakes HTTP made, and b) unlike in HTTP there is no simple way to redirect to the other form (and serving the same document on can easily cause incorrect outcomes, which is why even the lax HTTP servers redirect).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But would it make sense to store this on the file system?

What do you mean?

My proposal is to simply remove this one check. Then any URI could be ncget'ted. It may make sense to have a check for the (possibly implicit) output file name to not be empty (as the file system error is likely not helpful to the user). Just like wget http://riot-os.org/ -Owebsite.html makes sense, something like ncget coap://temperature.riot-os.org/temperatures/average/vienna/ latest-local.temp can happen.

Copy link
Contributor Author

@benpicco benpicco May 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well right now if you do a ncget on a / path you get a parsed directory listing to stdout for the user's convenience:

> ncget coap://[fe80::90a7:a6ff:fe4b:2e32%5]/core/
/core/include/
/core/cond.c
/core/doc.txt
/core/mbox.c
/core/msg_bus.c
/core/mutex.c
/core/thread_flags.c
/core/Makefile
/core/lib/
/core/msg.c
/core/Kconfig
/core/sched.c
/core/thread.c

If you to a ncget on a 'file' it will be downloaded instead:

ncget coap://[fe80::90a7:a6ff:fe4b:2e32%5]/core/thread.c
Saved as /nvm0/thread.c

unless you specify stdout as the destination

ncget coap://[fe80::90a7:a6ff:fe4b:2e32%5]/core/thread.c -
/*
 * Copyright (C) 2013 Freie Universität Berlin
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @ingroup     core_thread
 * @{
 *
 * @file
 * @brief       Threading implementation 
 …

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well you're interacting with a file server -- but not every server is, and it's part of the flexibility of web protocols that you can. I don't regularly interact with IPSO servers, but IIRC almost all of their resources have trailing slashes.

I don't even object to the default destination of paths with trailing slashes being - (as is implied here), that's a very sensible thing to do. But if a user wanted to save it (eg. because some device makes its most frequently accessed resource available on the empty path), that should not be ruled out.

Copy link
Contributor Author

@benpicco benpicco May 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah then this is a simple change! - cfdd360

@benpicco
Copy link
Contributor Author

Do you have any plans for nput (cvfs-put, coap upload?) as well?

Now that aiocoap-fileserver has write support it's the only logical conclusion 😄

@benpicco benpicco removed the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Apr 29, 2022
@benpicco benpicco added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label May 1, 2022
@maribu maribu added Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines labels May 3, 2022
@maribu
Copy link
Member

maribu commented May 3, 2022

@chrysn do you want to take another look? Otherwise I'd do some testing and (assuming positive outcome) give an ACK.

Copy link
Member

@chrysn chrysn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't do a full check (as maribu already mentioned the pending ACK), but didn't find any blockers; address comments as you deem adequate.

return -EINVAL;
}

if (_is_dir(url)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what if someone tries to download coap://host/path/? If they give an output file name, that might be fully OK (given that host doesn't necessarily have file system semantics). If they do not given an output file name, strrchr(url, '/') later will find the trailing slash, set dst = "/default-data/", and vfs_open will fail to open that as a file for writing.

So I don't see a good reason for that check.

* @returns 0 on success
* @returns <0 on error
*/
int nanocoap_vfs_get(nanocoap_sock_t *sock, const char *path, const char *dst);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whenever there is a pair like this (get vs. get_url), I wonder when to use which, if the use cases overlap or whether there are combinations that would be needed. (For example, can one use an established socket with a URL that has query components, or a Uri-Host component?)

Here it's probably motivated by the duality of nanocoap_sock_get_blockwise and nanocoap_get_blockwise_url, where I should have asked the question earlier.

I'd appreciate a note on when to use which, but maybe there are no good answers until #13827 is through.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nanocoap_vfs_get_url() is just there for convenience to avoid boilerplate in the common case.

The path component (and everything that goes with it) will be parsed the same way for both in nanocoap_sock_get_blockwise().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the path argument is really more path and query? If so, that should be documented (dejavu, I think we've had this somewhere else already.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I just call it query path?

Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only reviewed partially, but since I often forget to complete a review and leave the already provided comments in limbo, I rather click submit now half-way-through.

@benpicco benpicco removed the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label May 17, 2022
@benpicco
Copy link
Contributor Author

Should I squash?

@maribu
Copy link
Member

maribu commented May 24, 2022

Please squash and rebase (:

@benpicco benpicco added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label May 24, 2022
@benpicco benpicco requested a review from fabian18 May 24, 2022 11:28
Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK. Code looks good and I trust the provided testing.

Comment on lines +49 to +50
* @returns 0 on success
* @returns <0 on error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @returns 0 on success
* @returns <0 on error
* @retval 0 success
* @retval <0 error

@benpicco benpicco merged commit 85169fc into RIOT-OS:master May 24, 2022
@benpicco benpicco deleted the nanocoap_vfs branch May 24, 2022 14:10
@chrysn chrysn added this to the Release 2022.07 milestone Aug 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: CoAP Area: Constrained Application Protocol implementations Area: examples Area: Example Applications Area: network Area: Networking Area: OTA Area: Over-the-air updates Area: sys Area: System Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants